Support > Repository > Workflow > Dynamically decide Approver/Authorizer by Script
ja | en

You can dynamically change the workflow approver/authorizer using a script. R7.9

You can dynamically decide approvers and decision-makers using scripts.Here, I will show you how to calculate approvers and decision-makers using principals assigned to account (juser).

In the script, you can refer to data of another model using Dao, Service object.You can use Criteria for refining your search.Detail is"Business logicPlease read.

account

Have the following accounts prepared.

Sales department

account Principal
amuroApplicant
nakamuraAuthorizer
shinjoAuthorizer
onagaAuthorizer
Figure 2 Sales department account

The principal is set for each model.Figure 3 shows the principal set for the annual leave model.

Principals set in the 3-year holiday application model

Check the principals assigned to the accounts amuro, nakamura, onaga.(FIG. 4, FIG. 5, FIG. 6)

Figure 4 Account Amuro Principal
Figure 5 Account nakamura's principal
Figure 6 Account onaga's principal

Typically, flow participants specify users or groups.However, this time we will make the following settings for "consultation, sequential, sequential flow".

node Classification Description
Application 1 A conference Engineering Department
Application 2 A conference Sales department
Approval Sequentially (Script to determine Approver: described later)
Decision Sequentially (Script to determine authorizer: described later)

Because the application is set as a consultation, anyone belonging to the technical department or sales department can apply.

Figure 7 Flow Participant Settings

Check the flow pattern used here.Since the number of nodes of the consultation at the time of application is 1 (if belonging to the group) anyone can apply.

Figure 8 Checking the flow pattern

Script to determine Approver

Acquire the user who belongs to the same group as the applicant and who is granted "approver" to the principal.We will treat this as an approver.For this reason,The approver changes dynamically by changing the principal given to the user.

// 申請者の所属するグループの承認者を取得する
var getAdmitUsers = function(users) {
  stdout.println("getAdmitUsers users:["+users+"]");
  var admitUsers = "";
  if (!users || users.length == 0) {
    return admitUsers;
  }
  //stdout.println("承認者数:["+users.length+"]");
  //stdout.println("承認者1:["+users[0]+"]");
  admitUsers = users[0].getUserid();
  for (var i=1; i<users.length; i++) {
    //stdout.println("承認者"+(i+1)+":["+users[i]+"]");
    // 承認者が複数の場合は区切り文字「|」を付加して連結する
    admitUsers = admitUsers + "|" + users[i].getUserid();
  }
  return admitUsers;
};

var getApprovalPerson = function(applicant) {
  var groupid = applicant.getJgroupid();
  var juserEntityService = p.appctx.getBean("JuserEntityService");
  var juserMeta = new JuserMeta();
  var criteria = DetachedCriteria.forClass(juserMeta.entityClass());
  // 申請者の所属するグループを条件にする
  if (groupid && groupid.length > 0) {
    criteria.eq(juserMeta.jgroupid, groupid[0]);
  }
  // 承認者プリンシパルを条件にする
  criteria.eq(juserMeta.jprincipalId, 15);
  criteria.eq(juserMeta.jprincipalId, 19);
  return juserEntityService.find(criteria);
};

// 処理の本体。applicant は申請者を指す。
if (applicant == null) {
  return null;
}
stdout.println(applicant);
var admitUsers = getAdmitUsers(getApprovalPerson(applicant));
stdout.println(admitUsers);
return admitUsers;
Stdout.println is for debugging purposes.Please comment out during production operation.
  • From line 2 to line 17 we define function getAdmitUsers.
  • From line 19 to line 32, the function getApprovalPerson is defined.
  • The main body is the 33rd line and beyond.The implicit variable applicant indicates the applicant.The entity is juser.
  • We are seeking the next approver at line 39.First call the function getApprovalPerson with the applicant as an argument.This requires other accounts belonging to the same group as the applicant.Criteria are expressed using criteria.Please note that principals use IDs.Wagby keeps using the assigned principal ID (unless deleted) once.The principal ID is maintained even after import export.
  • It also calls getAdmitUsers with the return value of getApprovalPerson.This function returns one string of characters separated by "|" when there are multiple users of arguments.In Wagby's workflow processing, multiple accounts are separated by "|".

