the call activity test passes now w/ burnettk cullerton

This commit is contained in:
jasquat 2022-09-08 18:05:50 -04:00
parent 1faeaab118
commit eca3c92f86
22 changed files with 273 additions and 143 deletions

12
poetry.lock generated
View File

@ -1830,11 +1830,11 @@ test = ["pytest"]
[[package]]
name = "SpiffWorkflow"
version = "1.1.7"
description = "A workflow framework and BPMN/DMN Processor"
description = ""
category = "main"
optional = false
python-versions = "*"
develop = true
develop = false
[package.dependencies]
celery = "*"
@ -1844,8 +1844,10 @@ lxml = "*"
pytz = "*"
[package.source]
type = "directory"
url = "../SpiffWorkflow"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "feature/dependencies"
resolved_reference = "22853a4806e06395f39d66d2401d0c6b917a338d"
[[package]]
name = "sqlalchemy"
@ -2155,7 +2157,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
[metadata]
lock-version = "1.1"
python-versions = "^3.9"
content-hash = "645cb811651af21330bcd61e27d293ff280f5fd68997b4f42e3237289ef14212"
content-hash = "8b2690c841abe0bb0502fb451165e464d8481d5b843f6623a45ee55f69c78a74"
[metadata.files]
alabaster = [

View File

@ -28,8 +28,8 @@ flask-migrate = "*"
flask-restful = "*"
werkzeug = "*"
# SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
# SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "feature/centralized-logging"}
SpiffWorkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "feature/dependencies"}
# SpiffWorkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
sentry-sdk = "1.9.0"
sphinx-autoapi = "^1.8.4"
# flask-bpmn = {develop = true, path = "/home/jason/projects/github/sartography/flask-bpmn"}

View File

@ -31,4 +31,6 @@ OPEN_ID_CLIENT_SECRET_KEY = environ.get(
"OPEN_ID_CLIENT_SECRET_KEY", default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q"
) # noqa: S105
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="false") == "false"
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="false") == "false"
)

View File

@ -1,8 +1,9 @@
"""Testing.py."""
from os import environ
TESTING = True
SECRET_KEY = "the_secret_key"
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="true") == "true"
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
environ.get("SPIFFWORKFLOW_BACKEND_LOG_TO_FILE", default="true") == "true"
)

View File

