Skip to content

Commit e1e4fa7

Browse files
authored
Merge pull request #442 from sartography/feature/user-form-task-data-variable
add user task form variable
2 parents 9b50630 + cc6f137 commit e1e4fa7

File tree

6 files changed

+184
-4
lines changed

6 files changed

+184
-4
lines changed

SpiffWorkflow/spiff/parser/process.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
CallActivityParser,
5353
ServiceTaskParser,
5454
ScriptTaskParser,
55-
BusinessRuleTaskParser
55+
BusinessRuleTaskParser,
56+
UserTaskParser,
5657
)
5758
from SpiffWorkflow.spiff.parser.event_parsers import (
5859
SpiffStartEventParser,
@@ -94,5 +95,6 @@ class SpiffBpmnParser(BpmnDmnParser):
9495
full_tag('intermediateThrowEvent'): (SpiffIntermediateThrowEventParser, IntermediateThrowEvent),
9596
full_tag('sendTask'): (SpiffSendTaskParser, SendTask),
9697
full_tag('receiveTask'): (SpiffReceiveTaskParser, ReceiveTask),
97-
full_tag('businessRuleTask'): (BusinessRuleTaskParser, BusinessRuleTask)
98+
full_tag('businessRuleTask'): (BusinessRuleTaskParser, BusinessRuleTask),
99+
full_tag('userTask'): (UserTaskParser, UserTask),
98100
}

SpiffWorkflow/spiff/parser/task_spec.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
StandardLoopTask,
2828
ParallelMultiInstanceTask,
2929
SequentialMultiInstanceTask,
30-
BusinessRuleTask
30+
BusinessRuleTask,
31+
UserTask,
3132
)
3233

3334
SPIFFWORKFLOW_NSMAP = {'spiffworkflow': 'http://spiffworkflow.org/bpmn/schema/1.0/core'}
@@ -203,3 +204,20 @@ def create_task(self):
203204
def get_decision_ref(node):
204205
extensions = SpiffTaskParser._parse_extensions(node)
205206
return extensions.get('calledDecisionId')
207+
208+
class UserTaskParser(SpiffTaskParser):
209+
210+
def create_task(self):
211+
extensions = self.parse_extensions()
212+
variable = extensions.get('variableName')
213+
prescript = extensions.get('preScript')
214+
postscript = extensions.get('postScript')
215+
return UserTask(
216+
self.spec,
217+
self.bpmn_id,
218+
variable=variable,
219+
prescript=prescript,
220+
postscript=postscript,
221+
**self.bpmn_attributes,
222+
)
223+

SpiffWorkflow/spiff/specs/defaults.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
# 02110-1301 USA
1919

