Squashed 'spiffworkflow-backend/' changes from ab9b5f36..7f1776b5
7f1776b5 Merge pull request #161 from sartography/feature/potential_owners_from_task_data d19477e3 test removing an approver from a list while user lane_owners dict w/ burnettk 2f333204 resolved merge conflicts w/ burnettk 6b9c248b Merge remote-tracking branch 'origin/main' into feature/potential_owners_from_task_data 24a96ccd WIP: deleting user after approval w/ burnettk 8659f212 pyl now passes w/ burnettk e9ef5bfe Merge remote-tracking branch 'origin/main' into feature/potential_owners_from_task_data 56f8d734 added some support to get the potential task owners from task data w/ burnettk git-subtree-dir: spiffworkflow-backend git-subtree-split: 7f1776b5b7f11ae6c02ef435200b0ba87219d7d2
This commit is contained in:
parent
e228ab4b80
commit
d7e8533061
|
@ -0,0 +1,26 @@
|
||||||
|
"""Get_env."""
|
||||||
|
from typing import Any
|
||||||
|
from flask import g
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
|
||||||
|
|
||||||
|
from spiffworkflow_backend.scripts.script import Script
|
||||||
|
|
||||||
|
|
||||||
|
class GetUser(Script):
|
||||||
|
"""GetUser."""
|
||||||
|
|
||||||
|
def get_description(self) -> str:
|
||||||
|
"""Get_description."""
|
||||||
|
return """Return the current user."""
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self,
|
||||||
|
task: Optional[SpiffTask],
|
||||||
|
environment_identifier: str,
|
||||||
|
*_args: Any,
|
||||||
|
**kwargs: Any
|
||||||
|
) -> Any:
|
||||||
|
"""Run."""
|
||||||
|
return g.user.username
|
|
@ -14,6 +14,7 @@ from typing import List
|
||||||
from typing import NewType
|
from typing import NewType
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
from typing import TypedDict
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
@ -75,6 +76,7 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
|
||||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||||
from spiffworkflow_backend.models.task_event import TaskAction
|
from spiffworkflow_backend.models.task_event import TaskAction
|
||||||
from spiffworkflow_backend.models.task_event import TaskEventModel
|
from spiffworkflow_backend.models.task_event import TaskEventModel
|
||||||
|
from spiffworkflow_backend.models.user import UserModel
|
||||||
from spiffworkflow_backend.models.user import UserModelSchema
|
from spiffworkflow_backend.models.user import UserModelSchema
|
||||||
from spiffworkflow_backend.scripts.script import Script
|
from spiffworkflow_backend.scripts.script import Script
|
||||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||||
|
@ -106,6 +108,13 @@ DEFAULT_GLOBALS.update(safe_globals)
|
||||||
DEFAULT_GLOBALS["__builtins__"]["__import__"] = _import
|
DEFAULT_GLOBALS["__builtins__"]["__import__"] = _import
|
||||||
|
|
||||||
|
|
||||||
|
class PotentialOwnerIdList(TypedDict):
|
||||||
|
"""PotentialOwnerIdList."""
|
||||||
|
|
||||||
|
potential_owner_ids: list[int]
|
||||||
|
lane_assignment_id: Optional[int]
|
||||||
|
|
||||||
|
|
||||||
class ProcessInstanceProcessorError(Exception):
|
class ProcessInstanceProcessorError(Exception):
|
||||||
"""ProcessInstanceProcessorError."""
|
"""ProcessInstanceProcessorError."""
|
||||||
|
|
||||||
|
@ -114,6 +123,10 @@ class NoPotentialOwnersForTaskError(Exception):
|
||||||
"""NoPotentialOwnersForTaskError."""
|
"""NoPotentialOwnersForTaskError."""
|
||||||
|
|
||||||
|
|
||||||
|
class PotentialOwnerUserNotFoundError(Exception):
|
||||||
|
"""PotentialOwnerUserNotFoundError."""
|
||||||
|
|
||||||
|
|
||||||
class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
|
class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
|
||||||
"""This is a custom script processor that can be easily injected into Spiff Workflow.
|
"""This is a custom script processor that can be easily injected into Spiff Workflow.
|
||||||
|
|
||||||
|
@ -499,6 +512,58 @@ class ProcessInstanceProcessor:
|
||||||
|
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
def raise_if_no_potential_owners(
|
||||||
|
self, potential_owner_ids: list[int], message: str
|
||||||
|
) -> None:
|
||||||
|
"""Raise_if_no_potential_owners."""
|
||||||
|
if not potential_owner_ids:
|
||||||
|
raise (NoPotentialOwnersForTaskError(message))
|
||||||
|
|
||||||
|
def get_potential_owner_ids_from_task(
|
||||||
|
self, task: SpiffTask
|
||||||
|
) -> PotentialOwnerIdList:
|
||||||
|
"""Get_potential_owner_ids_from_task."""
|
||||||
|
task_spec = task.task_spec
|
||||||
|
task_lane = "process_initiator"
|
||||||
|
if task_spec.lane is not None and task_spec.lane != "":
|
||||||
|
task_lane = task_spec.lane
|
||||||
|
|
||||||
|
potential_owner_ids = []
|
||||||
|
lane_assignment_id = None
|
||||||
|
if re.match(r"(process.?)initiator", task_lane, re.IGNORECASE):
|
||||||
|
potential_owner_ids = [self.process_instance_model.process_initiator_id]
|
||||||
|
elif "lane_owners" in task.data and task_lane in task.data["lane_owners"]:
|
||||||
|
for username in task.data["lane_owners"][task_lane]:
|
||||||
|
lane_owner_user = UserModel.query.filter_by(username=username).first()
|
||||||
|
if lane_owner_user is not None:
|
||||||
|
potential_owner_ids.append(lane_owner_user.id)
|
||||||
|
self.raise_if_no_potential_owners(
|
||||||
|
potential_owner_ids,
|
||||||
|
f"No users found in task data lane owner list for lane: {task_lane}. "
|
||||||
|
f"The user list used: {task.data['lane_owners'][task_lane]}",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
group_model = GroupModel.query.filter_by(identifier=task_lane).first()
|
||||||
|
if group_model is None:
|
||||||
|
raise (
|
||||||
|
NoPotentialOwnersForTaskError(
|
||||||
|
f"Could not find a group with name matching lane: {task_lane}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
potential_owner_ids = [
|
||||||
|
i.user_id for i in group_model.user_group_assignments
|
||||||
|
]
|
||||||
|
lane_assignment_id = group_model.id
|
||||||
|
self.raise_if_no_potential_owners(
|
||||||
|
potential_owner_ids,
|
||||||
|
f"Could not find any users in group to assign to lane: {task_lane}",
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"potential_owner_ids": potential_owner_ids,
|
||||||
|
"lane_assignment_id": lane_assignment_id,
|
||||||
|
}
|
||||||
|
|
||||||
def save(self) -> None:
|
def save(self) -> None:
|
||||||
"""Saves the current state of this processor to the database."""
|
"""Saves the current state of this processor to the database."""
|
||||||
self.process_instance_model.bpmn_json = self.serialize()
|
self.process_instance_model.bpmn_json = self.serialize()
|
||||||
|
@ -532,32 +597,9 @@ class ProcessInstanceProcessor:
|
||||||
# filter out non-usertasks
|
# filter out non-usertasks
|
||||||
task_spec = ready_or_waiting_task.task_spec
|
task_spec = ready_or_waiting_task.task_spec
|
||||||
if not self.bpmn_process_instance._is_engine_task(task_spec):
|
if not self.bpmn_process_instance._is_engine_task(task_spec):
|
||||||
ready_or_waiting_task.data["current_user"]["id"]
|
potential_owner_hash = self.get_potential_owner_ids_from_task(
|
||||||
task_lane = "process_initiator"
|
ready_or_waiting_task
|
||||||
if task_spec.lane is not None and task_spec.lane != "":
|
)
|
||||||
task_lane = task_spec.lane
|
|
||||||
|
|
||||||
potential_owner_ids = []
|
|
||||||
lane_assignment_id = None
|
|
||||||
if re.match(r"(process.?)initiator", task_lane, re.IGNORECASE):
|
|
||||||
potential_owner_ids = [
|
|
||||||
self.process_instance_model.process_initiator_id
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
group_model = GroupModel.query.filter_by(
|
|
||||||
identifier=task_lane
|
|
||||||
).first()
|
|
||||||
if group_model is None:
|
|
||||||
raise (
|
|
||||||
NoPotentialOwnersForTaskError(
|
|
||||||
f"Could not find a group with name matching lane: {task_lane}"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
potential_owner_ids = [
|
|
||||||
i.user_id for i in group_model.user_group_assignments
|
|
||||||
]
|
|
||||||
lane_assignment_id = group_model.id
|
|
||||||
|
|
||||||
extensions = ready_or_waiting_task.task_spec.extensions
|
extensions = ready_or_waiting_task.task_spec.extensions
|
||||||
|
|
||||||
form_file_name = None
|
form_file_name = None
|
||||||
|
@ -586,12 +628,12 @@ class ProcessInstanceProcessor:
|
||||||
task_title=ready_or_waiting_task.task_spec.description,
|
task_title=ready_or_waiting_task.task_spec.description,
|
||||||
task_type=ready_or_waiting_task.task_spec.__class__.__name__,
|
task_type=ready_or_waiting_task.task_spec.__class__.__name__,
|
||||||
task_status=ready_or_waiting_task.get_state_name(),
|
task_status=ready_or_waiting_task.get_state_name(),
|
||||||
lane_assignment_id=lane_assignment_id,
|
lane_assignment_id=potential_owner_hash["lane_assignment_id"],
|
||||||
)
|
)
|
||||||
db.session.add(active_task)
|
db.session.add(active_task)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
for potential_owner_id in potential_owner_ids:
|
for potential_owner_id in potential_owner_hash["potential_owner_ids"]:
|
||||||
active_task_user = ActiveTaskUserModel(
|
active_task_user = ActiveTaskUserModel(
|
||||||
user_id=potential_owner_id, active_task_id=active_task.id
|
user_id=potential_owner_id, active_task_id=active_task.id
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||||
|
<bpmn:collaboration id="Collaboration_0iyw0q7">
|
||||||
|
<bpmn:participant id="Participant_17eqap4" processRef="Proccess_yhito9d" />
|
||||||
|
</bpmn:collaboration>
|
||||||
|
<bpmn:process id="Proccess_yhito9d" isExecutable="true">
|
||||||
|
<bpmn:laneSet id="LaneSet_17rankp">
|
||||||
|
<bpmn:lane id="process_initiator" name="Process Initiator">
|
||||||
|
<bpmn:flowNodeRef>StartEvent_1</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>initator_one</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>initiator_two</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>Activity_0wq6mdd</bpmn:flowNodeRef>
|
||||||
|
</bpmn:lane>
|
||||||
|
<bpmn:lane id="finance_team" name="Finance Team">
|
||||||
|
<bpmn:flowNodeRef>finance_approval_one</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>finance_approval_two</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>Activity_1s1855p</bpmn:flowNodeRef>
|
||||||
|
</bpmn:lane>
|
||||||
|
<bpmn:lane id="bigwig" name="Bigwig">
|
||||||
|
<bpmn:flowNodeRef>Event_0nsh6vv</bpmn:flowNodeRef>
|
||||||
|
<bpmn:flowNodeRef>bigwig_approval</bpmn:flowNodeRef>
|
||||||
|
</bpmn:lane>
|
||||||
|
</bpmn:laneSet>
|
||||||
|
<bpmn:startEvent id="StartEvent_1">
|
||||||
|
<bpmn:outgoing>Flow_1tbyols</bpmn:outgoing>
|
||||||
|
</bpmn:startEvent>
|
||||||
|
<bpmn:sequenceFlow id="Flow_1tbyols" sourceRef="StartEvent_1" targetRef="initator_one" />
|
||||||
|
<bpmn:manualTask id="initator_one" name="Initiator One">
|
||||||
|
<bpmn:extensionElements>
|
||||||
|
<spiffworkflow:instructionsForEndUser>This is initiator user?</spiffworkflow:instructionsForEndUser>
|
||||||
|
</bpmn:extensionElements>
|
||||||
|
<bpmn:incoming>Flow_1tbyols</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0xyca1b</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0jh05kw" sourceRef="initiator_two" targetRef="bigwig_approval" />
|
||||||
|
<bpmn:sequenceFlow id="Flow_04sc2wb" sourceRef="bigwig_approval" targetRef="Event_0nsh6vv" />
|
||||||
|
<bpmn:sequenceFlow id="Flow_0xyca1b" sourceRef="initator_one" targetRef="Activity_0wq6mdd" />
|
||||||
|
<bpmn:manualTask id="initiator_two" name="Initiator Two">
|
||||||
|
<bpmn:extensionElements>
|
||||||
|
<spiffworkflow:instructionsForEndUser>This is initiator again?</spiffworkflow:instructionsForEndUser>
|
||||||
|
</bpmn:extensionElements>
|
||||||
|
<bpmn:incoming>Flow_1aluose</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0jh05kw</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:endEvent id="Event_0nsh6vv">
|
||||||
|
<bpmn:incoming>Flow_04sc2wb</bpmn:incoming>
|
||||||
|
</bpmn:endEvent>
|
||||||
|
<bpmn:manualTask id="bigwig_approval" name="Bigwig Approval">
|
||||||
|
<bpmn:incoming>Flow_0jh05kw</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_04sc2wb</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_13ejjwk" sourceRef="Activity_0wq6mdd" targetRef="finance_approval_one" />
|
||||||
|
<bpmn:scriptTask id="Activity_0wq6mdd" name="Set Potential Owners For Lanes" scriptFormat="python">
|
||||||
|
<bpmn:incoming>Flow_0xyca1b</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_13ejjwk</bpmn:outgoing>
|
||||||
|
<bpmn:script>lane_owners = {
|
||||||
|
"Finance Team": ['testuser3', 'testuser4'],
|
||||||
|
"Bigwig": ['testadmin1'],
|
||||||
|
"Process Initiator": ['testadmin1']
|
||||||
|
}</bpmn:script>
|
||||||
|
</bpmn:scriptTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_1aluose" sourceRef="finance_approval_two" targetRef="initiator_two" />
|
||||||
|
<bpmn:manualTask id="finance_approval_one" name="Finance Approval One">
|
||||||
|
<bpmn:extensionElements>
|
||||||
|
<spiffworkflow:instructionsForEndUser>This is finance user one?</spiffworkflow:instructionsForEndUser>
|
||||||
|
<spiffworkflow:postScript />
|
||||||
|
<spiffworkflow:preScript />
|
||||||
|
</bpmn:extensionElements>
|
||||||
|
<bpmn:incoming>Flow_13ejjwk</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_0bgkfue</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:manualTask id="finance_approval_two" name="Finance Approval Two">
|
||||||
|
<bpmn:extensionElements>
|
||||||
|
<spiffworkflow:instructionsForEndUser>This is finance user two? {{approver}}</spiffworkflow:instructionsForEndUser>
|
||||||
|
</bpmn:extensionElements>
|
||||||
|
<bpmn:incoming>Flow_1ivhu7x</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_1aluose</bpmn:outgoing>
|
||||||
|
</bpmn:manualTask>
|
||||||
|
<bpmn:sequenceFlow id="Flow_0bgkfue" sourceRef="finance_approval_one" targetRef="Activity_1s1855p" />
|
||||||
|
<bpmn:sequenceFlow id="Flow_1ivhu7x" sourceRef="Activity_1s1855p" targetRef="finance_approval_two" />
|
||||||
|
<bpmn:scriptTask id="Activity_1s1855p" scriptFormat="python">
|
||||||
|
<bpmn:incoming>Flow_0bgkfue</bpmn:incoming>
|
||||||
|
<bpmn:outgoing>Flow_1ivhu7x</bpmn:outgoing>
|
||||||
|
<bpmn:script>approver = get_user()
|
||||||
|
lane_owners["Finance Team"].remove(approver)</bpmn:script>
|
||||||
|
</bpmn:scriptTask>
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0iyw0q7">
|
||||||
|
<bpmndi:BPMNShape id="Participant_17eqap4_di" bpmnElement="Participant_17eqap4" isHorizontal="true">
|
||||||
|
<dc:Bounds x="129" y="-68" width="600" height="490" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_0ih9iki_di" bpmnElement="bigwig" isHorizontal="true">
|
||||||
|
<dc:Bounds x="159" y="-68" width="570" height="120" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_0irvyol_di" bpmnElement="finance_team" isHorizontal="true">
|
||||||
|
<dc:Bounds x="159" y="302" width="570" height="120" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_1ewsife_di" bpmnElement="process_initiator" isHorizontal="true">
|
||||||
|
<dc:Bounds x="159" y="52" width="570" height="250" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||||
|
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1lm1ald_di" bpmnElement="initator_one">
|
||||||
|
<dc:Bounds x="270" y="137" width="100" height="80" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1c1xxe3_di" bpmnElement="initiator_two">
|
||||||
|
<dc:Bounds x="550" y="137" width="100" height="80" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Event_0nsh6vv_di" bpmnElement="Event_0nsh6vv">
|
||||||
|
<dc:Bounds x="672" y="-28" width="36" height="36" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1i20328_di" bpmnElement="bigwig_approval">
|
||||||
|
<dc:Bounds x="550" y="-50" width="100" height="80" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1xdc8g9_di" bpmnElement="Activity_0wq6mdd">
|
||||||
|
<dc:Bounds x="420" y="140" width="100" height="80" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1y566d5_di" bpmnElement="finance_approval_one">
|
||||||
|
<dc:Bounds x="340" y="320" width="100" height="80" />
|
||||||
|
<bpmndi:BPMNLabel />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_1rq1fsj_di" bpmnElement="finance_approval_two">
|
||||||
|
<dc:Bounds x="600" y="320" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_0g8uv6m_di" bpmnElement="Activity_1s1855p">
|
||||||
|
<dc:Bounds x="470" y="320" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_1tbyols_di" bpmnElement="Flow_1tbyols">
|
||||||
|
<di:waypoint x="215" y="177" />
|
||||||
|
<di:waypoint x="270" y="177" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0jh05kw_di" bpmnElement="Flow_0jh05kw">
|
||||||
|
<di:waypoint x="600" y="137" />
|
||||||
|
<di:waypoint x="600" y="30" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_04sc2wb_di" bpmnElement="Flow_04sc2wb">
|
||||||
|
<di:waypoint x="650" y="-10" />
|
||||||
|
<di:waypoint x="672" y="-10" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0xyca1b_di" bpmnElement="Flow_0xyca1b">
|
||||||
|
<di:waypoint x="370" y="179" />
|
||||||
|
<di:waypoint x="420" y="180" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_13ejjwk_di" bpmnElement="Flow_13ejjwk">
|
||||||
|
<di:waypoint x="460" y="220" />
|
||||||
|
<di:waypoint x="460" y="270" />
|
||||||
|
<di:waypoint x="380" y="270" />
|
||||||
|
<di:waypoint x="380" y="320" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_1aluose_di" bpmnElement="Flow_1aluose">
|
||||||
|
<di:waypoint x="650" y="320" />
|
||||||
|
<di:waypoint x="650" y="269" />
|
||||||
|
<di:waypoint x="600" y="269" />
|
||||||
|
<di:waypoint x="600" y="217" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0bgkfue_di" bpmnElement="Flow_0bgkfue">
|
||||||
|
<di:waypoint x="440" y="360" />
|
||||||
|
<di:waypoint x="470" y="360" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_1ivhu7x_di" bpmnElement="Flow_1ivhu7x">
|
||||||
|
<di:waypoint x="570" y="360" />
|
||||||
|
<di:waypoint x="600" y="360" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</bpmn:definitions>
|
|
@ -94,6 +94,8 @@ class TestAuthorizationService(BaseTest):
|
||||||
"""Test_user_can_be_added_to_active_task_on_first_login."""
|
"""Test_user_can_be_added_to_active_task_on_first_login."""
|
||||||
initiator_user = self.find_or_create_user("initiator_user")
|
initiator_user = self.find_or_create_user("initiator_user")
|
||||||
assert initiator_user.principal is not None
|
assert initiator_user.principal is not None
|
||||||
|
# to ensure there is a user that can be assigned to the task
|
||||||
|
self.find_or_create_user("testuser1")
|
||||||
AuthorizationService.import_permissions_from_yaml_file()
|
AuthorizationService.import_permissions_from_yaml_file()
|
||||||
|
|
||||||
process_model = load_test_spec(
|
process_model = load_test_spec(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Test_process_instance_processor."""
|
"""Test_process_instance_processor."""
|
||||||
import pytest
|
import pytest
|
||||||
|
from flask import g
|
||||||
from flask.app import Flask
|
from flask.app import Flask
|
||||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||||
|
@ -118,3 +119,108 @@ class TestProcessInstanceProcessor(BaseTest):
|
||||||
)
|
)
|
||||||
|
|
||||||
assert process_instance.status == ProcessInstanceStatus.complete.value
|
assert process_instance.status == ProcessInstanceStatus.complete.value
|
||||||
|
|
||||||
|
def test_sets_permission_correctly_on_active_task_when_using_dict(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test_sets_permission_correctly_on_active_task_when_using_dict."""
|
||||||
|
initiator_user = self.find_or_create_user("initiator_user")
|
||||||
|
finance_user_three = self.find_or_create_user("testuser3")
|
||||||
|
finance_user_four = self.find_or_create_user("testuser4")
|
||||||
|
testadmin1 = self.find_or_create_user("testadmin1")
|
||||||
|
assert initiator_user.principal is not None
|
||||||
|
assert finance_user_three.principal is not None
|
||||||
|
AuthorizationService.import_permissions_from_yaml_file()
|
||||||
|
|
||||||
|
finance_group = GroupModel.query.filter_by(identifier="Finance Team").first()
|
||||||
|
assert finance_group is not None
|
||||||
|
|
||||||
|
process_model = load_test_spec(
|
||||||
|
process_model_id="model_with_lanes",
|
||||||
|
bpmn_file_name="lanes_with_owner_dict.bpmn",
|
||||||
|
)
|
||||||
|
process_instance = self.create_process_instance_from_process_model(
|
||||||
|
process_model=process_model, user=initiator_user
|
||||||
|
)
|
||||||
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
|
processor.do_engine_steps(save=True)
|
||||||
|
|
||||||
|
assert len(process_instance.active_tasks) == 1
|
||||||
|
active_task = process_instance.active_tasks[0]
|
||||||
|
assert active_task.lane_assignment_id is None
|
||||||
|
assert len(active_task.potential_owners) == 1
|
||||||
|
assert active_task.potential_owners[0] == initiator_user
|
||||||
|
|
||||||
|
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
|
||||||
|
active_task.task_name, processor.bpmn_process_instance
|
||||||
|
)
|
||||||
|
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, finance_user_three
|
||||||
|
)
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, initiator_user
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(process_instance.active_tasks) == 1
|
||||||
|
active_task = process_instance.active_tasks[0]
|
||||||
|
assert active_task.lane_assignment_id is None
|
||||||
|
assert len(active_task.potential_owners) == 2
|
||||||
|
assert active_task.potential_owners == [finance_user_three, finance_user_four]
|
||||||
|
|
||||||
|
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
|
||||||
|
active_task.task_name, processor.bpmn_process_instance
|
||||||
|
)
|
||||||
|
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, initiator_user
|
||||||
|
)
|
||||||
|
|
||||||
|
g.user = finance_user_three
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, finance_user_three
|
||||||
|
)
|
||||||
|
assert len(process_instance.active_tasks) == 1
|
||||||
|
active_task = process_instance.active_tasks[0]
|
||||||
|
assert active_task.lane_assignment_id is None
|
||||||
|
assert len(active_task.potential_owners) == 1
|
||||||
|
assert active_task.potential_owners[0] == finance_user_four
|
||||||
|
|
||||||
|
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
|
||||||
|
active_task.task_name, processor.bpmn_process_instance
|
||||||
|
)
|
||||||
|
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, initiator_user
|
||||||
|
)
|
||||||
|
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, finance_user_four
|
||||||
|
)
|
||||||
|
assert len(process_instance.active_tasks) == 1
|
||||||
|
active_task = process_instance.active_tasks[0]
|
||||||
|
assert active_task.lane_assignment_id is None
|
||||||
|
assert len(active_task.potential_owners) == 1
|
||||||
|
assert active_task.potential_owners[0] == initiator_user
|
||||||
|
|
||||||
|
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
|
||||||
|
active_task.task_name, processor.bpmn_process_instance
|
||||||
|
)
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, initiator_user
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(process_instance.active_tasks) == 1
|
||||||
|
active_task = process_instance.active_tasks[0]
|
||||||
|
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
|
||||||
|
active_task.task_name, processor.bpmn_process_instance
|
||||||
|
)
|
||||||
|
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||||
|
ProcessInstanceService.complete_form_task(
|
||||||
|
processor, spiff_task, {}, initiator_user
|
||||||
|
)
|
||||||
|
ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testadmin1)
|
||||||
|
|
||||||
|
assert process_instance.status == ProcessInstanceStatus.complete.value
|
||||||
|
|
Loading…
Reference in New Issue