mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merging DEV/ACTIVITI_INTEGRATION2 to HEAD
25933: Updated activiti jars to 5.3 release + temporarily disabled query-tests for activtiti 25932: Fixed failing FormServiceImplTest. 25930: Fixed ClassCastException and NullPointerException when using JBPM and Activiti tasks in Alfresco Explorer. 25898: Implemented testGetWorkflows() which tests the methods getWorkflows() getActiveWorkflows() and getCompletedWorkflows() for both workflow engines. 25888: Fixed failing testOutcome. 25884: Workflow console fully tested using activiti engine + small bugfixes 25854: Implemented testGetPathProperties on AbstractWorkflowServiceIntegrationTest. This tests getPathProperties for Activiti and JBPM workflow engines. 25827: Added lifecycle sample for activiti engine 25801: Added a new WorkflowRestApiTest testTaskInstancesForWorkflowGet. Also fixed issues with ActivitWorkflowEngine.queryTasks() relating to the start task being returned incorrectly. 25731: Added timer execution test to verify Authentication and Transactional behavior + added license headers to 2 files 25682: ALF-6902 delete identitylinks + added timer sample + adhoc notify me feature 25649: Redeploying of parallel activiti WF's turned of (remainder from development) 25645: Fixing getWorkflows test, using valid date to check "due before" 25642: Implemented getPathProperties() on ActivitiWorkflowEngine. Also refactored ActivitiTypeConverter to create ActivitiPropertyConverter which uses a WorkflowPropertyHandlerRegistry. 25636: Fixes for use of Activiti workflows in JSF client 25615: Added parallel review and approve process (regular + grouped) 25520: Added REST-test for review workflow and pooled review workflow for both engines 25471: Added queryTasks test for both engines 25397: Testing getTimers() on both engines 25368: Using authorityName instead of name for candidate-group + fixed priority WF vs. Task mixup in start-task 25335: F96: A form control for LIST constraint based decision properties in Activiti tasks exists 25324: Added correct sources for current 5.3-SNAPSHOT 25323: Implemented TaskQuery further and added extra test-coverage + delete/cancel WF now deletes History as well 25318: The signal() method on ActivitiWorkflowEngine now returns a WorkflowPath if the signal ended the WorkflowInstance. 25300: Fixed start workflow form for Activiti pooled review and approve process definition 25294: Implemented signal() method on ActivitiWorkflowEngine. Currently it returns null if the signal() ended the Workflowinstance. 25199: Implemented getTimers() + fixed some issues with the outcome prop name + upgraded to activiti 5.3 25179: Added support for wf:outcome property on Activiti tasks. Now ian arbitrary property can be set as the property from which outcomes are read. 25152: Refactored the WorkflowServiceImplTest to create an AbstractWorkflowServiceImplTest. Extended this base test with Jbpm and Activiti implementations. 25134: Fixed workflowPath node issue on start-task + Task variables are no longer flushed to process-instance variables 25131: ALF-6901 start task completion date + taskListeners using ScriptService instead of activiti's built-in JSR-223 25105: Implemented getWorkflows() and getCompletedWorkflows() methods on ActivitiWorkflowEngine. 25098: Mandatory properties are now checked in TaskCompleteListener to allow setting of mandatory properties in end-task listeners before the check is performed + review-pooled used person to set as bpm_assignee + removed duplicate messageService in ActivitiWE 25089: Merged ActivitiTaskComponent and ActivitiWorkflowComponent into a single class, ActivitiWorkflowEngine. 25048: Implemented getStartTask(String) method on WorkflowService interface. This gets the start task instance for a given workflow instance Id. Also, modified the start task returned by the ActivitiTaskComponent so that it has the correct title. 25028: Added WorkflowDefinitionGet webscript and test + tested WorkflowInstanceDelete and fixed WorkflowTaskDefinition bug 25003: Added getStartTask() method to WorkflowService. Implemented for JBPMEngine and ActivitiTaskComponent. 24996: Added activiti process-definition for pooled review/approve workflow + new version of activiti 5.2 to allow releasing task to pool agian 24972: Extended TaskInstanceGet REST-test + upgraded activiti lib due to bug in HistoricTaskInstance 24934: Refactored package assignment/creation so that it is now mainly performed by the WOrkflowPackageComponent rather than the WorkflowComponent or TaskComponent. Implemented correct package behaviour for Activiti workflow engine. 24926: Extended TaskInstancePut REST-test + added extra logic for ignoring tasks for deleted/canceled WF's 24895: Added new tests to FormServiceImplTest to check TaskFormProcessor correctly transitions tasks with both workflow engines. 24888: Updated WorkflowRestApiTest, enhanced testing of getTaskInstances 24861: Updated the FormServiceImplTest so that it includes tests for the TaskFormProcessor using both workflow engines. 24851: Made WorkflowRestApiTest abstract and created a subtype for activiti and jbpm 24832: Added integration test to FormServiceImplTest to check WorkflowFormProcessor works correctly with both Activiti and Jbpm engines. 24829: ALF-6195 Pooled actors are now available on completed tasks 24806: Added null check for parameters variable 24805: Cleaned up WorkflowRestAPITest to remove deprecated field access. 24797: ALF-6016 start-task now contains variables, upgraded to activiti 5.2-SNAPSHOT 24796: Removed accidentaly checked-in folder 24795: Share project "Catalina-virtual" into "https://svn.alfresco.com/repos/enterprise/alfresco/BRANCHES/DEV/ACTIVITI_INTEGRATION2/root" 24780: Created Activiti Review & Approve workflow. 24702: ALF-6201 cleaned up WOFactory.createInstance + removed candidate group from adhoc WF (pooled task) 24693: ALF-6438 implemented getWorkflowById for completed workflows + added unittest for getWorkflowById from running and complete processes 24686: ALF-6195 added formKey (typeDefinition name) to variables to make available in history + added test for getTaskById() for a completed task 24642: ALF-6003 + ALF-6195 Introduced mapping of WorkfloTask from HistoricTaskInstance and it's variables 24565: ALF-6016 tested getting start task by id + added initial test for taskQuery 24560: ALF-6217 implemented and tested pooled actors using activiti-candidate user/group 24520: ALF-6003 ALF-6014 tested + various minor improvements + TaskTypeEvaluator matchin pattern adjusted to be able to use workflow-detail form for activiti start-tasks 24417: ALF-6003, ALF-6014 Added tasklisteners to set default task props + flush variables when task ends + running script in tasklistener (to set task-variables in script based on wf-props) 24399: Merged BRANCHES/V3.4 to BRANCHES/DEV/ACTIVITI_INTEGRATION2: 24396: Fix for ALF-6126: TaskTypeEvaluator uses task-name instead of taskType-name for node-type matching 24396: Fix for ALF-6126: TaskTypeEvaluator uses task-name instead of taskType-name for node-type matching 24334: ALF-6015 ALF-6016: Completing a task implemented + using task-local variables 24125: ALF-5995 properties passed when starting workflow are stored 24111: ALF-5974, ALF-5972 Task-update implemented + capturing company-home, initiator and initiator home implemented and tested 23891: Fixing failing tests in ActivitiWorkflowComponentTest 23776: Upgraded activiti to 5.0-SNAPSHOT + Introduced error-handling using messages + initial support for HistoricActivity/ProcessInstances 23600: Removing unneeded folder that was introduced accidentally when reattaching SVN to eclipse 23599: 23298: 23250: Rolling back revisions 23212 to 23113 to fix issue with logging in. 23212: Trying to fix the problem with logging in. 23200: Added Form config for the Activiti Adhoc Process. Fixed failing tests in ActivitiWorkflowComponentTest. 23197: Fixed failing tests in WorkflowServiceeImplTest. Updated Activiti jars in 3rdParty. 23191: Adding Activiti Ahodc Workflow to Workflow Deployer to demonstrate Activiti Workflow/Task..Component integration with UI. 23129: Copy Activiti JAR files when building WAR and doing exploded deploy 23113: Implemented ActivitiTaskComponent.getTaskById() 23079: Created ActivitiTaskComponent and started to implement various task getter methods. 22890: Added testStartTask to WorkflowServiceImplTests to test that the start task functionality works as required by the Workflow UI. 22889: Added testStartTask to WorkflowServiceImplTests to test that the start task functionality works as required by the Workflow UI. 22888: Added testStartTask to WorkflowServiceImplTests to test that the start task functionality works as required by the Workflow UI. 22887: Added testStartTask to WorkflowServiceImplTests to test that the start task functionality works as required by the Workflow UI. 22769: Added more functionality to ActivitiWorkflowComponent.startWorkflow. 22759: Implemented more methods for getting WorkflowDefinitions on ActivitiWorkflowComponent. Also added more functionality to the startWorkflow method. 22758: Implemented more methods for getting WorkflowDefinitions on ActivitiWorkflowComponent. Also added more functionality to the startWorkflow method. 22672: Created ActivitiWorkflowComponent and implemented deployDefinition(), undeployDefinition() and isDefinitionDeployed() methods. 22659: Replacing Activiti Jars 22359: Added tests to check rollback of transactions in Activiti. 22358: Got some simple transaction tests working. These test transaction visibility is working properly and also check that rollbacks work correctly. 22342: Created a patch to add the Activiti tables in. 22333: Added some simple tests to check if Activiti works using a DataSource and TransactionManager. 22332: Updating Activiti to the beta release. 22286: Added Activiti and its dependencies to 3rd Party libraries. Updated JUnit jar to 4.8. Created package org/alfresco/repo/workflow/activiti and added some simple tests to check Activiti integration. 21879: Branch to develop support for Activiti workflow engine. 23264: Creating branch ACTIVITI_INTEGRATION2 to merge HEAD back into the existing ACTIVITI_INTEGGRATION branch. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@25984 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
82
config/alfresco/workflow/adhoc.bpmn20.xml
Normal file
82
config/alfresco/workflow/adhoc.bpmn20.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<definitions id="adhoc-definitions"
|
||||
typeLanguage="http://www.w3.org/2001/XMLSchema"
|
||||
expressionLanguage="http://www.w3.org/1999/XPath"
|
||||
targetNamespace="http://activiti.org/bpmn20"
|
||||
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:activiti="http://activiti.org/bpmn">
|
||||
|
||||
<process id="activitiAdhoc" name="Adhoc Activiti Process">
|
||||
|
||||
<startEvent id="start"
|
||||
activiti:formKey="wf:submitAdhocTask" />
|
||||
|
||||
<sequenceFlow id='flow1'
|
||||
sourceRef='start'
|
||||
targetRef='adhocTask' />
|
||||
|
||||
<userTask id="adhocTask" name="Adhoc Task"
|
||||
activiti:formKey="wf:adhocTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
|
||||
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${bpm_assignee.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow2'
|
||||
sourceRef='adhocTask'
|
||||
targetRef='verifyTaskDone' />
|
||||
|
||||
<userTask id="verifyTaskDone" name="Verify Adhoc Task Completed."
|
||||
activiti:formKey="wf:completedAdhocTask" >
|
||||
<documentation>
|
||||
Verify the arbitrary task was completed.
|
||||
</documentation>
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
|
||||
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
|
||||
|
||||
if (wf_notifyMe)
|
||||
{
|
||||
var mail = actions.create("mail");
|
||||
mail.parameters.to = initiator.properties.email;
|
||||
mail.parameters.subject = "Adhoc Task " + bpm_workflowDescription;
|
||||
mail.parameters.from = bpm_assignee.properties.email;
|
||||
mail.parameters.text = "It's done";
|
||||
mail.execute(bpm_package);
|
||||
}
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow3' sourceRef='verifyTaskDone'
|
||||
targetRef='theEnd' />
|
||||
|
||||
<endEvent id="theEnd" />
|
||||
|
||||
</process>
|
||||
|
||||
</definitions>
|
171
config/alfresco/workflow/parallel-review-group.bpmn20.xml
Normal file
171
config/alfresco/workflow/parallel-review-group.bpmn20.xml
Normal file
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<definitions id="review-definitions"
|
||||
typeLanguage="http://www.w3.org/2001/XMLSchema"
|
||||
expressionLanguage="http://www.w3.org/1999/XPath"
|
||||
targetNamespace="http://activiti.org/bpmn20"
|
||||
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:activiti="http://activiti.org/bpmn">
|
||||
|
||||
<process id="activitiParallelGroupReview" name="Parallel Group Review And Approve Activiti Process">
|
||||
|
||||
<extensionElements>
|
||||
<activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
execution.setVariable('wf_approveCount', 0);
|
||||
execution.setVariable('wf_actualPercent', 0);
|
||||
execution.setVariable('wf_requiredPercent', wf_requiredApprovePercent);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:executionListener>
|
||||
</extensionElements>
|
||||
|
||||
<startEvent id="start"
|
||||
activiti:formKey="wf:submitGroupReviewTask" />
|
||||
|
||||
|
||||
<sequenceFlow id='flow1'
|
||||
sourceRef='start'
|
||||
targetRef='reviewTask'>
|
||||
<!-- TODO: Once multiInstanceLoopCharacteristics support using expression as loopDataInputRef, remove 'wf_groupMembers' variable -->
|
||||
<extensionElements>
|
||||
<activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
var members = people.getMembers(bpm_groupAssignee);
|
||||
var memberNames = new java.util.ArrayList();
|
||||
|
||||
for(var i in members) {
|
||||
memberNames.add(members[i].properties.userName);
|
||||
}
|
||||
execution.setVariable('wf_groupMembers', memberNames);
|
||||
execution.setVariable('wf_reviewerCount', memberNames.size());
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:executionListener>
|
||||
</extensionElements>
|
||||
</sequenceFlow>
|
||||
|
||||
<userTask id="reviewTask" name="Review Task"
|
||||
activiti:formKey="wf:activitiReviewTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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>
|
||||
if(task.getVariableLocal('wf_reviewOutcome') == 'Approve') {
|
||||
var newApprovedCount = wf_approveCount + 1;
|
||||
var newApprovedPercentage = (newApprovedCount / wf_reviewerCount) * 100;
|
||||
|
||||
execution.setVariable('wf_approveCount', newApprovedCount);
|
||||
execution.setVariable('wf_actualPercent', newApprovedPercentage);
|
||||
}
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${reviewAssignee}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
|
||||
<!-- For each assignee, task is created -->
|
||||
<multiInstanceLoopCharacteristics isSequential="false">
|
||||
<loopDataInputRef>wf_groupMembers</loopDataInputRef>
|
||||
<inputDataItem name="reviewAssignee" />
|
||||
<completionCondition>${wf_actualPercent >= wf_requiredApprovePercent}</completionCondition>
|
||||
</multiInstanceLoopCharacteristics>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow2'
|
||||
sourceRef='reviewTask'
|
||||
targetRef='reviewDecision' />
|
||||
|
||||
<exclusiveGateway id="reviewDecision" name="Review Decision" />
|
||||
|
||||
<sequenceFlow id='flow3' sourceRef='reviewDecision' targetRef='approved' >
|
||||
<conditionExpression xsi:type="tFormalExpression">${wf_actualPercent >= wf_requiredApprovePercent}</conditionExpression>
|
||||
</sequenceFlow>
|
||||
|
||||
<sequenceFlow id='flow4'
|
||||
sourceRef='reviewDecision'
|
||||
targetRef='rejected' />
|
||||
|
||||
<userTask id="approved" name="Document Approved"
|
||||
activiti:formKey="wf: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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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('wf_reviewerCount', wf_reviewerCount);
|
||||
task.setVariableLocal('wf_requiredPercent', wf_requiredPercent);
|
||||
task.setVariableLocal('wf_actualPercent', wf_actualPercent);
|
||||
task.setVariableLocal('wf_approveCount', wf_approveCount);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<userTask id="rejected" name="Document Rejected"
|
||||
activiti:formKey="wf: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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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('wf_reviewerCount', wf_reviewerCount);
|
||||
task.setVariableLocal('wf_requiredPercent', wf_requiredPercent);
|
||||
task.setVariableLocal('wf_actualPercent', wf_actualPercent);
|
||||
task.setVariableLocal('wf_approveCount', wf_approveCount);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow5' sourceRef='approved'
|
||||
targetRef='end' />
|
||||
|
||||
<sequenceFlow id='flow6' sourceRef='rejected'
|
||||
targetRef='end' />
|
||||
|
||||
<endEvent id="end" />
|
||||
|
||||
</process>
|
||||
|
||||
</definitions>
|
154
config/alfresco/workflow/parallel-review.bpmn20.xml
Normal file
154
config/alfresco/workflow/parallel-review.bpmn20.xml
Normal file
@@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<definitions id="review-definitions"
|
||||
typeLanguage="http://www.w3.org/2001/XMLSchema"
|
||||
expressionLanguage="http://www.w3.org/1999/XPath"
|
||||
targetNamespace="http://activiti.org/bpmn20"
|
||||
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:activiti="http://activiti.org/bpmn">
|
||||
|
||||
<process id="activitiParallelReview" name="Parallel Review And Approve Activiti Process">
|
||||
|
||||
<extensionElements>
|
||||
<activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
execution.setVariable('wf_approveCount', 0);
|
||||
execution.setVariable('wf_actualPercent', 0);
|
||||
execution.setVariable('wf_reviewerCount', bpm_assignees.size());
|
||||
execution.setVariable('wf_requiredPercent', wf_requiredApprovePercent);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:executionListener>
|
||||
</extensionElements>
|
||||
|
||||
<startEvent id="start"
|
||||
activiti:formKey="wf:submitParallelReviewTask" />
|
||||
|
||||
|
||||
<sequenceFlow id='flow1'
|
||||
sourceRef='start'
|
||||
targetRef='reviewTask' />
|
||||
|
||||
<userTask id="reviewTask" name="Review Task"
|
||||
activiti:formKey="wf:activitiReviewTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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>
|
||||
if(task.getVariableLocal('wf_reviewOutcome') == 'Approve') {
|
||||
var newApprovedCount = wf_approveCount + 1;
|
||||
var newApprovedPercentage = (newApprovedCount / wf_reviewerCount) * 100;
|
||||
|
||||
execution.setVariable('wf_approveCount', newApprovedCount);
|
||||
execution.setVariable('wf_actualPercent', newApprovedPercentage);
|
||||
}
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${review_assignee.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
|
||||
<!-- For each assignee, task is created -->
|
||||
<multiInstanceLoopCharacteristics isSequential="false">
|
||||
<loopDataInputRef>bpm_assignees</loopDataInputRef>
|
||||
<inputDataItem name="review_assignee" />
|
||||
<completionCondition>${wf_actualPercent >= wf_requiredApprovePercent}</completionCondition>
|
||||
</multiInstanceLoopCharacteristics>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow2'
|
||||
sourceRef='reviewTask'
|
||||
targetRef='reviewDecision' />
|
||||
|
||||
<exclusiveGateway id="reviewDecision" name="Review Decision" />
|
||||
|
||||
<sequenceFlow id='flow3' sourceRef='reviewDecision' targetRef='approved' >
|
||||
<conditionExpression xsi:type="tFormalExpression">${wf_actualPercent >= wf_requiredApprovePercent}</conditionExpression>
|
||||
</sequenceFlow>
|
||||
|
||||
<sequenceFlow id='flow4'
|
||||
sourceRef='reviewDecision'
|
||||
targetRef='rejected' />
|
||||
|
||||
<userTask id="approved" name="Document Approved"
|
||||
activiti:formKey="wf: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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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('wf_reviewerCount', wf_reviewerCount);
|
||||
task.setVariableLocal('wf_requiredPercent', wf_requiredPercent);
|
||||
task.setVariableLocal('wf_actualPercent', wf_actualPercent);
|
||||
task.setVariableLocal('wf_approveCount', wf_approveCount);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<userTask id="rejected" name="Document Rejected"
|
||||
activiti:formKey="wf: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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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('wf_reviewerCount', wf_reviewerCount);
|
||||
task.setVariableLocal('wf_requiredPercent', wf_requiredPercent);
|
||||
task.setVariableLocal('wf_actualPercent', wf_actualPercent);
|
||||
task.setVariableLocal('wf_approveCount', wf_approveCount);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow5' sourceRef='approved'
|
||||
targetRef='end' />
|
||||
|
||||
<sequenceFlow id='flow6' sourceRef='rejected'
|
||||
targetRef='end' />
|
||||
|
||||
<endEvent id="end" />
|
||||
|
||||
</process>
|
||||
|
||||
</definitions>
|
129
config/alfresco/workflow/review-pooled.bpmn20.xml
Normal file
129
config/alfresco/workflow/review-pooled.bpmn20.xml
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<definitions id="review-definitions"
|
||||
typeLanguage="http://www.w3.org/2001/XMLSchema"
|
||||
expressionLanguage="http://www.w3.org/1999/XPath"
|
||||
targetNamespace="http://activiti.org/bpmn20"
|
||||
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:activiti="http://activiti.org/bpmn">
|
||||
|
||||
<process id="activitiReviewPooled" name="Pooled Review And Approve Activiti Process">
|
||||
|
||||
<startEvent id="start"
|
||||
activiti:formKey="wf:submitGroupReviewTask" />
|
||||
|
||||
<sequenceFlow id='flow1'
|
||||
sourceRef='start'
|
||||
targetRef='reviewTask' />
|
||||
|
||||
<userTask id="reviewTask" name="Review Task"
|
||||
activiti:formKey="wf:activitiReviewTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariable('bpm_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>
|
||||
execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
|
||||
</extensionElements>
|
||||
<potentialOwner>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${bpm_groupAssignee.properties.authorityName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</potentialOwner>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow2'
|
||||
sourceRef='reviewTask'
|
||||
targetRef='reviewDecision' />
|
||||
|
||||
<exclusiveGateway id="reviewDecision" name="Review Decision" />
|
||||
|
||||
<sequenceFlow id='flow3' sourceRef='reviewDecision' targetRef='approved' >
|
||||
<conditionExpression xsi:type="tFormalExpression">${wf_reviewOutcome == 'Approve'}</conditionExpression>
|
||||
</sequenceFlow>
|
||||
|
||||
<sequenceFlow id='flow4'
|
||||
sourceRef='reviewDecision'
|
||||
targetRef='rejected' />
|
||||
|
||||
<userTask id="approved" name="Document Approved"
|
||||
activiti:formKey="wf:approvedTask" >
|
||||
<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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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>
|
||||
execution.setVariable('bpm_assignee', person);
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<userTask id="rejected" name="Document Rejected"
|
||||
activiti:formKey="wf:rejectedTask" >
|
||||
<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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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>
|
||||
bpm_assignee = person;
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow5' sourceRef='approved'
|
||||
targetRef='end' />
|
||||
|
||||
<sequenceFlow id='flow6' sourceRef='rejected'
|
||||
targetRef='end' />
|
||||
|
||||
<endEvent id="end" />
|
||||
|
||||
</process>
|
||||
|
||||
</definitions>
|
114
config/alfresco/workflow/review.bpmn20.xml
Normal file
114
config/alfresco/workflow/review.bpmn20.xml
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<definitions id="review-definitions"
|
||||
typeLanguage="http://www.w3.org/2001/XMLSchema"
|
||||
expressionLanguage="http://www.w3.org/1999/XPath"
|
||||
targetNamespace="http://activiti.org/bpmn20"
|
||||
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:activiti="http://activiti.org/bpmn">
|
||||
|
||||
<process id="activitiReview" name="Review And Approve Activiti Process">
|
||||
|
||||
<startEvent id="start"
|
||||
activiti:formKey="wf:submitReviewTask" />
|
||||
|
||||
<sequenceFlow id='flow1'
|
||||
sourceRef='start'
|
||||
targetRef='reviewTask' />
|
||||
|
||||
<userTask id="reviewTask" name="Review Task"
|
||||
activiti:formKey="wf:activitiReviewTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_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>
|
||||
execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${bpm_assignee.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow2'
|
||||
sourceRef='reviewTask'
|
||||
targetRef='reviewDecision' />
|
||||
|
||||
<exclusiveGateway id="reviewDecision" name="Review Decision" />
|
||||
|
||||
<sequenceFlow id='flow3' sourceRef='reviewDecision' targetRef='approved' >
|
||||
<conditionExpression xsi:type="tFormalExpression">${wf_reviewOutcome == 'Approve'}</conditionExpression>
|
||||
</sequenceFlow>
|
||||
|
||||
<sequenceFlow id='flow4'
|
||||
sourceRef='reviewDecision'
|
||||
targetRef='rejected' />
|
||||
|
||||
<userTask id="approved" name="Document Approved"
|
||||
activiti:formKey="wf:approvedTask" >
|
||||
<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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
|
||||
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<userTask id="rejected" name="Document Rejected"
|
||||
activiti:formKey="wf:rejectedTask" >
|
||||
<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>
|
||||
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
|
||||
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
|
||||
</activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
<humanPerformer>
|
||||
<resourceAssignmentExpression>
|
||||
<formalExpression>${initiator.properties.userName}</formalExpression>
|
||||
</resourceAssignmentExpression>
|
||||
</humanPerformer>
|
||||
</userTask>
|
||||
|
||||
<sequenceFlow id='flow5' sourceRef='approved'
|
||||
targetRef='end' />
|
||||
|
||||
<sequenceFlow id='flow6' sourceRef='rejected'
|
||||
targetRef='end' />
|
||||
|
||||
<endEvent id="end" />
|
||||
|
||||
</process>
|
||||
|
||||
</definitions>
|
@@ -1,5 +1,9 @@
|
||||
# Display labels for out-of-the-box Content-oriented Workflows
|
||||
|
||||
####################
|
||||
# JBPM WORKFLOWS #
|
||||
####################
|
||||
|
||||
#
|
||||
# Review & Approve Workflow
|
||||
#
|
||||
@@ -64,7 +68,9 @@ wf_workflowmodel.property.wf_requiredPercent.description=Required Approval Perce
|
||||
wf_workflowmodel.property.wf_approveCount.title=Reviewers Who Approved
|
||||
wf_workflowmodel.property.wf_approveCount.description=Reviewers who approved
|
||||
wf_workflowmodel.property.wf_actualPercent.title=Actual Approval Percentage
|
||||
wf_workflowmodel.property.wf_actualPercentdescription=Actual approval percentage
|
||||
wf_workflowmodel.property.wf_actualPercent.description=Actual approval percentage
|
||||
wf_workflowmodel.property.wf_reviewOutcome.title=Review Outcome
|
||||
wf_workflowmodel.property.wf_reviewOutcome.description=Review Outcome
|
||||
|
||||
# Group Review & Approve Process Definitions
|
||||
|
||||
@@ -120,3 +126,60 @@ wf_workflowmodel.type.wf_adhocTask.title=Adhoc Task
|
||||
wf_workflowmodel.type.wf_adhocTask.description=Adhoc Task allocated by colleague
|
||||
wf_workflowmodel.type.wf_completedAdhocTask.title=Adhoc Task Completed
|
||||
wf_workflowmodel.type.wf_completedAdhocTask.description=Adhoc Task Completed
|
||||
|
||||
#######################
|
||||
# ACTIVITI WORKFLOWS #
|
||||
#######################
|
||||
|
||||
#
|
||||
# Activiti Adhoc Task Workflow
|
||||
#
|
||||
|
||||
activitiAdhoc.workflow.title=Activiti Adhoc
|
||||
activitiAdhoc.workflow.description=Assign Activiti task to colleague
|
||||
|
||||
# Activiti Adhoc Task Definitions
|
||||
|
||||
activitiAdhocmodel.type.wf_submitAdhocTask.title=Start Activiti Adhoc Task
|
||||
activitiAdhocmodel.type.wf_submitAdhocTask.description=Allocate Activiti task to colleague
|
||||
activitiAdhocmodel.property.wf_notifyMe.title=Notify Me
|
||||
activitiAdhocmodel.property.wf_notifyMe.description=Notify me when task is complete
|
||||
activitiAdhocmodel.type.wf_adhocTask.title=Activiti Adhoc Task
|
||||
activitiAdhocmodel.type.wf_adhocTask.description=Activiti Adhoc Task allocated by colleague
|
||||
activitiAdhocmodel.type.wf_completedAdhocTask.title=Activiti Adhoc Task Completed
|
||||
activitiAdhocmodel.type.wf_completedAdhocTask.description=Activiti Adhoc Task Completed
|
||||
|
||||
#
|
||||
# Activiti Review & Approve Workflow
|
||||
#
|
||||
|
||||
activitiReview.workflow.title=Activiti Review & Approve
|
||||
activitiReview.workflow.description=Review & approval of content
|
||||
|
||||
# Activiti Review & Approve Task Definitions
|
||||
|
||||
activitiReviewmodel.type.wf_submitReviewTask.title=Start Activiti Review
|
||||
activitiReviewmodel.type.wf_submitReviewTask.description=Submit documents for review & approval
|
||||
activitiReviewmodel.type.wf_reviewTask.title=Activiti Review
|
||||
activitiReviewmodel.type.wf_reviewTask.description=Review Documents to Approve or Reject them
|
||||
activitiReviewmodel.type.wf_rejectedTask.title=Rejected
|
||||
activitiReviewmodel.type.wf_rejectedTask.description=Rejected
|
||||
activitiReviewmodel.type.wf_approvedTask.title=Approved
|
||||
activitiReviewmodel.type.wf_approvedTask.description=Approved
|
||||
|
||||
# Activiti Review & Approve Process Definitions
|
||||
|
||||
activitiReview.node.start.title=Start
|
||||
activitiReview.node.start.description=Start
|
||||
activitiReview.node.review.title=Review
|
||||
activitiReview.node.review.description=Review
|
||||
activitiReview.node.rejected.title=Rejected
|
||||
activitiReview.node.rejected.description=Rejected
|
||||
activitiReview.task.wf_rejectedTask.title=Rejected
|
||||
wf_review.task.wf_rejectedTask.description=Rejected
|
||||
activitiReview.node.approved.title=Approved
|
||||
activitiReview.node.approved.description=Approved
|
||||
activitiReview.task.wf_approvedTask.title=Approved
|
||||
activitiReview.task.wf_approvedTask.description=Approved
|
||||
activitiReview.node.end.title=End
|
||||
activitiReview.node.end.description=End
|
||||
|
@@ -66,6 +66,36 @@
|
||||
</overrides>
|
||||
</type>
|
||||
|
||||
<type name="wf:activitiReviewTask">
|
||||
<parent>bpm:activitiOutcomeTask</parent>
|
||||
<properties>
|
||||
<property name="wf:reviewOutcome">
|
||||
<type>d:text</type>
|
||||
<default>Reject</default>
|
||||
<constraints>
|
||||
<constraint type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<!-- TODO: Determine if priority values can
|
||||
be mapped to human-readable strings -->
|
||||
<list>
|
||||
<value>Approve</value>
|
||||
<value>Reject</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
</property>
|
||||
</properties>
|
||||
<overrides>
|
||||
<property name="bpm:packageItemActionGroup">
|
||||
<default>edit_package_item_actions</default>
|
||||
</property>
|
||||
<property name="bpm:outcomePropertyName">
|
||||
<default>{http://www.alfresco.org/model/workflow/1.0}reviewOutcome</default>
|
||||
</property>
|
||||
</overrides>
|
||||
</type>
|
||||
|
||||
<type name="wf:approvedTask">
|
||||
<parent>bpm:workflowTask</parent>
|
||||
<mandatory-aspects>
|
||||
|
Reference in New Issue
Block a user