activiti cc

Project address: activiti-workflow , welcome star.

In process approval, a person needs to be copied to a certain node, and the person to be copied can view the process without approval. Here is by extending activit, customizing the BPMN tag, and adding the CC attribute.

Set the CC attribute to the common user node and inherit UserTask


/**
 * @description: 自定义用户节点
 * @author lhj
 * @param  
 * @return 
 * @date 2020-6-11 10:50 
 */
public class CustomUserTask extends UserTask {
    
    

    //抄送用户
    protected List<String> candidateNotifyUsers = new ArrayList();

    public List<String> getCandidateNotifyUsers() {
    
    
        return candidateNotifyUsers;
    }

    public void setCandidateNotifyUsers(List<String> candidateNotifyUsers) {
    
    
        this.candidateNotifyUsers = candidateNotifyUsers;
    }

    public CustomUserTask clone() {
    
    
        CustomUserTask clone = new CustomUserTask();
        clone.setValues(this);
        return clone;
    }
    public void setValues(CustomUserTask otherElement) {
    
    
        super.setValues(otherElement);
        this.setCandidateNotifyUsers(otherElement.getCandidateNotifyUsers());
    }
}

Parsing BPMN's xml and json is to set this property

	if (StringUtils.isNotEmpty(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_CANDIDATE_NOTIFY_USERS))) {
    
    
      String expression = xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_CANDIDATE_NOTIFY_USERS);
      userTask.getCandidateNotifyUsers().addAll(parseDelimitedList(expression));
    }
   task.setCandidateNotifyUsers(getValueAsList(CANDIDATE_NOTIFY_USERS, assignmentDefNode));

bpmn file format

    <userTask id="sid-254390AD-30E7-4390-8B97-E2A395C4A15C" name="主管审批" activiti:assignee="lisi" activiti:candidateNotifyUsers="wangwu,zhangsan">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>

In the process of flow transfer, the CC is stored in the database, and the processing logic is mainly in UserTaskActivityBehavior, which is realized through inheritance

  //保存抄送人
    if (candidateNotifyUsers != null && !candidateNotifyUsers.isEmpty()) {
    
    
      for (String notify : candidateNotifyUsers) {
    
    
        Expression userIdExpr = expressionManager.createExpression(notify);
        Object value = userIdExpr.getValue(execution);
        if (value instanceof String) {
    
    
          List<String> userIds = extractCandidates((String) value);
          for (String userId : userIds) {
    
    
            Context.getCommandContext().getIdentityLinkEntityManager().addUserIdentityLink(task, userId, ProcessConstants.NOTIFY);
          }
        } else if (value instanceof Collection) {
    
    
          Iterator userIdSet = ((Collection) value).iterator();
          while (userIdSet.hasNext()) {
    
    
            Context.getCommandContext().getIdentityLinkEntityManager().addUserIdentityLink(task, (String)userIdSet.next(), ProcessConstants.NOTIFY);
          }
          throw new ActivitiException("Expression did not resolve to a string or collection of strings");
        }
      }
    }

At this point, the CC definition and data storage have been implemented, and the rest is how to query the data, which depends on the specific business needs. Here is a simple implementation, according to the to-do check together with CC. Through the extension Mybatis provided by activiti.

	/**
     *  查询待审批任务
     * @param taskUnFinishQuery 查询条件
     * @return
     */
    @Override
    public PageBean<ProcessTaskResult> queryUnFinishTask(TaskUnFinishQuery taskUnFinishQuery){
    
    
        PageUtil<ProcessTaskResult, TaskUnFinishQuery> pageUtil = new PageUtil<>();
        Long count = managementService.executeCustomSql(new AbstractCustomSqlExecution<CustomActivitiDatabaseMapper, Long>(CustomActivitiDatabaseMapper.class) {
    
    
            @Override
            public Long execute(CustomActivitiDatabaseMapper customActivitiDatabaseMapper) {
    
    
                return customActivitiDatabaseMapper.selectUnFinishTaskCount(taskUnFinishQuery);
            }
        });
        //没有查询到,就直接返回空
        if(count <= 0){
    
    
            return pageUtil.buildPage(Collections.emptyList(), taskUnFinishQuery, 0);
        }
        List<ProcessTaskResult> list = managementService.executeCustomSql(new AbstractCustomSqlExecution<CustomActivitiDatabaseMapper, List<ProcessTaskResult>>(CustomActivitiDatabaseMapper.class) {
    
    
            @Override
            public List<ProcessTaskResult> execute(CustomActivitiDatabaseMapper customActivitiDatabaseMapper) {
    
    
                return customActivitiDatabaseMapper.selectUnFinishTask(taskUnFinishQuery);
            }
        });

        return pageUtil.buildPage(list,taskUnFinishQuery,count);
    }

There is additional processing. The CC may be for the entire process, but not for a node. Therefore, when saving the CC, not only the taskId but also the processInstanceId instance ID is saved

	@Override
    public IdentityLinkEntity addIdentityLink(TaskEntity taskEntity, String userId, String groupId, String type) {
    
    
        IdentityLinkEntity identityLinkEntity = (IdentityLinkEntity)this.identityLinkDataManager.create();
        taskEntity.getIdentityLinks().add(identityLinkEntity);
        identityLinkEntity.setTask(taskEntity);
        identityLinkEntity.setUserId(userId);
        identityLinkEntity.setGroupId(groupId);
        if (ProcessConstants.NOTIFY.equals(type)) {
    
    
            identityLinkEntity.setProcessInstanceId(taskEntity.getProcessInstanceId());
        }
        identityLinkEntity.setType(type);
        this.insert(identityLinkEntity);
        if (userId != null && taskEntity.getProcessInstanceId() != null) {
    
    
            this.involveUser(taskEntity.getProcessInstance(), userId, "participant");
        }

        return identityLinkEntity;
    }

An implementation idea is given here for reference only. The specific code can be viewed in the github project.
Regarding the problems encountered in extending BPMN, refer to

Guess you like

Origin blog.csdn.net/qq_34758074/article/details/106683308
cc