2020
from SpiffWorkflow.bpmn.specs.mixins import (
21-
UserTaskMixin,
2221
ManualTaskMixin,
2322
NoneTaskMixin,
2423
ScriptTaskMixin,
@@ -34,6 +33,7 @@
3433
from SpiffWorkflow.dmn.specs import BusinessRuleTaskMixin
3534

3635
from .mixins.service_task import ServiceTask as ServiceTaskMixin
36+
from .mixins.user_task import UserTask as UserTaskMixin
3737
from .spiff_task import SpiffBpmnTask
3838

3939

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (C) 2025 Sartography
2+
#
3+
# This file is part of SpiffWorkflow.
4+
#
5+
# SpiffWorkflow is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU Lesser General Public
7+
# License as published by the Free Software Foundation; either
8+
# version 3.0 of the License, or (at your option) any later version.
9+
#
10+
# SpiffWorkflow is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
# Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with this library; if not, write to the Free Software
17+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
# 02110-1301 USA
19+
20+
21+
from SpiffWorkflow.bpmn.specs.mixins.user_task import UserTask
22+
from SpiffWorkflow.util.deep_merge import DeepMerge
23+
24+
class UserTask(UserTask):
25+
def __init__(self, wf_spec, bpmn_id, variable=None, **kwargs):
26+
super().__init__(wf_spec, bpmn_id, **kwargs)
27+
self.variable = variable
28+
29+
def add_data_from_form(self, my_task, data):
30+
if self.variable is not None:
31+
my_task.set_data(**{self.variable: data})
32+
else:
33+
DeepMerge.merge(my_task.data, data)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from SpiffWorkflow.util.task import TaskState
2+
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
3+
from .BaseTestCase import BaseTestCase
4+
5+
6+
class UserTaskTest(BaseTestCase):
7+
8+
def setUp(self):
9+
pass
10+
11+
def testVariable(self):
12+
workflow = self.run_workflow('one')
13+
self.assertIn('order', workflow.data)
14+
15+
def testNoVariable(self):
16+
workflow = self.run_workflow('two')
17+
self.assertIn('size', workflow.data)
18+
self.assertIn('toppings', workflow.data)
19+
20+
def run_workflow(self, process_id):
21+
spec, subprocesses = self.load_workflow_spec('user_task_variable.bpmn', process_id)
22+
workflow = BpmnWorkflow(spec, subprocesses)
23+
workflow.do_engine_steps()
24+
task = workflow.get_next_task(state=TaskState.READY)
25+
order = {
26+
'size': 'large',
27+
'toppings': [
28+
'sausage',
29+
'onions',
30+
'peppers',
31+
],
32+
}
33+
task.task_spec.add_data_from_form(task, order)
34+
task.run()
35+
workflow.do_engine_steps()
36+
return workflow
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1qnx3d3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
3+
<bpmn:collaboration id="Collaboration_11rypv4">
4+
<bpmn:participant id="Participant_190ghs2" processRef="two" />
5+
<bpmn:participant id="Participant_0kga0m3" processRef="one" />
6+
</bpmn:collaboration>
7+
<bpmn:process id="two" isExecutable="true">
8+
<bpmn:startEvent id="StartEvent_1">
9+
<bpmn:outgoing>Flow_0vt1twq</bpmn:outgoing>
10+
</bpmn:startEvent>
11+
<bpmn:endEvent id="Event_0yxpeto">
12+
<bpmn:incoming>Flow_00ilv2d</bpmn:incoming>
13+
</bpmn:endEvent>
14+
<bpmn:userTask id="user_task_one" name="User Task">
15+
<bpmn:extensionElements>
16+
<spiffworkflow:properties>
17+
<spiffworkflow:property name="formJsonSchemaFilename" value="pizza_form.json" />
18+
</spiffworkflow:properties>
19+
<spiffworkflow:variableName />
20+
</bpmn:extensionElements>
21+
<bpmn:incoming>Flow_0vt1twq</bpmn:incoming>
22+
<bpmn:outgoing>Flow_00ilv2d</bpmn:outgoing>
23+
</bpmn:userTask>
24+
<bpmn:sequenceFlow id="Flow_0vt1twq" sourceRef="StartEvent_1" targetRef="user_task_one" />
25+
<bpmn:sequenceFlow id="Flow_00ilv2d" sourceRef="user_task_one" targetRef="Event_0yxpeto" />
26+
</bpmn:process>
27+
<bpmn:process id="one" isExecutable="true">
28+
<bpmn:startEvent id="Event_0pincx2">
29+
<bpmn:outgoing>Flow_0qcvsqc</bpmn:outgoing>
30+
</bpmn:startEvent>
31+
<bpmn:endEvent id="Event_0wyj6uh">
32+
<bpmn:incoming>Flow_1cmc5fv</bpmn:incoming>
33+
</bpmn:endEvent>
34+
<bpmn:userTask id="user_task_two" name="User Task">
35+
<bpmn:extensionElements>
36+
<spiffworkflow:properties>
37+
<spiffworkflow:property name="formJsonSchemaFilename" value="pizza_form.json" />
38+
</spiffworkflow:properties>
39+
<spiffworkflow:variableName>order</spiffworkflow:variableName>
40+
</bpmn:extensionElements>
41+
<bpmn:incoming>Flow_0qcvsqc</bpmn:incoming>
42+
<bpmn:outgoing>Flow_1cmc5fv</bpmn:outgoing>
43+
</bpmn:userTask>
44+
<bpmn:sequenceFlow id="Flow_0qcvsqc" sourceRef="Event_0pincx2" targetRef="user_task_two" />
45+
<bpmn:sequenceFlow id="Flow_1cmc5fv" sourceRef="user_task_two" targetRef="Event_0wyj6uh" />
46+
</bpmn:process>
47+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
48+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_11rypv4">
49+
<bpmndi:BPMNShape id="Participant_190ghs2_di" bpmnElement="Participant_190ghs2" isHorizontal="true">
50+
<dc:Bounds x="92" y="30" width="600" height="250" />
51+
</bpmndi:BPMNShape>
52+
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
53+
<dc:Bounds x="232" y="122" width="36" height="36" />
54+
</bpmndi:BPMNShape>
55+
<bpmndi:BPMNShape id="Event_0yxpeto_di" bpmnElement="Event_0yxpeto">
56+
<dc:Bounds x="512" y="122" width="36" height="36" />
57+
</bpmndi:BPMNShape>
58+
<bpmndi:BPMNShape id="Activity_08ynz71_di" bpmnElement="user_task">
59+
<dc:Bounds x="330" y="100" width="100" height="80" />
60+
</bpmndi:BPMNShape>
61+
<bpmndi:BPMNEdge id="Flow_0vt1twq_di" bpmnElement="Flow_0vt1twq">
62+
<di:waypoint x="268" y="140" />
63+
<di:waypoint x="330" y="140" />
64+
</bpmndi:BPMNEdge>
65+
<bpmndi:BPMNEdge id="Flow_00ilv2d_di" bpmnElement="Flow_00ilv2d">
66+
<di:waypoint x="430" y="140" />
67+
<di:waypoint x="512" y="140" />
68+
</bpmndi:BPMNEdge>
69+
<bpmndi:BPMNShape id="BPMNShape_1d6xazy" bpmnElement="Participant_0kga0m3" isHorizontal="true">
70+
<dc:Bounds x="92" y="-240" width="600" height="250" />
71+
</bpmndi:BPMNShape>
72+
<bpmndi:BPMNShape id="BPMNShape_0ouulug" bpmnElement="Event_0pincx2">
73+
<dc:Bounds x="232" y="-148" width="36" height="36" />
74+
</bpmndi:BPMNShape>
75+
<bpmndi:BPMNShape id="BPMNShape_0j6zfji" bpmnElement="Event_0wyj6uh">
76+
<dc:Bounds x="512" y="-148" width="36" height="36" />
77+
</bpmndi:BPMNShape>
78+
<bpmndi:BPMNShape id="BPMNShape_0rfd4sd" bpmnElement="user_task_two">
79+
<dc:Bounds x="330" y="-170" width="100" height="80" />
80+
</bpmndi:BPMNShape>
81+
<bpmndi:BPMNEdge id="BPMNEdge_0dyifou" bpmnElement="Flow_0qcvsqc">
82+
<di:waypoint x="268" y="-130" />
83+
<di:waypoint x="330" y="-130" />
84+
</bpmndi:BPMNEdge>
85+
<bpmndi:BPMNEdge id="BPMNEdge_1r3h3hf" bpmnElement="Flow_1cmc5fv">
86+
<di:waypoint x="430" y="-130" />
87+
<di:waypoint x="512" y="-130" />
88+
</bpmndi:BPMNEdge>
89+
</bpmndi:BPMNPlane>
90+
</bpmndi:BPMNDiagram>
91+
</bpmn:definitions>

0 commit comments

Comments
 (0)