Script to determine the authorizer

Acquire the user who belongs to the same group as the applicant and who has "authorized person" granted to the principal.I will treat this as an authorizer.For this reason,The authorizer changes dynamically by changing the principal given to the user.

// 申請者の所属するグループの決裁者を取得する
var getAdmitUsers = function(users) {
  stdout.println("getAdmitUsers users:["+users+"]");
  var admitUsers = "";
  if (!users || users.length == 0) {
    return admitUsers;
  }
  //stdout.println("承認者数:["+users.length+"]");
  //stdout.println("承認者1:["+users[0]+"]");
  admitUsers = users[0].getUserid();
  for (var i=1; i<users.length; i++) {
    //stdout.println("承認者"+(i+1)+":["+users[i]+"]");
    // 承認者が複数の場合は区切り文字「|」を付加して連結する
    admitUsers = admitUsers + "|" + users[i].getUserid();
  }
  return admitUsers;
};

var getApprovalPerson = function(applicant, principalIds) {
  var groupid = applicant.getJgroupid();
  var juserEntityService = p.appctx.getBean("JuserEntityService");
  var juserMeta = new JuserMeta();
  var criteria = DetachedCriteria.forClass(juserMeta.entityClass());
  // 申請者の所属するグループを条件にする
  if (groupid && groupid.length > 0) {
    criteria.eq(juserMeta.jgroupid, groupid[0]);
  }
  // 決裁者プリンシパルを条件にする
  criteria.eq(juserMeta.jprincipalId, 17);
  criteria.eq(juserMeta.jprincipalId, 21);
  return juserEntityService.find(criteria);
};
if (applicant == null) {
  return null;
}
stdout.println(applicant);
var admitUsers = getAdmitUsers(getApprovalPerson(applicant));
stdout.println(admitUsers);
return admitUsers;
Stdout.println is for debugging purposes.Please comment out during production operation.
Since the content of the script is similar to "Script to determine Approver", we will skip the explanation.

Figure 9 shows an example of logging on with applicant amuro and applying for workflow.By executing the script, you can see that the next processing pendants are nakamura and shinjo.(The next process pending WF_USERID functionI'm looking for it.)

Figure 9 Account After amuro application

Figure 10 shows an example approved by the following approver nakamura.By the execution of the script, the next process held party (settlement's) will find that that is the onaga.

Fig. 10 After approval processing by account nakamura

You can use the model ID (the object indicated by) in the script set for the workflow participant.For example, if the model using workflow is leave, you can write it in the script as follows.

var reason = leave.reason;

By default, this variable (object) isWe are not performing reference linking and automatic calculation processing.This is because we prioritize performance.To solve the reference linkage item and obtain the value of the calculation expression, please go through the EntityService as follows.

var entityService = p.appctx.getBean("LeaveEntityService");
var leave = entityService.findById(modelpkey);

Here variablemodelpkeyCan also be used implicitly in this script.It holds the primary key of the target model, so it can be used as an argument to findById.

  • The database type of the flow participant script uses a type corresponding to CLOB of each database.The maximum length of the size of the script is the upper limit value of the CLOB type of the database.For example, Oracle will be NCLOB.For details, please check the automatically generated jfcparticipant_setting.ddl.
  • The entity of implicit variable applicant that can be referenced in scripts is a juser object.
  • This script may be executed multiple times under the assumption of workflow processing.Since how many times it is executed depends on the flow setting, make sure that the result does not change even if it is executed multiple times.(Specifically, please do not add procedures such as assuming that it is called N times or changing processing at the Nth call.)