First commit for cleaning up error messages for customers.
This is *not* in a working state. Committing this so I can work on another ticket.
This commit is contained in:
parent
cccb722e07
commit
fa34bee18a
|
@ -10,6 +10,7 @@ from crc.models.study import StudyModel, WorkflowMetadata
|
|||
from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema
|
||||
from crc.models.workflow import WorkflowModel, WorkflowSpecModelSchema, WorkflowSpecModel, WorkflowSpecCategoryModel, \
|
||||
WorkflowSpecCategoryModelSchema
|
||||
from crc.services.error_service import ValidationErrorService
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.lookup_service import LookupService
|
||||
from crc.services.study_service import StudyService
|
||||
|
@ -47,15 +48,16 @@ def validate_workflow_specification(spec_id):
|
|||
try:
|
||||
WorkflowService.test_spec(spec_id)
|
||||
except ApiError as ae:
|
||||
ae.message = "When populating all fields ... " + ae.message
|
||||
errors.append(ae)
|
||||
# ae.message = "When populating all fields ... \n" + ae.message
|
||||
errors.append(('all', ae))
|
||||
try:
|
||||
# Run the validation twice, the second time, just populate the required fields.
|
||||
WorkflowService.test_spec(spec_id, required_only=True)
|
||||
except ApiError as ae:
|
||||
ae.message = "When populating only required fields ... " + ae.message
|
||||
errors.append(ae)
|
||||
return ApiErrorSchema(many=True).dump(errors)
|
||||
# ae.message = "When populating only required fields ... \n" + ae.message
|
||||
errors.append(('required', ae))
|
||||
interpreted_errors = ValidationErrorService.interpret_validation_errors(errors)
|
||||
return ApiErrorSchema(many=True).dump(interpreted_errors)
|
||||
|
||||
|
||||
def update_workflow_specification(spec_id, body):
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# known_errors
|
||||
# key - something we can search for in an error message.
|
||||
# both_message - human readable message return to the user if error occurs in both
|
||||
# required_message - human readable message return to the user if error only occurs in required
|
||||
# all_message -human readable message return to the user if error only occurs in all
|
||||
#
|
||||
known_errors = [{'key': 'Error is Non-default exclusive outgoing sequence flow without condition',
|
||||
'message': 'Missing condition'}]
|
||||
generic_message = """Workflow validation failed. For more information about the error, see below."""
|
||||
|
||||
class ValidationErrorService(object):
|
||||
|
||||
"""Validation Error Service interprets messages return from api.workflow.validate_workflow_specification
|
||||
Validation is run twice,
|
||||
once where we try to fill in all form fields
|
||||
and a second time where we only fill in the required fields.
|
||||
|
||||
We get a list that contains possible errors from the validation."""
|
||||
|
||||
@staticmethod
|
||||
def interpret_validation_errors(errors):
|
||||
if len(errors) == 0:
|
||||
return errors
|
||||
hint = ''
|
||||
for known_error in known_errors:
|
||||
if known_error['key'] in errors[0].message:
|
||||
|
||||
# in both error 0 and error 1
|
||||
if known_error['key'] in errors[1].message:
|
||||
if 'both_hint' in known_error.keys():
|
||||
hint = known_error['both_hint']
|
||||
if 'both_message' in known_error.keys():
|
||||
message = known_error['both_message']
|
||||
|
||||
# just in error 0
|
||||
else:
|
||||
pass
|
||||
|
||||
# just in error 1
|
||||
if known_error['key'] in errors[1].message:
|
||||
pass
|
||||
|
||||
return errors
|
|
@ -0,0 +1,133 @@
|
|||
<?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:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1d35aoh" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
|
||||
<bpmn:process id="Process_BadGateway" name="Bad Gateway" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_065zdx1</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_065zdx1" sourceRef="StartEvent_1" targetRef="Activity_Hello" />
|
||||
<bpmn:sequenceFlow id="Flow_067y7wi" sourceRef="Activity_Hello" targetRef="Activity_PreData" />
|
||||
<bpmn:exclusiveGateway id="Gateway_0max6mi" default="Flow_True">
|
||||
<bpmn:incoming>Flow_0xguxj8</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_False</bpmn:outgoing>
|
||||
<bpmn:outgoing>Flow_True</bpmn:outgoing>
|
||||
</bpmn:exclusiveGateway>
|
||||
<bpmn:sequenceFlow id="Flow_False" name="False" sourceRef="Gateway_0max6mi" targetRef="Activity_GoodBye" />
|
||||
<bpmn:sequenceFlow id="Flow_True" sourceRef="Gateway_0max6mi" targetRef="Activity_Name" />
|
||||
<bpmn:endEvent id="Event_0vo2pjz">
|
||||
<bpmn:incoming>Flow_0enbio6</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0enbio6" sourceRef="Activity_GoodBye" targetRef="Event_0vo2pjz" />
|
||||
<bpmn:manualTask id="Activity_Hello" name="Hello">
|
||||
<bpmn:documentation><H1>Hello</H1></bpmn:documentation>
|
||||
<bpmn:incoming>Flow_065zdx1</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_067y7wi</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:scriptTask id="Activity_PreData" name="Pre Data">
|
||||
<bpmn:incoming>Flow_067y7wi</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_10wcmiq</bpmn:outgoing>
|
||||
<bpmn:script>if not 'yes_no' in globals():
|
||||
yes_no = True</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:manualTask id="Activity_GoodBye" name="Good Bye">
|
||||
<bpmn:documentation><H1>Good Bye</H1>
|
||||
{% if select_one %}
|
||||
<div></span>{{ name.value }}</span></div>
|
||||
{% endif %}</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_False</bpmn:incoming>
|
||||
<bpmn:incoming>Flow_0fldafi</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0enbio6</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:userTask id="Activity_Name" name="Name" camunda:formKey="NameForm">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="name" label="Please type your name" type="string" defaultValue="Cruel World" />
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_True</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0fldafi</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_10wcmiq" sourceRef="Activity_PreData" targetRef="Activity_DataSelect" />
|
||||
<bpmn:sequenceFlow id="Flow_0xguxj8" sourceRef="Activity_DataSelect" targetRef="Gateway_0max6mi" />
|
||||
<bpmn:userTask id="Activity_DataSelect" name="Data Select" camunda:formKey="DataSelectForm">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="select_one" label="Please Select One" type="boolean">
|
||||
<camunda:properties>
|
||||
<camunda:property id="value_expression" value="yes_no" />
|
||||
</camunda:properties>
|
||||
</camunda:formField>
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_10wcmiq</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0xguxj8</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_0fldafi" sourceRef="Activity_Name" targetRef="Activity_GoodBye" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_BadGateway">
|
||||
<bpmndi:BPMNEdge id="Flow_0pc4h1d_di" bpmnElement="Flow_False">
|
||||
<di:waypoint x="775" y="117" />
|
||||
<di:waypoint x="840" y="117" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="794" y="99" width="27" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_09jx2on_di" bpmnElement="Flow_True">
|
||||
<di:waypoint x="750" y="142" />
|
||||
<di:waypoint x="750" y="230" />
|
||||
<di:waypoint x="840" y="230" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="625" y="243" width="23" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0enbio6_di" bpmnElement="Flow_0enbio6">
|
||||
<di:waypoint x="940" y="117" />
|
||||
<di:waypoint x="1012" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0xguxj8_di" bpmnElement="Flow_0xguxj8">
|
||||
<di:waypoint x="670" y="117" />
|
||||
<di:waypoint x="725" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_10wcmiq_di" bpmnElement="Flow_10wcmiq">
|
||||
<di:waypoint x="510" y="117" />
|
||||
<di:waypoint x="570" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_067y7wi_di" bpmnElement="Flow_067y7wi">
|
||||
<di:waypoint x="350" y="117" />
|
||||
<di:waypoint x="410" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_065zdx1_di" bpmnElement="Flow_065zdx1">
|
||||
<di:waypoint x="195" y="117" />
|
||||
<di:waypoint x="250" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0fldafi_di" bpmnElement="Flow_0fldafi">
|
||||
<di:waypoint x="890" y="190" />
|
||||
<di:waypoint x="890" y="157" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Gateway_0max6mi_di" bpmnElement="Gateway_0max6mi" isMarkerVisible="true">
|
||||
<dc:Bounds x="725" y="92" width="50" height="50" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1277din_di" bpmnElement="Activity_GoodBye">
|
||||
<dc:Bounds x="840" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_06taoot_di" bpmnElement="Activity_Name">
|
||||
<dc:Bounds x="840" y="190" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1e89wvv_di" bpmnElement="Activity_PreData">
|
||||
<dc:Bounds x="410" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_09gfvub_di" bpmnElement="Activity_Hello">
|
||||
<dc:Bounds x="250" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="159" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1jxjzf1_di" bpmnElement="Activity_DataSelect">
|
||||
<dc:Bounds x="570" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0vo2pjz_di" bpmnElement="Event_0vo2pjz">
|
||||
<dc:Bounds x="1012" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -0,0 +1,14 @@
|
|||
from tests.base_test import BaseTest
|
||||
import json
|
||||
|
||||
class TestCustomerError(BaseTest):
|
||||
|
||||
def test_customer_error(self):
|
||||
# workflow = self.create_workflow('failing_workflow')
|
||||
# workflow_api = self.get_workflow_api(workflow)
|
||||
# first_task = workflow_api.next_task
|
||||
spec_model = self.load_test_spec('failing_gateway_workflow')
|
||||
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
#
|
||||
print('test_customer_error: ')
|
Loading…
Reference in New Issue