@ -5,6 +5,9 @@ autoflake8 will remove these lines without the noqa comment
from flask_bpmn.models.db import add_listeners
from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401
from spiffworkflow_backend.models.bpmn_process_id_lookup import (
BpmnProcessIdLookup,
) # noqa: F401
from spiffworkflow_backend.models.data_store import DataStoreModel # noqa: F401
from spiffworkflow_backend.models.file import FileModel # noqa: F401
from spiffworkflow_backend.models.message_correlation_property import (
@ -26,7 +29,6 @@ from spiffworkflow_backend.models.process_instance_report import (
) # noqa: F401
from spiffworkflow_backend.models.task_event import TaskEventModel # noqa: F401
from spiffworkflow_backend.models.user import UserModel # noqa: F401
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup # noqa: F401
from spiffworkflow_backend.models.user_group_assignment import (
UserGroupAssignmentModel,
) # noqa: F401

View File

@ -4,6 +4,7 @@ from flask_bpmn.models.db import SpiffworkflowBaseDBModel
class BpmnProcessIdLookup(SpiffworkflowBaseDBModel):
"""BpmnProcessIdLookup."""
__tablename__ = "bpmn_process_id_lookup"

View File

@ -277,7 +277,9 @@ def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Res
file.process_model_id = process_model.id
file.process_group_id = process_model.process_group_id
if not process_model.primary_process_id and file.type == FileType.bpmn.value:
SpecFileService.process_bpmn_file(process_model, file.name, set_primary_file=True)
SpecFileService.process_bpmn_file(
process_model, file.name, set_primary_file=True
)
process_model_service.save_process_model(process_model)
return Response(
json.dumps(FileSchema().dump(file)), status=201, mimetype="application/json"

View File

@ -50,9 +50,8 @@ class FileSystemService:
@staticmethod
def full_path_from_relative_path(relative_path: str) -> str:
return os.path.join(
FileSystemService.root_path(), relative_path
)
"""Full_path_from_relative_path."""
return os.path.join(FileSystemService.root_path(), relative_path)
@staticmethod
def process_model_relative_path(spec: ProcessModelInfo) -> str:

View File

@ -127,8 +127,8 @@ def setup_logger(app: Flask) -> None:
log_formatter = json_formatter
spiff_logger_filehandler = None
if app.config['SPIFFWORKFLOW_BACKEND_LOG_TO_FILE']:
spiff_logger_filehandler = logging.FileHandler(f'log/{app.env}.log')
if app.config["SPIFFWORKFLOW_BACKEND_LOG_TO_FILE"]:
spiff_logger_filehandler = logging.FileHandler(f"log/{app.env}.log")
spiff_logger_filehandler.setLevel(logging.DEBUG)
spiff_logger_filehandler.setFormatter(log_formatter)

View File

@ -1,5 +1,6 @@
"""Process_instance_processor."""
import json
import os
import time
from typing import Any
from typing import Dict
@ -47,6 +48,7 @@ from SpiffWorkflow.spiff.serializer import UserTaskConverter
from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
from spiffworkflow_backend.models.active_task import ActiveTaskModel
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel
@ -65,6 +67,7 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.task_event import TaskAction
from spiffworkflow_backend.models.task_event import TaskEventModel
from spiffworkflow_backend.models.user import UserModelSchema
from spiffworkflow_backend.services.file_system_service import FileSystemService
from spiffworkflow_backend.services.process_model_service import ProcessModelService
from spiffworkflow_backend.services.spec_file_service import SpecFileService
from spiffworkflow_backend.services.user_service import UserService
@ -449,6 +452,42 @@ class ProcessInstanceProcessor:
parser = MyCustomParser()
return parser
@staticmethod
def find_required_files(
bpmn_file_full_path: str,
parser: BpmnDmnParser,
processed_identifiers: Optional[set[str]] = None,
) -> None:
"""Find_required_files."""
if processed_identifiers is None:
processed_identifiers = set()
parser.get_dependencies()
processor_dependencies = parser.get_process_dependencies()
processor_dependencies_new = processor_dependencies - processed_identifiers
new_bpmn_files = set()
for bpmn_process_identifier in processor_dependencies_new:
bpmn_process_id_lookup = BpmnProcessIdLookup.query.filter_by(
bpmn_process_identifier=bpmn_process_identifier
).first()
new_bpmn_file_full_path = None
if bpmn_process_id_lookup is None:
# TODO: this should only happen rarely
new_bpmn_file_full_path = ""
else:
new_bpmn_file_full_path = os.path.join(
FileSystemService.root_path(),
bpmn_process_id_lookup.bpmn_file_relative_path,
)
new_bpmn_files.add(new_bpmn_file_full_path)
processed_identifiers.add(bpmn_process_identifier)
for new_bpmn_file_full_path in new_bpmn_files:
parser.add_bpmn_file(new_bpmn_file_full_path)
ProcessInstanceProcessor.find_required_files(
new_bpmn_file_full_path, parser, processed_identifiers
)
@staticmethod
def get_spec(
files: List[File], process_model_info: ProcessModelInfo
@ -475,6 +514,13 @@ class ProcessInstanceProcessor:
% process_model_info.id,
)
)
workflow_path = FileSystemService.workflow_path(process_model_info) or ""
primary_file_full_path = os.path.join(
workflow_path, (process_model_info.primary_file_name or "")
)
ProcessInstanceProcessor.find_required_files(primary_file_full_path, parser)
try:
spec = parser.get_spec(process_model_info.primary_process_id)

View File

@ -11,8 +11,8 @@ from lxml import etree # type: ignore
from lxml.etree import _Element # type: ignore
from lxml.etree import Element as EtreeElement
from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.message_correlation_property import (
@ -76,10 +76,18 @@ class SpecFileService(FileSystemService):
if file.type == str(FileType.bpmn):
set_primary_file = False
if process_model_info.primary_file_name is None or file_name == process_model_info.primary_file_name:
if (
process_model_info.primary_file_name is None
or file_name == process_model_info.primary_file_name
):
# If no primary process exists, make this primary process.
set_primary_file = True
SpecFileService.process_bpmn_file(process_model_info, file_name, binary_data, set_primary_file=set_primary_file)
SpecFileService.process_bpmn_file(
process_model_info,
file_name,
binary_data,
set_primary_file=set_primary_file,
)
return file
@ -156,14 +164,20 @@ class SpecFileService(FileSystemService):
bpmn_etree_element: EtreeElement = etree.fromstring(binary_data)
if set_primary_file:
process_model_info.primary_process_id = SpecFileService.get_process_id(
bpmn_etree_element
process_model_info.primary_process_id = (
SpecFileService.get_process_id(bpmn_etree_element)
)
process_model_info.primary_file_name = file_name
process_model_info.is_review = SpecFileService.has_swimlane(bpmn_etree_element)
process_model_info.is_review = SpecFileService.has_swimlane(
bpmn_etree_element
)
SpecFileService.check_for_message_models(bpmn_etree_element, process_model_info)
SpecFileService.store_process_ids(process_model_info, file_name, bpmn_etree_element)
SpecFileService.check_for_message_models(
bpmn_etree_element, process_model_info
)
SpecFileService.store_process_ids(
process_model_info, file_name, bpmn_etree_element
)
except etree.XMLSyntaxError as xse:
raise ApiError(
@ -202,9 +216,9 @@ class SpecFileService(FileSystemService):
retval = True
return retval
@staticmethod
def get_executable_process_elements(et_root: _Element) -> list[_Element]:
"""Get_executable_process_elements."""
process_elements = []
for child in et_root:
if child.tag.endswith("process") and child.attrib.get(
@ -218,8 +232,9 @@ class SpecFileService(FileSystemService):
@staticmethod
def get_executable_process_ids(et_root: _Element) -> list[str]:
"""Get_executable_process_ids."""
process_elements = SpecFileService.get_executable_process_elements(et_root)
process_ids = [pe.attrib['id'] for pe in process_elements]
process_ids = [pe.attrib["id"] for pe in process_elements]
return process_ids
@staticmethod
@ -245,21 +260,33 @@ class SpecFileService(FileSystemService):
return str(process_elements[0].attrib["id"])
@staticmethod
def store_process_ids(process_model_info: ProcessModelInfo, bpmn_file_name: str, et_root: _Element):
relative_process_model_path = SpecFileService.process_model_relative_path(process_model_info)
relative_bpmn_file_path = os.path.join(relative_process_model_path, bpmn_file_name)
def store_process_ids(
process_model_info: ProcessModelInfo, bpmn_file_name: str, et_root: _Element
) -> None:
"""Store_process_ids."""
relative_process_model_path = SpecFileService.process_model_relative_path(
process_model_info
)
relative_bpmn_file_path = os.path.join(
relative_process_model_path, bpmn_file_name
)
process_ids = SpecFileService.get_executable_process_ids(et_root)
for process_id in process_ids:
process_id_lookup = BpmnProcessIdLookup.query.filter_by(bpmn_process_identifier=process_id).first()
process_id_lookup = BpmnProcessIdLookup.query.filter_by(
bpmn_process_identifier=process_id
).first()
if process_id_lookup is None:
process_id_lookup = BpmnProcessIdLookup(
bpmn_process_identifier=process_id, bpmn_file_relative_path=relative_bpmn_file_path
bpmn_process_identifier=process_id,
bpmn_file_relative_path=relative_bpmn_file_path,
)
db.session.add(process_id_lookup)
db.session.commit()
else:
if relative_bpmn_file_path != process_id_lookup.bpmn_file_relative_path:
full_bpmn_file_path = SpecFileService.full_path_from_relative_path(process_id_lookup.bpmn_file_relative_path)
full_bpmn_file_path = SpecFileService.full_path_from_relative_path(
process_id_lookup.bpmn_file_relative_path
)
# if the old relative bpmn file no longer exists, then assume things were moved around
# on the file system. Otherwise, assume it is a duplicate process id and error.
if os.path.isfile(full_bpmn_file_path):
@ -268,7 +295,9 @@ class SpecFileService(FileSystemService):
f"{process_id_lookup.bpmn_file_relative_path}. It cannot be reused."
)
else:
process_id_lookup.bpmn_file_relative_path = relative_bpmn_file_path
process_id_lookup.bpmn_file_relative_path = (
relative_bpmn_file_path
)
db.session.add(process_id_lookup)
db.session.commit()

View File

@ -1,15 +1,15 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Level2" isExecutable="true">
<bpmn:process id="Level2" name="Level 2" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="Activity_12zat0d" />
<bpmn:callActivity id="Activity_12zat0d" name="call level 3" calledElement="Level3">
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="level3" />
<bpmn:callActivity id="level3" name="call level 3" calledElement="Level3">
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
</bpmn:callActivity>
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="Activity_12zat0d" targetRef="Activity_1cmkdc8" />
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="level3" targetRef="level2b_second_call" />
<bpmn:endEvent id="Event_18dla68">
<bpmn:documentation># Main Workflow
Hello {{my_other_var}}
@ -17,39 +17,39 @@ Hello {{my_other_var}}
</bpmn:documentation>
<bpmn:incoming>Flow_1ll6j9j</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1ll6j9j" sourceRef="Activity_1cmkdc8" targetRef="Event_18dla68" />
<bpmn:callActivity id="Activity_1cmkdc8" name="call level 2b again" calledElement="Level2b">
<bpmn:sequenceFlow id="Flow_1ll6j9j" sourceRef="level2b_second_call" targetRef="Event_18dla68" />
<bpmn:callActivity id="level2b_second_call" name="call level 2b again" calledElement="Level2b">
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
<bpmn:outgoing>Flow_1ll6j9j</bpmn:outgoing>
</bpmn:callActivity>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level2">
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="430" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ll6j9j_di" bpmnElement="Flow_1ll6j9j">
<di:waypoint x="530" y="117" />
<di:waypoint x="552" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="Activity_12zat0d">
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="level3">
<dc:Bounds x="280" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
<dc:Bounds x="552" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0522m2j_di" bpmnElement="Activity_1cmkdc8">
<bpmndi:BPMNShape id="Activity_0522m2j_di" bpmnElement="level2b_second_call">
<dc:Bounds x="430" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="430" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ll6j9j_di" bpmnElement="Flow_1ll6j9j">
<di:waypoint x="530" y="117" />
<di:waypoint x="552" y="117" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -1,10 +1,10 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Level2" isExecutable="true">
<bpmn:process id="Level2b" name="Level 2b" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="Activity_16ayqi8" />
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="do_nothing" />
<bpmn:endEvent id="Event_18dla68">
<bpmn:documentation># Main Workflow
Hello {{my_other_var}}
@ -12,14 +12,25 @@ Hello {{my_other_var}}
</bpmn:documentation>
<bpmn:incoming>Flow_0l0w6u9</bpmn:incoming>
</bpmn:endEvent>
<bpmn:task id="Activity_16ayqi8">
<bpmn:sequenceFlow id="Flow_0l0w6u9" sourceRef="do_nothing" targetRef="Event_18dla68" />
<bpmn:scriptTask id="do_nothing" name="Do Nothing">
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
<bpmn:outgoing>Flow_0l0w6u9</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_0l0w6u9" sourceRef="Activity_16ayqi8" targetRef="Event_18dla68" />
<bpmn:script>a = 1</bpmn:script>
</bpmn:scriptTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level2">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level2b">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1reqred_di" bpmnElement="do_nothing">
<dc:Bounds x="260" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="260" y="117" />
@ -28,15 +39,6 @@ Hello {{my_other_var}}
<di:waypoint x="360" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_16ayqi8_di" bpmnElement="Activity_16ayqi8">
<dc:Bounds x="260" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -1,15 +1,11 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Level3" name="Level3" isExecutable="true">
<bpmn:process id="Level3" name="Level 3" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="Activity_12zat0d" />
<bpmn:callActivity id="Activity_12zat0d" name="call level 3" calledElement="Level3">
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
</bpmn:callActivity>
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="Activity_12zat0d" targetRef="Event_18dla68" />
<bpmn:sequenceFlow id="Flow_1g3dpd7" sourceRef="StartEvent_1" targetRef="do_nothing" />
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="do_nothing" targetRef="Event_18dla68" />
<bpmn:endEvent id="Event_18dla68">
<bpmn:documentation># Main Workflow
Hello {{my_other_var}}
@ -17,27 +13,31 @@ Hello {{my_other_var}}
</bpmn:documentation>
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
</bpmn:endEvent>
<bpmn:scriptTask id="do_nothing" name="Do Nothing">
<bpmn:incoming>Flow_1g3dpd7</bpmn:incoming>
<bpmn:outgoing>Flow_0qdgvah</bpmn:outgoing>
<bpmn:script>a = 3</bpmn:script>
</bpmn:scriptTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level3">
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0mcej1g_di" bpmnElement="Activity_12zat0d">
<bpmndi:BPMNShape id="Activity_1po21cu_di" bpmnElement="do_nothing">
<dc:Bounds x="280" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -1,7 +1,5 @@
<?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: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" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<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:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Level1" name="Level1" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1g3dpd7</bpmn:outgoing>
@ -14,43 +12,19 @@
<bpmn:sequenceFlow id="Flow_0qdgvah" sourceRef="Activity_12zat0d" targetRef="Activity_0rkbhbz" />
<bpmn:endEvent id="Event_18dla68">
<bpmn:documentation># Main Workflow
Hello {{my_other_var}}
Hello {{my_other_var}}
</bpmn:documentation>
<bpmn:incoming>Flow_04o2npf</bpmn:incoming>
</bpmn:documentation>
<bpmn:incoming>Flow_0upce00</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0upce00" sourceRef="Activity_0rkbhbz" targetRef="Activity_0gg4414" />
<bpmn:sequenceFlow id="Flow_0upce00" sourceRef="Activity_0rkbhbz" targetRef="Event_18dla68" />
<bpmn:callActivity id="Activity_0rkbhbz" name="call level 2B" calledElement="Level2b">
<bpmn:incoming>Flow_0qdgvah</bpmn:incoming>
<bpmn:outgoing>Flow_0upce00</bpmn:outgoing>
</bpmn:callActivity>
<bpmn:sequenceFlow id="Flow_04o2npf" sourceRef="Activity_0gg4414" targetRef="Event_18dla68" />
<bpmn:businessRuleTask id="Activity_0gg4414" name="call level 2c" camunda:decisionRef="Level2c">
<bpmn:extensionElements>
<spiffworkflow:calledDecisionId>Level2c</spiffworkflow:calledDecisionId>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0upce00</bpmn:incoming>
<bpmn:outgoing>Flow_04o2npf</bpmn:outgoing>
</bpmn:businessRuleTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Level1">
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="420" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0upce00_di" bpmnElement="Flow_0upce00">
<di:waypoint x="520" y="117" />
<di:waypoint x="560" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_04o2npf_di" bpmnElement="Flow_04o2npf">
<di:waypoint x="660" y="117" />
<di:waypoint x="702" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
@ -58,15 +32,24 @@ Hello {{my_other_var}}
<dc:Bounds x="280" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0jddvat_di" bpmnElement="Activity_0rkbhbz">
<dc:Bounds x="420" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18dla68_di" bpmnElement="Event_18dla68">
<dc:Bounds x="702" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1lzid7b_di" bpmnElement="Activity_0gg4414">
<dc:Bounds x="560" y="77" width="100" height="80" />
<bpmndi:BPMNShape id="Activity_0jddvat_di" bpmnElement="Activity_0rkbhbz">
<dc:Bounds x="420" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1g3dpd7_di" bpmnElement="Flow_1g3dpd7">
<di:waypoint x="215" y="117" />
<di:waypoint x="280" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qdgvah_di" bpmnElement="Flow_0qdgvah">
<di:waypoint x="380" y="117" />
<di:waypoint x="420" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0upce00_di" bpmnElement="Flow_0upce00">
<di:waypoint x="520" y="117" />
<di:waypoint x="702" y="117" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
</bpmn:definitions>

View File

@ -1,5 +1,5 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI"
<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" id="Definitions_f07329e" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Level1" name="Level1" isExecutable="true">

View File

@ -1,7 +1,7 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:collaboration id="Collaboration_0oye1os">
<bpmn:participant id="message_receiver_one" name="Message Receiver" processRef="message_receiver_process" />
<bpmn:participant id="message_receiver_one" name="Message Receiver" processRef="message_receiver_process_one" />
<bpmn:participant id="message_sender" name="Message Sender" />
<bpmn:messageFlow id="message_send_flow" name="Message Send Flow" sourceRef="message_sender" targetRef="receive_message" />
<bpmn:messageFlow id="Flow_0ds946g" sourceRef="send_message_response" targetRef="message_sender" />
@ -40,7 +40,7 @@
}</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:process id="message_receiver_process" name="Message Receiver Process" isExecutable="true">
<bpmn:process id="message_receiver_process_one" name="Message Receiver Process" isExecutable="true">
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
<bpmn:endEvent id="Event_0q5otqd">
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>

View File

@ -1,7 +1,7 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:collaboration id="Collaboration_0oye1os">
<bpmn:participant id="message_receiver_two" name="Message Receiver" processRef="message_receiver_process" />
<bpmn:participant id="message_receiver_two" name="Message Receiver" processRef="message_receiver_process_two" />
<bpmn:participant id="message_sender" name="Message Sender" />
<bpmn:messageFlow id="message_send_flow" name="Message Send Flow" sourceRef="message_sender" targetRef="receive_message" />
<bpmn:messageFlow id="Flow_0ds946g" sourceRef="send_message_response" targetRef="message_sender" />
@ -40,7 +40,7 @@
}</spiffworkflow:messagePayload>
</bpmn:extensionElements>
</bpmn:message>
<bpmn:process id="message_receiver_process" name="Message Receiver Process" isExecutable="true">
<bpmn:process id="message_receiver_process_two" name="Message Receiver Process" isExecutable="true">
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
<bpmn:endEvent id="Event_0q5otqd">
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>

View File

@ -216,7 +216,7 @@ class BaseTest:
# return public_access_token
def create_process_instance_from_process_model(
self, process_model: ProcessModelInfo, status: str
self, process_model: ProcessModelInfo, status: Optional[str] = "not_started"
) -> ProcessInstanceModel:
"""Create_process_instance_from_process_model."""
user = self.find_or_create_user()

View File

@ -100,7 +100,9 @@ class ExampleDataLoader:
process_model_info=spec, file_name=filename, binary_data=data
)
if is_primary:
SpecFileService.process_bpmn_file(spec, filename, data, set_primary_file=True)
SpecFileService.process_bpmn_file(
spec, filename, data, set_primary_file=True
)
workflow_spec_service = ProcessModelService()
workflow_spec_service.save_process_model(spec)
finally:

View File

@ -1,9 +1,17 @@
"""Process Model."""
from spiffworkflow_backend.models.process_model import ProcessModelInfo
from flask.app import Flask
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
class TestProcessModel(BaseTest):
"""TestProcessModel."""
def test_initializes_files_as_empty_array(self) -> None:
"""Test_initializes_files_as_empty_array."""
process_model_one = self.create_test_process_model(
@ -12,6 +20,33 @@ class TestProcessModel(BaseTest):
assert process_model_one.files == []
assert process_model_one.libraries == []
def test_can_run_process_model_with_call_activities(
self, app: Flask, with_db_and_bpmn_file_cleanup: None
) -> None:
"""Test_can_run_process_model_with_call_activities."""
process_model = load_test_spec(
"call_activity_nested",
process_model_source_directory="call_activity_nested",
bpmn_file_name="call_activity_nested",
)
bpmn_file_names = [
"call_activity_level_2b",
"call_activity_level_2",
"call_activity_level_3",
]
for bpmn_file_name in bpmn_file_names:
load_test_spec(
bpmn_file_name,
process_model_source_directory="call_activity_nested",
bpmn_file_name=bpmn_file_name,
)
process_instance = self.create_process_instance_from_process_model(
process_model
)
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps()
def create_test_process_model(self, id: str, display_name: str) -> ProcessModelInfo:
"""Create_test_process_model."""
return ProcessModelInfo(

View File

@ -1,12 +1,13 @@
"""Test_message_service."""
from flask import Flask
import pytest
from flask_bpmn.models.db import db
from flask import Flask
from flask_bpmn.api.api_error import ApiError
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
from flask_bpmn.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
class TestSpecFileService(BaseTest):
"""TestSpecFileService."""
@ -20,6 +21,7 @@ class TestSpecFileService(BaseTest):
def test_can_store_process_ids_for_lookup(
self, app: Flask, with_db_and_bpmn_file_cleanup: None
) -> None:
"""Test_can_store_process_ids_for_lookup."""
load_test_spec(
"call_activity_nested",
process_model_source_directory="call_activity_nested",
@ -27,12 +29,16 @@ class TestSpecFileService(BaseTest):
)
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
assert len(bpmn_process_id_lookups) == 1
assert bpmn_process_id_lookups[0].bpmn_process_identifier == 'Level1'
assert bpmn_process_id_lookups[0].bpmn_file_relative_path == 'test_process_group_id/call_activity_nested/call_activity_nested.bpmn'
assert bpmn_process_id_lookups[0].bpmn_process_identifier == "Level1"
assert (
bpmn_process_id_lookups[0].bpmn_file_relative_path
== "test_process_group_id/call_activity_nested/call_activity_nested.bpmn"
)
def test_fails_to_save_duplicate_process_id(
self, app: Flask, with_db_and_bpmn_file_cleanup: None
) -> None:
"""Test_fails_to_save_duplicate_process_id."""
bpmn_process_identifier = "Level1"
load_test_spec(
"call_activity_nested",
@ -41,23 +47,35 @@ class TestSpecFileService(BaseTest):
)
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
assert len(bpmn_process_id_lookups) == 1
assert bpmn_process_id_lookups[0].bpmn_process_identifier == bpmn_process_identifier
assert bpmn_process_id_lookups[0].bpmn_file_relative_path == 'test_process_group_id/call_activity_nested/call_activity_nested.bpmn'
assert (
bpmn_process_id_lookups[0].bpmn_process_identifier
== bpmn_process_identifier
)
assert (
bpmn_process_id_lookups[0].bpmn_file_relative_path
== "test_process_group_id/call_activity_nested/call_activity_nested.bpmn"
)
with pytest.raises(ApiError) as exception:
load_test_spec(
"call_activity_nested_duplicate",
process_model_source_directory="call_activity_nested",
bpmn_file_name="call_activity_nested_duplicate",
)
assert f"Process id ({bpmn_process_identifier}) has already been used" in str(exception.value)
assert f"Process id ({bpmn_process_identifier}) has already been used" in str(
exception.value
)
def test_updates_relative_file_path_when_appropriate(
self, app: Flask, with_db_and_bpmn_file_cleanup: None
) -> None:
"""Test_updates_relative_file_path_when_appropriate."""
bpmn_process_identifier = "Level1"
bpmn_file_relative_path = 'test_process_group_id/call_activity_nested/new_bpmn_file.bpmn'
bpmn_file_relative_path = (
"test_process_group_id/call_activity_nested/new_bpmn_file.bpmn"
)
process_id_lookup = BpmnProcessIdLookup(
bpmn_process_identifier=bpmn_process_identifier, bpmn_file_relative_path=bpmn_file_relative_path
bpmn_process_identifier=bpmn_process_identifier,
bpmn_file_relative_path=bpmn_file_relative_path,
)
db.session.add(process_id_lookup)
db.session.commit()
@ -69,5 +87,11 @@ class TestSpecFileService(BaseTest):
)
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
assert len(bpmn_process_id_lookups) == 1
assert bpmn_process_id_lookups[0].bpmn_process_identifier == bpmn_process_identifier
assert bpmn_process_id_lookups[0].bpmn_file_relative_path == 'test_process_group_id/call_activity_nested/call_activity_nested.bpmn'
assert (
bpmn_process_id_lookups[0].bpmn_process_identifier
== bpmn_process_identifier
)
assert (
bpmn_process_id_lookups[0].bpmn_file_relative_path
== "test_process_group_id/call_activity_nested/call_activity_nested.bpmn"
)