mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-01-27 01:40:48 +00:00
unit tests are passing with the new spec tables
This commit is contained in:
parent
8d67e8cc87
commit
0c6e9a63ba
28
spiffworkflow-backend/migrations/versions/567d22ded3af_.py
Normal file
28
spiffworkflow-backend/migrations/versions/567d22ded3af_.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 567d22ded3af
|
||||
Revises: 2fe2830f45e1
|
||||
Create Date: 2023-03-03 08:38:25.855923
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '567d22ded3af'
|
||||
down_revision = '2fe2830f45e1'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_unique_constraint('bpmn_process_definition_relationship_unique', 'bpmn_process_definition_relationship', ['bpmn_process_definition_parent_id', 'bpmn_process_definition_child_id'])
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint('bpmn_process_definition_relationship_unique', 'bpmn_process_definition_relationship', type_='unique')
|
||||
# ### end Alembic commands ###
|
30
spiffworkflow-backend/migrations/versions/6315ff2525b0_.py
Normal file
30
spiffworkflow-backend/migrations/versions/6315ff2525b0_.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 6315ff2525b0
|
||||
Revises: 567d22ded3af
|
||||
Create Date: 2023-03-03 09:19:28.098057
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '6315ff2525b0'
|
||||
down_revision = '567d22ded3af'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('process_instance', sa.Column('bpmn_process_definition_id', sa.Integer(), nullable=False))
|
||||
op.create_foreign_key(None, 'process_instance', 'bpmn_process_definition', ['bpmn_process_definition_id'], ['id'])
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint(None, 'process_instance', type_='foreignkey')
|
||||
op.drop_column('process_instance', 'bpmn_process_definition_id')
|
||||
# ### end Alembic commands ###
|
32
spiffworkflow-backend/migrations/versions/def2cbb0ca6b_.py
Normal file
32
spiffworkflow-backend/migrations/versions/def2cbb0ca6b_.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: def2cbb0ca6b
|
||||
Revises: 6315ff2525b0
|
||||
Create Date: 2023-03-03 09:23:19.480250
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'def2cbb0ca6b'
|
||||
down_revision = '6315ff2525b0'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('process_instance', 'bpmn_process_definition_id',
|
||||
existing_type=mysql.INTEGER(),
|
||||
nullable=True)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('process_instance', 'bpmn_process_definition_id',
|
||||
existing_type=mysql.INTEGER(),
|
||||
nullable=False)
|
||||
# ### end Alembic commands ###
|
@ -21,6 +21,7 @@ class BpmnProcessDefinitionModel(SpiffworkflowBaseDBModel):
|
||||
properties_json: str = db.Column(db.JSON, nullable=False)
|
||||
|
||||
# process or subprocess
|
||||
# FIXME: will probably ignore for now since we do not strictly need it
|
||||
type: str = db.Column(db.String(32), nullable=False, index=True)
|
||||
|
||||
# TODO: remove these from process_instance
|
||||
|
@ -1,4 +1,5 @@
|
||||
from __future__ import annotations
|
||||
from sqlalchemy import UniqueConstraint
|
||||
from sqlalchemy.orm import deferred
|
||||
from sqlalchemy import ForeignKey
|
||||
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel
|
||||
@ -9,6 +10,12 @@ from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
|
||||
|
||||
class BpmnProcessDefinitionRelationshipModel(SpiffworkflowBaseDBModel):
|
||||
__tablename__ = "bpmn_process_definition_relationship"
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"bpmn_process_definition_parent_id", "bpmn_process_definition_child_id", name="bpmn_process_definition_relationship_unique"
|
||||
),
|
||||
)
|
||||
|
||||
id: int = db.Column(db.Integer, primary_key=True)
|
||||
bpmn_process_definition_parent_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=False) # type: ignore
|
||||
bpmn_process_definition_child_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=False) # type: ignore
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Process_instance."""
|
||||
from __future__ import annotations
|
||||
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel
|
||||
|
||||
from typing import Any
|
||||
from typing import cast
|
||||
@ -74,6 +75,9 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
||||
)
|
||||
process_instance_data = relationship("ProcessInstanceDataModel", cascade="delete")
|
||||
|
||||
bpmn_process_definition_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=True) # type: ignore
|
||||
bpmn_process_definition = relationship(BpmnProcessDefinitionModel)
|
||||
|
||||
active_human_tasks = relationship(
|
||||
"HumanTaskModel",
|
||||
primaryjoin=(
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""Process_instance_processor."""
|
||||
import _strptime # type: ignore
|
||||
import _strptime
|
||||
from spiffworkflow_backend.models import serialized_bpmn_definition # type: ignore
|
||||
from spiffworkflow_backend.models.bpmn_process_definition_relationship import BpmnProcessDefinitionRelationshipModel # noqa: F401
|
||||
import decimal
|
||||
import json
|
||||
import logging
|
||||
@ -55,6 +57,7 @@ from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
|
||||
from sqlalchemy import text
|
||||
|
||||
from spiffworkflow_backend.exceptions.api_error import ApiError
|
||||
from spiffworkflow_backend.models import bpmn_process_definition_relationship
|
||||
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel
|
||||
from spiffworkflow_backend.models.db import db
|
||||
from spiffworkflow_backend.models.file import File
|
||||
@ -526,9 +529,32 @@ class ProcessInstanceProcessor:
|
||||
def _get_full_bpmn_json(cls, process_instance_model: ProcessInstanceModel) -> dict:
|
||||
if process_instance_model.serialized_bpmn_definition_id is None:
|
||||
return {}
|
||||
serialized_bpmn_definition = process_instance_model.serialized_bpmn_definition
|
||||
# serialized_bpmn_definition = process_instance_model.serialized_bpmn_definition
|
||||
# print(f"serialized_bpmn_definition.static_json: {serialized_bpmn_definition.static_json}")
|
||||
# loaded_json: dict = json.loads(serialized_bpmn_definition.static_json) # or "{}")
|
||||
|
||||
serialized_bpmn_definition = {}
|
||||
bpmn_process_definition = BpmnProcessDefinitionModel.query.filter_by(id=process_instance_model.bpmn_process_definition_id).first()
|
||||
task_definitions = TaskDefinitionModel.query.filter_by(bpmn_process_definition_id=process_instance_model.bpmn_process_definition_id).all()
|
||||
if bpmn_process_definition is not None:
|
||||
serialized_bpmn_definition = {"serializer_version": cls.SERIALIZER_VERSION, "spec": {}, "subprocess_specs": {}}
|
||||
bpmn_process_definition_dict = json.loads(bpmn_process_definition.properties_json)
|
||||
bpmn_process_definition_dict['task_specs'] = {}
|
||||
for task_definition in task_definitions:
|
||||
bpmn_process_definition_dict['task_specs'][task_definition.bpmn_identifier] = json.loads(task_definition.properties_json)
|
||||
serialized_bpmn_definition['spec'] = bpmn_process_definition_dict
|
||||
|
||||
bpmn_process_subprocess_definitions = BpmnProcessDefinitionRelationshipModel.query.filter_by(bpmn_process_definition_parent_id=bpmn_process_definition.id).all()
|
||||
for bpmn_process_subprocess_definition in bpmn_process_subprocess_definitions:
|
||||
subprocess_task_definitions = TaskDefinitionModel.query.filter_by(bpmn_process_definition_id=bpmn_process_subprocess_definition.id).all()
|
||||
bpmn_process_subprocess_dict = json.loads(bpmn_process_definition.properties_json)
|
||||
bpmn_process_subprocess_dict['task_specs'] = {}
|
||||
for subprocess_task_definition in subprocess_task_definitions:
|
||||
bpmn_process_subprocess_dict['task_specs'][subprocess_task_definition.bpmn_identifier] = json.loads(subprocess_task_definition.properties_json)
|
||||
serialized_bpmn_definition['subprocess_specs'][bpmn_process_subprocess_definition.bpmn_identifier] = bpmn_process_subprocess_dict
|
||||
loaded_json: dict = serialized_bpmn_definition
|
||||
|
||||
process_instance_data = process_instance_model.process_instance_data
|
||||
loaded_json: dict = json.loads(serialized_bpmn_definition.static_json or "{}")
|
||||
loaded_json.update(json.loads(process_instance_data.runtime_json))
|
||||
return loaded_json
|
||||
|
||||
@ -909,19 +935,15 @@ class ProcessInstanceProcessor:
|
||||
self.process_instance_model.process_instance_data = process_instance_data
|
||||
|
||||
|
||||
def _store_bpmn_process_definitions(self, process_bpmn_properties: dict) -> None:
|
||||
# for process_bpmn_identifier, process_bpmn_properties in bpmn_spec_dict.items():
|
||||
print(f"process_bpmn_properties: {process_bpmn_properties}")
|
||||
def _store_bpmn_process_definition(self, process_bpmn_properties: dict, bpmn_process_definition_parent: Optional[BpmnProcessDefinitionModel] = None) -> BpmnProcessDefinitionModel:
|
||||
process_bpmn_identifier = process_bpmn_properties['name']
|
||||
new_hash_digest = sha256(
|
||||
json.dumps(process_bpmn_properties, sort_keys=True).encode("utf8")
|
||||
).hexdigest()
|
||||
bpmn_process_definition = BpmnProcessDefinitionModel.query.filter_by(
|
||||
bpmn_process_definition: Optional[BpmnProcessDefinitionModel] = BpmnProcessDefinitionModel.query.filter_by(
|
||||
hash=new_hash_digest
|
||||
).first()
|
||||
if bpmn_process_definition is None:
|
||||
# print(f"process_bpmn_identifier: {process_bpmn_identifier}")
|
||||
print(f"process_bpmn_properties: {process_bpmn_properties}")
|
||||
task_specs = process_bpmn_properties.pop("task_specs")
|
||||
bpmn_process_definition = BpmnProcessDefinitionModel(
|
||||
hash=new_hash_digest, bpmn_identifier=process_bpmn_identifier, properties_json=json.dumps(process_bpmn_properties), type="process"
|
||||
@ -937,6 +959,19 @@ class ProcessInstanceProcessor:
|
||||
)
|
||||
db.session.add(task_definition)
|
||||
|
||||
if bpmn_process_definition_parent:
|
||||
bpmn_process_definition_relationship = BpmnProcessDefinitionRelationshipModel.query.filter_by(
|
||||
bpmn_process_definition_parent_id=bpmn_process_definition_parent.id,
|
||||
bpmn_process_definition_child_id=bpmn_process_definition.id,
|
||||
).first()
|
||||
if bpmn_process_definition_relationship is None:
|
||||
bpmn_process_definition_relationship = BpmnProcessDefinitionRelationshipModel(
|
||||
bpmn_process_definition_parent_id=bpmn_process_definition_parent.id,
|
||||
bpmn_process_definition_child_id=bpmn_process_definition.id,
|
||||
)
|
||||
db.session.add(bpmn_process_definition_relationship)
|
||||
return bpmn_process_definition
|
||||
|
||||
def _add_bpmn_json_records_new(self) -> None:
|
||||
"""Adds serialized_bpmn_definition and process_instance_data records to the db session.
|
||||
|
||||
@ -952,7 +987,11 @@ class ProcessInstanceProcessor:
|
||||
else:
|
||||
process_instance_data_dict[bpmn_key] = bpmn_dict[bpmn_key]
|
||||
|
||||
self._store_bpmn_process_definitions(bpmn_spec_dict['spec'])
|
||||
bpmn_process_definition_parent = self._store_bpmn_process_definition(bpmn_spec_dict['spec'])
|
||||
for process_bpmn_properties in bpmn_spec_dict['subprocess_specs'].values():
|
||||
self._store_bpmn_process_definition(process_bpmn_properties, bpmn_process_definition_parent)
|
||||
self.process_instance_model.bpmn_process_definition = bpmn_process_definition_parent
|
||||
|
||||
|
||||
# # FIXME: always save new hash until we get updated Spiff without loopresettask
|
||||
# # if self.process_instance_model.serialized_bpmn_definition_id is None:
|
||||
|
@ -24,14 +24,14 @@
|
||||
</bpmn:correlationPropertyRetrievalExpression>
|
||||
</bpmn:correlationProperty>
|
||||
<bpmn:process id="test_dot_notation" name="Test Dot Notation" isExecutable="true">
|
||||
<bpmn:startEvent id="start" name="Start">
|
||||
<bpmn:startEvent id="startHere" name="StartHere">
|
||||
<bpmn:outgoing>Flow_0dbnzbi</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0dbnzbi" sourceRef="start" targetRef="get_data" />
|
||||
<bpmn:endEvent id="end" name="End">
|
||||
<bpmn:sequenceFlow id="Flow_0dbnzbi" sourceRef="startHere" targetRef="get_data" />
|
||||
<bpmn:endEvent id="endHere" name="End">
|
||||
<bpmn:incoming>Flow_0nt355i</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0nt355i" sourceRef="get_data" targetRef="end" />
|
||||
<bpmn:sequenceFlow id="Flow_0nt355i" sourceRef="get_data" targetRef="endHere" />
|
||||
<bpmn:userTask id="get_data" name="Get Data">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:properties>
|
||||
@ -53,13 +53,13 @@
|
||||
<di:waypoint x="360" y="230" />
|
||||
<di:waypoint x="412" y="230" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Event_1uf4njx_di" bpmnElement="start">
|
||||
<bpmndi:BPMNShape id="Event_1uf4njx_di" bpmnElement="startHere">
|
||||
<dc:Bounds x="172" y="212" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="178" y="255" width="24" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_00d0dwr_di" bpmnElement="end">
|
||||
<bpmndi:BPMNShape id="Event_00d0dwr_di" bpmnElement="endHere">
|
||||
<dc:Bounds x="412" y="212" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="420" y="255" width="20" height="14" />
|
||||
|
@ -1301,10 +1301,11 @@ class TestProcessApi(BaseTest):
|
||||
assert create_response.json is not None
|
||||
assert create_response.status_code == 201
|
||||
process_instance_id = create_response.json["id"]
|
||||
client.post(
|
||||
run_response = client.post(
|
||||
f"/v1.0/process-instances/{modified_process_model_identifier}/{process_instance_id}/run",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
)
|
||||
assert run_response.status_code == 200
|
||||
show_response = client.get(
|
||||
f"/v1.0/process-instances/{modified_process_model_identifier}/{process_instance_id}?process_identifier={spec_reference.identifier}",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
|
@ -13,9 +13,7 @@ from spiffworkflow_backend.services.process_instance_service import (
|
||||
|
||||
|
||||
class TestDotNotation(BaseTest):
|
||||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_dot_notation(
|
||||
def test_dot_notation_in_message_path(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
|
Loading…
x
Reference in New Issue
Block a user