Squashed 'spiffworkflow-backend/' changes from 4f71a03e3..1b7c530a9

1b7c530a9 added some debug code for Processor failed to obtain task error w/ burnettk
cf5bbf0e7 Merge commit 'ec431349e8b5cc2e8aa1ee1799bcb768fd3116c3'
dfaa699f9 Merge pull request #7 from sartography/feature/get-local-time
3e1d6773e mypy
3471ab792 Added `get_localtime` script Added test for new script, with test process

git-subtree-dir: spiffworkflow-backend
git-subtree-split: 1b7c530a9ab2335a4a7b7efd1026464b333311aa
This commit is contained in:
burnettk 2022-10-26 13:42:08 -04:00
parent ec431349e8
commit 00dc4e149d
8 changed files with 243 additions and 17 deletions

View File

@ -20,7 +20,7 @@ groups:
natalia,
]
finance:
Finance Team:
users: [finance_user1]
permissions:
@ -30,11 +30,24 @@ permissions:
allowed_permissions: [create, read, update, delete, list, instantiate]
uri: /*
finance-admin:
groups: [finance]
tasks-crud:
groups: [everybody]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-groups/execute-procure-to-pay/*
uri: /v1.0/tasks/*
# TODO: all uris should really have the same structure
finance-admin-group:
groups: ["Finance Team"]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-groups/finance/*
finance-admin-model:
groups: ["Finance Team"]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-models/finance/*
read-all:
groups: [finance, admin]

View File

@ -46,12 +46,12 @@ class ActiveTaskModel(SpiffworkflowBaseDBModel):
updated_at_in_seconds: int = db.Column(db.Integer)
created_at_in_seconds: int = db.Column(db.Integer)
task_id = db.Column(db.String(50))
task_name = db.Column(db.String(50))
task_title = db.Column(db.String(50))
task_type = db.Column(db.String(50))
task_status = db.Column(db.String(50))
process_model_display_name = db.Column(db.String(255))
task_id: str = db.Column(db.String(50))
task_name: str = db.Column(db.String(50))
task_title: str = db.Column(db.String(50))
task_type: str = db.Column(db.String(50))
task_status: str = db.Column(db.String(50))
process_model_display_name: str = db.Column(db.String(255))
active_task_users = relationship("ActiveTaskUserModel", cascade="delete")
potential_owners = relationship( # type: ignore

View File

@ -1,4 +1,5 @@
"""APIs for dealing with process groups, process models, and process instances."""
import dataclasses
import json
import os
import random
@ -1352,6 +1353,13 @@ def get_spiff_task_from_process_instance(
task_uuid = uuid.UUID(task_id)
spiff_task = processor.bpmn_process_instance.get_task(task_uuid)
# FOR DEBUGGING: save this variable so we get it in sentry when something fails
active_task = ActiveTaskModel.query.filter_by(task_id=task_id).first()
if active_task:
task_json = dataclasses.asdict(active_task)
print(f"task_json: {task_json}")
########
if spiff_task is None:
raise (
ApiError(

View File

@ -0,0 +1,43 @@
from flask_bpmn.api.api_error import ApiError
from spiffworkflow_backend.scripts.script import Script
from datetime import datetime
import pytz
from typing import Any
from typing import Optional
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
class GetLocaltime(Script):
def get_description(self) -> str:
return """Converts a Datetime object into a Datetime object for a specific timezone.
Defaults to US/Eastern"""
def run(
self,
task: Optional[SpiffTask],
environment_identifier: str,
*args: Any,
**kwargs: Any
) -> datetime:
if len(args) > 0 or 'datetime' in kwargs:
if 'datetime' in kwargs:
date_time = kwargs['datetime']
else:
date_time = args[0]
if 'timezone' in kwargs:
timezone = kwargs['timezone']
elif len(args) > 1:
timezone = args[1]
else:
timezone = 'US/Eastern'
localtime: datetime = date_time.astimezone(pytz.timezone(timezone))
return localtime
else:
raise ApiError(error_code='missing_datetime',
message='You must include a datetime to convert.')

View File

@ -20,10 +20,12 @@ class DataSetupService:
failing_process_models = []
process_models = ProcessModelService().get_process_models()
for process_model in process_models:
if process_model.primary_file_name:
process_model_files = SpecFileService.get_files(
process_model, extension_filter=".bpmn"
)
for process_model_file in process_model_files:
bpmn_xml_file_contents = SpecFileService.get_data(
process_model, process_model.primary_file_name
process_model, process_model_file.name
)
bad_files = [
"B.1.0.bpmn",
@ -32,21 +34,21 @@ class DataSetupService:
"C.6.0.bpmn",
"TC-5.1.bpmn",
]
if process_model.primary_file_name in bad_files:
if process_model_file.name in bad_files:
continue
current_app.logger.debug(
f"primary_file_name: {process_model.primary_file_name}"
f"primary_file_name: {process_model_file.name}"
)
try:
SpecFileService.update_file(
process_model,
process_model.primary_file_name,
process_model_file.name,
bpmn_xml_file_contents,
)
except Exception as ex:
failing_process_models.append(
(
f"{process_model.process_group_id}/{process_model.id}/{process_model.primary_file_name}",
f"{process_model.process_group_id}/{process_model.id}/{process_model_file.name}",
str(ex),
)
)

View File

@ -0,0 +1,79 @@
<?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:process id="Proccess_LocalTime" name="Get LocalTime" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_0ijucqh</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_0ijucqh" sourceRef="StartEvent_1" targetRef="Activity_GetTimezone" />
<bpmn:scriptTask id="Activity_GetTime" name="Get Time">
<bpmn:documentation>Get Time</bpmn:documentation>
<bpmn:incoming>Flow_10y2eax</bpmn:incoming>
<bpmn:outgoing>Flow_1gcfk27</bpmn:outgoing>
<bpmn:script>some_time = datetime.now()
localtime = get_localtime(some_time, timezone)</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_1gcfk27" sourceRef="Activity_GetTime" targetRef="Activity_DisplayTime" />
<bpmn:endEvent id="Event_1c50ix7">
<bpmn:incoming>Flow_0dcc306</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0dcc306" sourceRef="Activity_DisplayTime" targetRef="Event_1c50ix7" />
<bpmn:manualTask id="Activity_DisplayTime" name="Display Time">
<bpmn:documentation>Display the time</bpmn:documentation>
<bpmn:extensionElements>
<spiffworkflow:instructionsForEndUser>## Time
### Some Time: {{ some_time }}
### Timezone: {{ timezone }}
### Localtime: {{ localtime }}</spiffworkflow:instructionsForEndUser>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1gcfk27</bpmn:incoming>
<bpmn:outgoing>Flow_0dcc306</bpmn:outgoing>
</bpmn:manualTask>
<bpmn:sequenceFlow id="Flow_10y2eax" sourceRef="Activity_GetTimezone" targetRef="Activity_GetTime" />
<bpmn:userTask id="Activity_GetTimezone" name="Get Timezone">
<bpmn:extensionElements>
<spiffworkflow:properties>
<spiffworkflow:property name="formJsonSchemaFilename" value="get_localtime.json" />
</spiffworkflow:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0ijucqh</bpmn:incoming>
<bpmn:outgoing>Flow_10y2eax</bpmn:outgoing>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Proccess_LocalTime">
<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_1ahvmya_di" bpmnElement="Activity_GetTime">
<dc:Bounds x="430" y="137" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1c50ix7_di" bpmnElement="Event_1c50ix7">
<dc:Bounds x="752" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1gfsyxd_di" bpmnElement="Activity_DisplayTime">
<dc:Bounds x="590" y="137" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1x3u69s_di" bpmnElement="Activity_GetTimezone">
<dc:Bounds x="270" y="137" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0ijucqh_di" bpmnElement="Flow_0ijucqh">
<di:waypoint x="215" y="177" />
<di:waypoint x="270" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1gcfk27_di" bpmnElement="Flow_1gcfk27">
<di:waypoint x="530" y="177" />
<di:waypoint x="590" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0dcc306_di" bpmnElement="Flow_0dcc306">
<di:waypoint x="690" y="177" />
<di:waypoint x="752" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10y2eax_di" bpmnElement="Flow_10y2eax">
<di:waypoint x="370" y="177" />
<di:waypoint x="430" y="177" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,20 @@
{
"title": "Get Timezone",
"description": "Form to select a timezone.",
"type": "object",
"required": [
"timezone"
],
"properties": {
"timezone": {
"type": "string",
"title": "Timezone",
"enum": [
"US/Eastern",
"US/Pacific",
"Europe/Berlin",
"Australia/ACT"
]
}
}
}

View File

@ -0,0 +1,61 @@
import datetime
import pytz
from flask.app import Flask
from flask.testing import FlaskClient
from spiffworkflow_backend.scripts.get_localtime import GetLocaltime
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
class TestGetLocaltime(BaseTest):
"""TestProcessAPi."""
def test_get_localtime_script_directly(self) -> None:
current_time = datetime.datetime.now()
timezone = "US/Pacific"
result = GetLocaltime().run(task=None, environment_identifier='testing', datetime=current_time, timezone=timezone)
assert result == current_time.astimezone(pytz.timezone(timezone))
def test_get_localtime_script_through_bpmn(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_process_instance_run."""
initiator_user = self.find_or_create_user("initiator_user")
process_model = load_test_spec(
process_model_id="get_localtime", bpmn_file_name="get_localtime.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)
active_task = process_instance.active_tasks[0]
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
active_task.task_name, processor.bpmn_process_instance
)
ProcessInstanceService.complete_form_task(
processor, spiff_task, {"timezone": "US/Pacific"}, initiator_user
)
active_task = process_instance.active_tasks[0]
spiff_task = processor.__class__.get_task_by_bpmn_identifier(
active_task.task_name, processor.bpmn_process_instance
)
assert spiff_task
data = spiff_task.data
some_time = data['some_time']
localtime = data['localtime']
timezone = data['timezone']
assert localtime == some_time.astimezone(pytz.timezone(timezone))