Merge pull request #101 from sartography/feature/allow-dot-notation-in-forms
Feature/allow dot notation in forms
This commit is contained in:
commit
6d6e0e7efd
|
@ -11,7 +11,6 @@ from flask_bpmn.models.db import SpiffworkflowBaseDBModel
|
|||
from marshmallow import INCLUDE
|
||||
from marshmallow import Schema
|
||||
from marshmallow_enum import EnumField # type: ignore
|
||||
from SpiffWorkflow.navigation import NavItem # type: ignore
|
||||
from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import deferred
|
||||
|
@ -54,20 +53,6 @@ class NavigationItemSchema(Schema):
|
|||
marshmallow.fields.Nested(lambda: NavigationItemSchema())
|
||||
)
|
||||
|
||||
@marshmallow.post_load
|
||||
def make_nav(self, data: dict[str, Any], **kwargs: dict) -> NavItem:
|
||||
"""Make_nav."""
|
||||
state = data.pop("state", None)
|
||||
task_id = data.pop("task_id", None)
|
||||
children = data.pop("children", [])
|
||||
spec_type = data.pop("spec_type", None)
|
||||
item = NavItem(**data)
|
||||
item.state = state
|
||||
item.task_id = task_id
|
||||
item.children = children
|
||||
item.spec_type = spec_type
|
||||
return item
|
||||
|
||||
|
||||
class ProcessInstanceStatus(SpiffEnum):
|
||||
"""ProcessInstanceStatus."""
|
||||
|
|
|
@ -275,7 +275,8 @@ class ProcessInstanceService:
|
|||
Abstracted here because we need to do it multiple times when completing all tasks in
|
||||
a multi-instance task.
|
||||
"""
|
||||
spiff_task.update_data(data)
|
||||
dot_dct = ProcessInstanceService.create_dot_dict(data)
|
||||
spiff_task.update_data(dot_dct)
|
||||
# ProcessInstanceService.post_process_form(spiff_task) # some properties may update the data store.
|
||||
processor.complete_task(spiff_task)
|
||||
# Log the action before doing the engine steps, as doing so could effect the state of the task
|
||||
|
@ -342,6 +343,14 @@ class ProcessInstanceService:
|
|||
ProcessInstanceService.set_dot_value(field.id, value, data)
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def create_dot_dict(data: dict) -> dict[str, Any]:
|
||||
"""Create_dot_dict."""
|
||||
dot_dict: dict[str, Any] = {}
|
||||
for key, value in data.items():
|
||||
ProcessInstanceService.set_dot_value(key, value, dot_dict)
|
||||
return dot_dict
|
||||
|
||||
@staticmethod
|
||||
def get_dot_value(path: str, source: dict) -> Any:
|
||||
"""Get_dot_value."""
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?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:correlationProperty id="message_correlation_property" name="Message Correlation Property">
|
||||
<bpmn:correlationPropertyRetrievalExpression messageRef="message_send">
|
||||
<bpmn:formalExpression>to</bpmn:formalExpression>
|
||||
</bpmn:correlationPropertyRetrievalExpression>
|
||||
<bpmn:correlationPropertyRetrievalExpression messageRef="message_response">
|
||||
<bpmn:formalExpression>from.name</bpmn:formalExpression>
|
||||
</bpmn:correlationPropertyRetrievalExpression>
|
||||
</bpmn:correlationProperty>
|
||||
<bpmn:message id="message_send" name="Message Send">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:messagePayload>{"to": "the_recipient1" }</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:message id="message_response" name="Message Response">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:messagePayload>{"from": {"name": "the_sender"}}</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:correlationProperty id="correlation_property_one" name="Correlation Property One">
|
||||
<bpmn:correlationPropertyRetrievalExpression messageRef="message_send">
|
||||
<bpmn:formalExpression>new</bpmn:formalExpression>
|
||||
</bpmn:correlationPropertyRetrievalExpression>
|
||||
</bpmn:correlationProperty>
|
||||
<bpmn:process id="test_dot_notation" name="Test Dot Notation" isExecutable="true">
|
||||
<bpmn:startEvent id="start" name="Start">
|
||||
<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:incoming>Flow_0nt355i</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0nt355i" sourceRef="get_data" targetRef="end" />
|
||||
<bpmn:userTask id="get_data" name="Get Data">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:properties>
|
||||
<spiffworkflow:property name="formJsonSchemaFilename" value="json_schema.json" />
|
||||
<spiffworkflow:property name="formUiSchemaFilename" value="ui_schema.json" />
|
||||
</spiffworkflow:properties>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_0dbnzbi</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0nt355i</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="test_dotnotation">
|
||||
<bpmndi:BPMNEdge id="Flow_0dbnzbi_di" bpmnElement="Flow_0dbnzbi">
|
||||
<di:waypoint x="208" y="230" />
|
||||
<di:waypoint x="260" y="230" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0nt355i_di" bpmnElement="Flow_0nt355i">
|
||||
<di:waypoint x="360" y="230" />
|
||||
<di:waypoint x="412" y="230" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Event_1uf4njx_di" bpmnElement="start">
|
||||
<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">
|
||||
<dc:Bounds x="412" y="212" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="420" y="255" width="20" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1vgvg3h_di" bpmnElement="get_data">
|
||||
<dc:Bounds x="260" y="190" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"title": "Submit Invoice",
|
||||
"description": "Information for submitting an invoice.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"invoice.contributorName",
|
||||
"invoice.contributorId",
|
||||
"invoice.invoiceId",
|
||||
"invoice.invoiceAmount",
|
||||
"invoice.dueDate"
|
||||
],
|
||||
"properties": {
|
||||
"invoice.contributorName": {
|
||||
"type": "string",
|
||||
"title": "Contributor Name"
|
||||
},
|
||||
"invoice.contributorId": {
|
||||
"type": "integer",
|
||||
"title": "Contributor Id",
|
||||
"minLength": 2
|
||||
},
|
||||
"invoice.invoiceId": {
|
||||
"type": "integer",
|
||||
"title": "Invoice Id",
|
||||
"minLength": 4
|
||||
},
|
||||
"invoice.invoiceAmount": {
|
||||
"type": "number",
|
||||
"title": "Invoice Amount"
|
||||
},
|
||||
"invoice.dueDate": {
|
||||
"type": "string",
|
||||
"title": "Due Date"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"invoice.contributorName": {
|
||||
"ui:autofocus": true,
|
||||
"ui:emptyValue": ""
|
||||
},
|
||||
"invoice.contributorId": {
|
||||
"ui:emptyValue": "Enter your Status Contributor ID"
|
||||
},
|
||||
"invoice.invoiceId": {
|
||||
"ui:title": "Status Invoice ID",
|
||||
"ui:description": "Enter the Status Invoice ID found in the upper left"
|
||||
},
|
||||
"invoice.invoiceAmount": {
|
||||
"ui:help": "Amount in Euros"
|
||||
},
|
||||
"invoice.dueDate": {
|
||||
"ui:widget": "date"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
"""Test_various_bpmn_constructs."""
|
||||
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.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_instance_service import (
|
||||
ProcessInstanceService,
|
||||
)
|
||||
|
||||
|
||||
class TestDotNotation(BaseTest):
|
||||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_dot_notation(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
"""Test_form_data_conversion_to_dot_dict."""
|
||||
process_model = load_test_spec(
|
||||
"test_dot_notation",
|
||||
bpmn_file_name="diagram.bpmn",
|
||||
process_model_source_directory="dot_notation",
|
||||
)
|
||||
current_user = self.find_or_create_user()
|
||||
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model
|
||||
)
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
|
||||
processor.do_engine_steps(save=True)
|
||||
|
||||
user_task = processor.get_ready_user_tasks()[0]
|
||||
form_data = {
|
||||
"invoice.contibutorName": "Elizabeth",
|
||||
"invoice.contributorId": 100,
|
||||
"invoice.invoiceId": 10001,
|
||||
"invoice.invoiceAmount": "1000.00",
|
||||
"invoice.dueDate": "09/30/2022",
|
||||
}
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, user_task, form_data, current_user
|
||||
)
|
||||
|
||||
expected = {
|
||||
"contibutorName": "Elizabeth",
|
||||
"contributorId": 100,
|
||||
"invoiceId": 10001,
|
||||
"invoiceAmount": "1000.00",
|
||||
"dueDate": "09/30/2022",
|
||||
}
|
||||
|
||||
processor.do_engine_steps(save=True)
|
||||
assert processor.get_data()["invoice"] == expected
|
Loading…
Reference in New Issue