ソースを参照

feature(督办): 督办对接钉钉审批

likai 2 年 前
コミット
245392b99b

+ 19 - 0
opms_parent/app/handler/dingtalk/ding_event.go

@@ -259,6 +259,25 @@ func (h *DingHandler) handleBpmsInstanceChange(msg *message.MixMessage, ctx *din
 			return err.Error()
 		}
 		return "success"
+	case model.PlatTaskApproval:
+		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
+			srv, err := platServer.NewTaskService(ctx.SubsMessage.Ctx)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+			err = srv.AddTaskApproval(instance, msg)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+		}
+		err = s.Update(instance, msg)
+		if err != nil {
+			glog.Error(err)
+			return err.Error()
+		}
+		return "success"
 	}
 
 	// 以下的代码需要调用钉钉接口查询数据,并且以下接口需要审批实例的数据

+ 6 - 2
opms_parent/app/handler/plat/task.go

@@ -30,6 +30,7 @@ func (h *TaskHandler) GetList(ctx context.Context, req *model.SearchPlatTaskReq,
 }
 
 // Create 添加任务
+// Swagger:Task 督办 添加
 func (h *TaskHandler) Create(ctx context.Context, req *model.AddPlatTaskReq, rsp *comm_def.CommonMsg) error {
 	if req.TaskStatus == "" {
 		req.TaskStatus = "10" // 任务状态(10进行中20关闭)
@@ -51,6 +52,7 @@ func (h *TaskHandler) Create(ctx context.Context, req *model.AddPlatTaskReq, rsp
 }
 
 // Handle 督办任务处理
+// Swagger:Task 督办 处理
 func (h *TaskHandler) Handle(ctx context.Context, req *model.HandleReq, rsp *comm_def.CommonMsg) error {
 	// 参数校验
 	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
@@ -69,6 +71,7 @@ func (h *TaskHandler) Handle(ctx context.Context, req *model.HandleReq, rsp *com
 }
 
 // ChangeStatus 修改任务状态
+// Swagger:Task 督办 修改状态
 func (h *TaskHandler) ChangeStatus(ctx context.Context, req *model.ChangeStatusReq, rsp *comm_def.CommonMsg) error {
 	// 参数校验
 	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
@@ -86,7 +89,7 @@ func (h *TaskHandler) ChangeStatus(ctx context.Context, req *model.ChangeStatusR
 	return nil
 }
 
-// 导出数据
+// Export 导出数据
 func (h *TaskHandler) Export(ctx context.Context, req *model.ExportReq, rsp *comm_def.CommonMsg) error {
 	taskService, err := server.NewTaskService(ctx)
 	if err != nil {
@@ -101,7 +104,8 @@ func (h *TaskHandler) Export(ctx context.Context, req *model.ExportReq, rsp *com
 	return nil
 }
 
-// 统计各类型督办任务数量
+// StatisticsTaskNumber 统计各类型督办任务数量
+// Swagger:Task 督办 数量统计
 func (h *TaskHandler) StatisticsTaskNumber(ctx context.Context, req *model.SearchPlatTaskReq, rsp *comm_def.CommonMsg) error {
 	taskService, err := server.NewTaskService(ctx)
 	if err != nil {

+ 1 - 0
opms_parent/app/model/plat/plat_task.go

@@ -24,6 +24,7 @@ type PlatTaskEx struct {
 type SearchPlatTaskReq struct {
 	TaskTitle   string `json:"taskTitle"`   // 任务标题
 	TaskType    string `son:"taskType"`     // 任务类型 数据字典
+	Source      string `json:"source"`      // 事项来源 数据字典
 	TaskStatus  string `json:"taskStatus"`  // 任务状态(10发起  20进行中   30流程完成)
 	IsOverdue   string `json:"isOverdue"`   // 是否超期(10否20是)
 	MainUserId  string `json:"mainUserId"`  // 负责人ID

+ 1 - 0
opms_parent/app/model/workflow/plat_workflow.go

@@ -22,6 +22,7 @@ const (
 	ProjectPersonnel = "25" // 项目协同人员审批
 	ContractCreate   = "30" // 合同创建
 	ContractInvoice  = "31" // 申请发票
+	PlatTaskApproval = "40" // 督办任务审批
 )
 
 // PlatWorkflow is the golang structure for table plat_workflow.

+ 179 - 10
opms_parent/app/service/plat/plat_task.go

@@ -3,7 +3,13 @@ package plat
 import (
 	"bytes"
 	"context"
+	workflowModel "dashoo.cn/micro/app/model/workflow"
+	workflowService "dashoo.cn/micro/app/service/workflow"
+	"dashoo.cn/opms_libary/plugin/dingtalk/message"
+	"dashoo.cn/opms_libary/plugin/dingtalk/workflow"
+	"dashoo.cn/opms_libary/utils"
 	"database/sql"
+	"errors"
 	"fmt"
 	"strconv"
 	"strings"
@@ -19,6 +25,8 @@ import (
 	"dashoo.cn/micro/app/service"
 )
 
+var PlatTaskApprovalProcessCode = "PROC-B2BE7E92-8A12-4CFF-83CD-FF23F397CCE2"
+
 type taskService struct {
 	*service.ContextService
 
@@ -34,15 +42,18 @@ func NewTaskService(ctx context.Context) (svc *taskService, err error) {
 	return svc, nil
 }
 
-// 任务信息列表
+// GetList 任务信息列表
 func (s *taskService) GetList(req *model.SearchPlatTaskReq) (total int, TaskList []*model.PlatTaskEx, err error) {
-	TaskModel := s.Dao.InnerJoin("plat_task_handle", "plat_task_handle.task_id=plat_task.id")
+	TaskModel := s.Dao.LeftJoin("plat_task_handle", "plat_task_handle.task_id=plat_task.id")
 	if req.TaskTitle != "" {
 		TaskModel = TaskModel.Where("plat_task.task_title LIKE ?", "%"+req.TaskTitle+"%")
 	}
 	if req.TaskType != "" {
 		TaskModel = TaskModel.Where("plat_task.task_type", req.TaskType)
 	}
+	if req.Source != "" {
+		TaskModel = TaskModel.Where("plat_task.source", req.Source)
+	}
 	if req.TaskStatus != "" {
 		TaskModel = TaskModel.Where("plat_task.task_status", req.TaskStatus)
 	}
@@ -84,7 +95,7 @@ func (s *taskService) GetList(req *model.SearchPlatTaskReq) (total int, TaskList
 	return
 }
 
-// 导出数据
+// Export 导出数据
 func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent, err error) {
 	var con model.ExportContent
 	// 获取数据
@@ -200,7 +211,7 @@ func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent
 	return &con, err
 }
 
-// 统计
+// Statistics 统计
 func (s *taskService) Statistics(req *model.SearchPlatTaskReq) (*model.TaskNumberCount, error) {
 	var result model.TaskNumberCount
 	// 统计数量
@@ -213,7 +224,7 @@ func (s *taskService) Statistics(req *model.SearchPlatTaskReq) (*model.TaskNumbe
 	return &result, nil
 }
 
-// 添加信息
+// Create 添加信息
 func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
 	platTask := new(model.PlatTask)
 	if err = gconv.Struct(req, platTask); err != nil {
@@ -237,8 +248,7 @@ func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
 	// 创建操作任务
 	id, _ := res.LastInsertId()
 	platTask.Id = int(id)
-	nextHandle := createNextTaskHandel(s, platTask, 10)
-	_, err = s.Dao.DB.Insert("plat_task_handle", nextHandle)
+	err = s.startDingApproval(platTask)
 	if err != nil {
 		return
 	}
@@ -248,7 +258,55 @@ func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
 	return
 }
 
-// 修改状态
+// AddTaskApproval 创建督办之后,需要钉钉审批才能生效
+func (s *taskService) AddTaskApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	task, err := s.Dao.Where("id = ?", flow.BizCode).FindOne()
+	if err != nil {
+		return fmt.Errorf("创建督办审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
+	}
+	if err != nil {
+		return err
+	}
+	if task == nil {
+		return fmt.Errorf("督办不存在:%s Id: %d", flow.BizCode, flow.Id)
+	}
+
+	if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
+		return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
+	}
+	if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
+		return fmt.Errorf("无法识别的 Result :%s", msg.Result)
+	}
+	if msg.ProcessType == "terminate" {
+		_, err = s.Dao.Update("task_status='50'", fmt.Sprintf("id='%v'", task.Id))
+		if err != nil {
+			return err
+		}
+		// 流程日志
+		err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "撤销", "")
+	} else {
+		if msg.Result == "agree" {
+			nextHandle := createNextTaskHandel(s, task, 10)
+			_, err = s.Dao.DB.Insert("plat_task_handle", nextHandle)
+			if err != nil {
+				return err
+			}
+			// 流程日志
+			err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "通过", "")
+		} else if msg.Result == "refuse" {
+			_, err = s.Dao.Update("task_status='40'", fmt.Sprintf("id='%v'", task.Id))
+			if err != nil {
+				return err
+			}
+			// 流程日志
+			err = CreateTaskLog(s, nil, task.Id, s.GetCxtUserId(), s.GetCxtUserName(), "督办审批", "拒绝", "")
+		}
+	}
+
+	return err
+}
+
+// ChangeStatus 修改状态
 func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
 	data := ""
 	where := fmt.Sprintf("id='%v'", req.TaskId)
@@ -299,8 +357,8 @@ func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
 	return
 }
 
+// Handle 督办任务处理
 //步骤号(10接收  15暂存  20提交  30审批(督办人)  40评价(监办人))
-// 督办任务处理
 func (s *taskService) Handle(req *model.HandleReq) (err error) {
 	// 步骤号(10接收  15暂存  20提交  30审批(督办人)  40评价(监办人))
 	// 处理结果(10接收20提交30审批通过40审批退回)
@@ -437,7 +495,7 @@ func (s *taskService) Handle(req *model.HandleReq) (err error) {
 	return nil
 }
 
-// 任务日志创建方法
+// CreateTaskLog 任务日志创建方法
 func CreateTaskLog(s1 *taskService, s2 *taskProgressService, taskId, userId int, userName, nodeName, desc, remark string) (err error) {
 	var log model.PlatTaskLog
 	startTime := gtime.Now()
@@ -509,6 +567,117 @@ func createNextTaskHandel(s *taskService, task *model.PlatTask, step int) *model
 	return &personTask
 }
 
+func (s *taskService) startDingApproval(task *model.PlatTask) error {
+	dictMap := make(map[string]string, 0)
+	userMap := make(map[int]string, 0)
+	teamNames := ""
+	dicts, err := s.Dao.DB.Model("sys_dict_data").Where("dict_type = 'plat_task_source'").FindAll()
+	if err != nil && err != sql.ErrNoRows {
+		return err
+	}
+	if len(dicts) == 0 {
+		return errors.New("督办来源数据缺失,请前往配置")
+	}
+	for _, dict := range dicts {
+		dictMap[dict["dict_value"].String()] = dict["dict_label"].String()
+	}
+	users, err := s.Dao.DB.Model("sys_user").FindAll()
+	if err != nil && err != sql.ErrNoRows {
+		return err
+	}
+	if len(users) == 0 {
+		return errors.New("用户数据数据缺失,请前往配置")
+	}
+	for _, user := range users {
+		userMap[user["id"].Int()] = user["nick_name"].String()
+	}
+	if task.OwnerUserId != "" {
+		ids := strings.Split(task.OwnerUserId, ",")
+		for _, id := range ids {
+			if teamNames == "" {
+				teamNames = userMap[gconv.Int(id)]
+			} else {
+				teamNames += "," + userMap[gconv.Int(id)]
+			}
+		}
+	}
+
+	workflowSrv, err := workflowService.NewFlowService(s.Ctx)
+	if err != nil {
+		return err
+	}
+
+	_, err = workflowSrv.StartProcessInstance(gconv.String(task.Id), "40", "", &workflow.StartProcessInstanceRequest{
+		ProcessCode: &PlatTaskApprovalProcessCode,
+		FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
+			{
+				Id:    utils.String("TextField-K2AD4O5B"),
+				Name:  utils.String("编号"),
+				Value: utils.String(task.TaskTitle),
+			},
+			{
+				Id:    utils.String("DDDateField_C7LJMHNU6N40"),
+				Name:  utils.String("发布时间"),
+				Value: utils.String(task.CreatedTime.Format("Y-m-d")),
+			},
+			{
+				Id:    utils.String("DDSelectField_OF3POKFZ43K"),
+				Name:  utils.String("督办来源"),
+				Value: utils.String(dictMap[task.Source]),
+			},
+			{
+				Id:    utils.String("TextField_VPO2N6I4N5S0"),
+				Name:  utils.String("督办内容"),
+				Value: utils.String(task.TaskDesc),
+			},
+			{
+				Id:    utils.String("DDAttachment_18RP41VRTITC0"),
+				Name:  utils.String("附件"),
+				Value: utils.String(""),
+			},
+			{
+				Id:    utils.String("DDPhotoField_11WXOUDIZ85C0"),
+				Name:  utils.String("图片"),
+				Value: utils.String(""),
+			},
+			{
+				Id:    utils.String("TextField_1ER7VNEEGU0W0"),
+				Name:  utils.String("督办人"),
+				Value: utils.String(userMap[task.SupervisorUserId]),
+			},
+			{
+				Id:    utils.String("TextField_OKAEW6GD2FK0"),
+				Name:  utils.String("监办人"),
+				Value: utils.String(userMap[task.WatchUserId]),
+			},
+			{
+				Id:    utils.String("TextField_G97RO96HMXK0"),
+				Name:  utils.String("被督办人"),
+				Value: utils.String(userMap[task.MainUserId]),
+			},
+			{
+				Id:    utils.String("TextField_1FKS6CUW7REO0"),
+				Name:  utils.String("共同完成人"),
+				Value: utils.String(teamNames),
+			},
+			{
+				Id:    utils.String("DDDateField_T9YBZCDTB680"),
+				Name:  utils.String("要求完成时间"),
+				Value: utils.String(task.TaskEndDate.Format("Y-m-d")),
+			},
+			{
+				Id:    utils.String("TextField_LMV0Q71JD5C0"),
+				Name:  utils.String("备注"),
+				Value: utils.String(task.Remark),
+			},
+		},
+	})
+	if err != nil {
+		return err
+	}
+	return err
+}
+
 // 处理暂存、提交任务进展
 func (s *taskService) saveProgressList(req *model.HandleReq, now *gtime.Time) (err error) {
 	ids := ""