alfrescoalfresco-sharealfresco-webscripts

How to add custom table to the reviewTask screen of workflow form?


Alfresco Community v5.2 includes some of preconfigured workflows that available on the page /share/page/start-workflow

Among others, there is one that is interested to me - is "Review and Approve (one or more reviewers) - Assign a review task to multiple reviewers".

This business process is well suited to the requirements of one of our customers.

The only difference is that is needed to see the table of all the performers on the ReviewTask screens.

I decided to start with this wonderful article by Muralidharan Deenathayalan: Alfresco community 5.1.x workflow form add input fields dynamically

For start, I would like to see the table on my screens.

But I faced with the problem - the table is not displayed (even the static header).

And when I try to approve or reject the document, an exception occurs:

org.activiti.engine.ActivitiException: Exception while invoking TaskListener: 02100034 Mandatory task properties have not been provided! {http://www......com/model/workflow/1.0}userDetails

Some of the details below.

workflow-model.xml:

<?xml version="1.0" encoding="UTF-8"?>

<model name="mswf:workflowmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

   <imports>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
   </imports>

   <namespaces>
      <namespace uri="http://www.........../model/workflow/1.0" prefix="mswf" />
   </namespaces>

   <types>
      <type name="mswf:submitConcurrentReviewTask">
         <parent>bpm:startTask</parent>
         <properties>
            <property name="mswf:requiredApprovePercent">
                <type>d:int</type>
                <mandatory>true</mandatory>
                <default>50</default>
                <constraints>
                    <constraint type="MINMAX">
                        <parameter name="minValue"><value>1</value></parameter>
                        <parameter name="maxValue"><value>100</value></parameter>
                    </constraint>
                </constraints>
            </property>
         </properties>
      </type>

      <type name="mswf:submitParallelReviewTask">
         <parent>mswf:submitConcurrentReviewTask</parent>
         <mandatory-aspects>
            <aspect>bpm:assignees</aspect>
         </mandatory-aspects>
      </type>

        <type name="mswf:activitiReviewTask">
            <parent>bpm:activitiOutcomeTask</parent>
            <properties>
                <property name="mswf:reviewOutcome">
                    <type>d:text</type>
                    <default>Reject</default>
                    <constraints>
                        <constraint name="mswf:reviewOutcomeOptions" type="LIST">
                            <parameter name="allowedValues">
                                <list>
                                    <value>Approve|...</value>
                                    <value>Reject|...</value>
                                </list>
                            </parameter>
                        </constraint>
                    </constraints>
                </property>
                 <property name="mswf:userDetails"> 
                    <title> User Details</title> 
                    <type>d:text</type> 
                    <mandatory>true</mandatory> 
                 </property>
            </properties>
            <overrides>
                <property name="bpm:packageItemActionGroup">
                    <default>edit_package_item_actions</default>
                </property>
                <property name="bpm:outcomePropertyName">
                    <default>{http://www......../model/workflow/1.0}reviewOutcome</default>
                </property>
            </overrides>
        </type>

      <type name="mswf:rejectedParallelTask">
         <parent>bpm:workflowTask</parent>
         <mandatory-aspects>
            <aspect>mswf:parallelReviewStats</aspect>
         </mandatory-aspects>
      </type>

      <type name="mswf:approvedParallelTask">
         <parent>bpm:workflowTask</parent>
         <mandatory-aspects>
            <aspect>mswf:parallelReviewStats</aspect>
         </mandatory-aspects>
      </type>
   </types>

   <aspects>
      <aspect name="mswf:parallelReviewStats">
         <properties>
            <property name="mswf:reviewerCount">
               <type>d:int</type>
            </property>
            <property name="mswf:requiredPercent">
               <type>d:int</type>
            </property>
            <property name="mswf:approveCount">
               <type>d:int</type>
            </property>
            <property name="mswf:actualPercent">
               <type>d:int</type>
            </property>
         </properties> 
      </aspect>
   </aspects>
</model>

contractsApproval.bpmn:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/....-10.0">
  <process id="contractsApproval" name="..... Approval " isExecutable="true">
    <extensionElements>
      <activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener">
        <activiti:field name="script">
          <activiti:string><![CDATA[execution.setVariable('mswf_approveCount', 0);
                        execution.setVariable('mswf_rejectCount', 0);

                        execution.setVariable('mswf_actualPercent', 0);
                        execution.setVariable('mswf_actualRejectPercent', 0);

                        execution.setVariable('mswf_reviewerCount', bpm_assignees.size());
                        execution.setVariable('mswf_requiredPercent', mswf_requiredApprovePercent);]]></activiti:string>
        </activiti:field>
      </activiti:executionListener>
    </extensionElements>
    <startEvent id="start" activiti:formKey="mswf:submitParallelReviewTask"></startEvent>
    <sequenceFlow id="flow1" sourceRef="start" targetRef="reviewTask"></sequenceFlow>
    <userTask id="reviewTask" name="Review Task" activiti:assignee="${reviewAssignee.properties.userName}" activiti:formKey="mswf:activitiReviewTask">
      <extensionElements>
        <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
            <activiti:string><![CDATA[if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
                        if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
        <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
            <activiti:string><![CDATA[if(task.getVariableLocal('mswf_reviewOutcome') == 'Approve') {
                            var newApprovedCount = mswf_approveCount + 1;
                             var newApprovedPercentage = (newApprovedCount / mswf_reviewerCount) * 100;

                             execution.setVariable('mswf_approveCount', newApprovedCount);
                             execution.setVariable('mswf_actualPercent', newApprovedPercentage);
                        } else {
                            var newRejectCount = mswf_rejectCount + 1;
                            var newRejectPercentage = (newRejectCount / mswf_reviewerCount) * 100;

                            execution.setVariable('mswf_rejectCount', newRejectCount);
                            execution.setVariable('mswf_actualRejectPercent', newRejectPercentage);
                        }]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
      </extensionElements>
      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="bpm_assignees" activiti:elementVariable="reviewAssignee">
        <completionCondition>${mswf_actualPercent &gt;= mswf_requiredApprovePercent || mswf_requiredApprovePercent &gt; (100 - mswf_actualRejectPercent)}</completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="reviewTask" targetRef="reviewDecision"></sequenceFlow>
    <exclusiveGateway id="reviewDecision" name="Review Decision"></exclusiveGateway>
    <sequenceFlow id="flow3" sourceRef="reviewDecision" targetRef="approved">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${mswf_actualPercent >= mswf_requiredApprovePercent}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow4" sourceRef="reviewDecision" targetRef="rejected"></sequenceFlow>
    <userTask id="approved" name="Document Approved" activiti:assignee="${initiator.exists() ? initiator.properties.userName : 'admin'}" activiti:formKey="mswf:approvedParallelTask">
      <documentation>The document was reviewed and approved.</documentation>
      <extensionElements>
        <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
            <activiti:string><![CDATA[if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
                        if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;

                        // Set parallel review params on task, to be kept in history
                        task.setVariableLocal('mswf_reviewerCount', mswf_reviewerCount);
                        task.setVariableLocal('mswf_requiredPercent', mswf_requiredPercent);
                        task.setVariableLocal('mswf_actualPercent', mswf_actualPercent);
                        task.setVariableLocal('mswf_approveCount', mswf_approveCount);]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
      </extensionElements>
    </userTask>
    <userTask id="rejected" name="Document Rejected" activiti:assignee="${initiator.exists() ? initiator.properties.userName : 'admin'}" activiti:formKey="mswf:rejectedParallelTask">
      <documentation>The document was reviewed and rejected.</documentation>
      <extensionElements>
        <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
            <activiti:string><![CDATA[if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
                        if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;

                        // Set parallel review params on task, to be kept in history
                        task.setVariableLocal('mswf_reviewerCount', mswf_reviewerCount);
                        task.setVariableLocal('mswf_requiredPercent', mswf_requiredPercent);
                        task.setVariableLocal('mswf_actualPercent', mswf_actualPercent);
                        task.setVariableLocal('mswf_approveCount', mswf_approveCount);]]></activiti:string>
          </activiti:field>
        </activiti:taskListener>
      </extensionElements>
    </userTask>
    <sequenceFlow id="flow5" sourceRef="approved" targetRef="end"></sequenceFlow>
    <sequenceFlow id="flow6" sourceRef="rejected" targetRef="end"></sequenceFlow>
    <endEvent id="end"></endEvent>
  </process>

  <bpmndi:BPMNDiagram id="BPMNDiagram_contractsApproval">
   ...
  </bpmndi:BPMNDiagram>
</definitions>

share-config-custom.xml (some fields are not specified):

<alfresco-config>
   <config evaluator="string-compare" condition="activiti$activitiReview">
      <forms>
         <form>
            <field-visibility>
               <show id="bpm:workflowDescription" />
               <show id="bpm:workflowDueDate" />
               <show id="bpm:workflowPriority" />
               <show id="bpm:assignee" />
               <show id="packageItems" />
               <show id="bpm:sendEMailNotifications" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.general" />
               <set id="info" appearance="" template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="assignee" appearance="title" label-id="workflow.set.assignee" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" label-id="workflow.set.other" />

               <field id="bpm:assignee" label-id="workflow.field.reviewer" set="assignee" />
                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>                   
            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="string-compare" condition="activiti$contractsApproval">
      <forms>
         <form>
            <field-visibility>
               <show id="bpm:workflowDescription" />
               <show id="bpm:workflowDueDate" />
               <show id="bpm:workflowPriority" />
               <show id="bpm:assignees" />
               <show id="mswf:requiredApprovePercent" />
               <show id="packageItems" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.general" />
               <set id="info" appearance="" template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="assignee" appearance="title" label-id="workflow.set.assignees" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" label-id="workflow.set.other" />

               <field id="bpm:assignees" label-id="workflow.field.reviewers" set="assignee" />
                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>
               <field id="packageItems" set="items" />
            </appearance>
         </form>
      </forms>
   </config>    
    <config evaluator="string-compare" condition="activiti$activitiLifecycleApproval">
      <forms>
         <form>
            <field-visibility>
               <show id="bpm:workflowDescription" />
               <show id="bpm:workflowDueDate" />
               <show id="bpm:workflowPriority" />
               <show id="bpm:assignee" />
               <show id="packageItems" />
               <show id="bpm:sendEMailNotifications" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.general" />
               <set id="info" appearance="" template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="assignee" appearance="title" label-id="workflow.set.assignee" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" label-id="workflow.set.other" />

                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>
            </appearance>
         </form>
      </forms>
   </config>            
   <config evaluator="task-type" condition="bpm:startTask">
      <forms>
         <form id="workflow-details">
            <field-visibility>
               <show id="bpm:sendEMailNotifications" />
               <show id="packageItems" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.workflow.more_info" />
               <set id="items" appearance="title" label-id="workflow.set.items" />

               <field id="packageItems" set="items" />
            </appearance>
         </form>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:workflowPriority" />
               <show id="bpm:workflowDueDate" />
               <show id="bpm:taskId" />
               <show id="bpm:status" />
               <show id="packageItems" />
               <show id="bpm:sendEMailNotifications" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" label-id="workflow.set.other" />

                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>

            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="task-type" condition="mswf:submitParallelReviewTask">
      <forms>
         <form id="workflow-details">
            <field-visibility>
               <show id="mswf:requiredApprovePercent" />
               <show id="bpm:sendEMailNotifications" />
               <show id="packageItems" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.workflow.more_info" />
               <set id="items" appearance="title" label-id="workflow.set.items" />

               <field id="packageItems" set="items" />
            </appearance>
         </form>    
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:workflowPriority" />
               <show id="bpm:workflowDueDate" />
               <show id="bpm:taskId" />
               <show id="mswf:requiredApprovePercent" />
               <show id="bpm:status" />
               <show id="packageItems" />
               <show id="bpm:sendEMailNotifications" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" label-id="workflow.set.other" />

                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>

            </appearance>
         </form>
      </forms>
   </config>       
   <config evaluator="task-type" condition="bpm:workflowTask">
      <forms>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:priority" />
               <show id="bpm:dueDate" />
               <show id="bpm:taskId" />
               <show id="bpm:status" />
               <show id="packageItems" />
               <show id="bpm:comment" />
               <show id="transitions" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="response" appearance="title" label-id="workflow.set.response" />

                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>
            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="task-type" condition="mswf:reviewTask">
      <forms>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:priority" />
               <show id="bpm:dueDate" />
               <show id="bpm:taskId" />
               <show id="packageItems" />
               <show id="bpm:comment" />
               <show id="transitions" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="response" appearance="title" label-id="workflow.set.response" />

                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>

            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="task-type" condition="mswf:activitiReviewTask">
      <forms>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:priority" />
               <show id="bpm:dueDate" />
               <show id="bpm:taskId" />
               <show id="packageItems" />
               <show id="bpm:comment" />              
               <show id="mswf:reviewOutcome" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="response" appearance="title" label-id="workflow.set.response" />

               <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
               </field>
            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="task-type" condition="mswf:approvedParallelTask">
      <forms>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:priority" />
               <show id="bpm:dueDate" />
               <show id="bpm:taskId" />
               <show id="mswf:reviewerCount" />
               <show id="mswf:approveCount" />
               <show id="mswf:requiredPercent" />
               <show id="mswf:actualPercent" />
               <show id="packageItems" />
               <show id="bpm:comment" />
               <show id="transitions" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="outcome" appearance="title" label-id="workflow.set.outcome"
                    template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="response" appearance="title" label-id="workflow.set.response" />

               <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
               </field>
            </appearance>
         </form>
      </forms>
   </config>    
   <config evaluator="task-type" condition="mswf:rejectedParallelTask">
      <forms>
         <form>
            <field-visibility>
               <show id="message" />
               <show id="taskOwner" />
               <show id="bpm:priority" />
               <show id="bpm:dueDate" />
               <show id="bpm:taskId" />
               <show id="mswf:reviewerCount" />
               <show id="mswf:approveCount" />
               <show id="mswf:requiredPercent" />
               <show id="mswf:actualPercent" />
               <show id="packageItems" />
               <show id="bpm:comment" />
               <show id="transitions" />
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.task.info" />
               <set id="info" appearance="" template="/org/alfresco/components/form/3-column-set.ftl" />
               <set id="progress" appearance="title" label-id="workflow.set.task.progress" />
               <set id="outcome" appearance="title" label-id="workflow.set.outcome"
                    template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="response" appearance="title" label-id="workflow.set.response" />

               <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
               </field>                   
            </appearance>
         </form>
      </forms>
   </config>
</alfresco-config>

Where I'm wrong?


Solution

  • Yes, it should be present in the <field-visibility> section and ensure, you've the set also exists int the section.

         <form>
            <field-visibility>
               ......
               ......
               <show id="mswf:userDetails" />
               ........
               ........
            </field-visibility>
            <appearance>
             ............
               <set id="userDetails" appearance="title" label="User Details" />
             .............
                <field id="mswf:userDetails" set="userDetails" label="User Details"  read-only="true">
                    <control template="/org/alfresco/components/form/controls/workflow/userdetails.ftl" />
                </field>
            </appearance>
         </form>
    

    Hope this helps you.