Merge pull request #88 from sartography/feature/process-nav-improvements
Feature/process nav improvements
This commit is contained in:
commit
6459d13960
|
@ -574,39 +574,13 @@ def process_instance_reset(
|
||||||
modified_process_model_identifier: str,
|
modified_process_model_identifier: str,
|
||||||
spiff_step: int = 0,
|
spiff_step: int = 0,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Process_instance_reset."""
|
"""Reset a process instance to a particular step."""
|
||||||
process_instance = ProcessInstanceService().get_process_instance(
|
process_instance = ProcessInstanceService().get_process_instance(
|
||||||
process_instance_id
|
process_instance_id
|
||||||
)
|
)
|
||||||
step_detail = (
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
db.session.query(SpiffStepDetailsModel)
|
processor.reset_process(spiff_step)
|
||||||
.filter(
|
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
||||||
SpiffStepDetailsModel.process_instance_id == process_instance.id,
|
|
||||||
SpiffStepDetailsModel.spiff_step == spiff_step,
|
|
||||||
)
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
if step_detail is not None and process_instance.bpmn_json is not None:
|
|
||||||
bpmn_json = json.loads(process_instance.bpmn_json)
|
|
||||||
bpmn_json["tasks"] = step_detail.task_json["tasks"]
|
|
||||||
bpmn_json["subprocesses"] = step_detail.task_json["subprocesses"]
|
|
||||||
process_instance.bpmn_json = json.dumps(bpmn_json)
|
|
||||||
|
|
||||||
db.session.add(process_instance)
|
|
||||||
try:
|
|
||||||
db.session.commit()
|
|
||||||
except Exception as e:
|
|
||||||
db.session.rollback()
|
|
||||||
raise ApiError(
|
|
||||||
error_code="reset_process_instance_error",
|
|
||||||
message=f"Could not update the Instance. Original error is {e}",
|
|
||||||
) from e
|
|
||||||
|
|
||||||
return Response(
|
|
||||||
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
|
||||||
status=200,
|
|
||||||
mimetype="application/json",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_process_instance(
|
def _get_process_instance(
|
||||||
|
|
|
@ -646,7 +646,7 @@ class ProcessInstanceProcessor:
|
||||||
subprocesses_by_child_task_ids[task_id] = subprocess_id
|
subprocesses_by_child_task_ids[task_id] = subprocess_id
|
||||||
return subprocesses_by_child_task_ids
|
return subprocesses_by_child_task_ids
|
||||||
|
|
||||||
def _save(self) -> None:
|
def save(self) -> None:
|
||||||
"""Saves the current state of this processor to the database."""
|
"""Saves the current state of this processor to the database."""
|
||||||
self.process_instance_model.bpmn_json = self.serialize()
|
self.process_instance_model.bpmn_json = self.serialize()
|
||||||
|
|
||||||
|
@ -668,9 +668,6 @@ class ProcessInstanceProcessor:
|
||||||
db.session.add(self.process_instance_model)
|
db.session.add(self.process_instance_model)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
def save(self) -> None:
|
|
||||||
"""Saves the current state and moves on to the next state."""
|
|
||||||
self._save()
|
|
||||||
human_tasks = HumanTaskModel.query.filter_by(
|
human_tasks = HumanTaskModel.query.filter_by(
|
||||||
process_instance_id=self.process_instance_model.id
|
process_instance_id=self.process_instance_model.id
|
||||||
).all()
|
).all()
|
||||||
|
@ -758,6 +755,13 @@ class ProcessInstanceProcessor:
|
||||||
self.bpmn_process_instance.catch(event_definition)
|
self.bpmn_process_instance.catch(event_definition)
|
||||||
self.do_engine_steps(save=True)
|
self.do_engine_steps(save=True)
|
||||||
|
|
||||||
|
def add_step(self, step: Union[dict, None] = None) -> None:
|
||||||
|
"""Add a spiff step."""
|
||||||
|
if step is None:
|
||||||
|
step = self.spiff_step_details_mapping()
|
||||||
|
db.session.add(SpiffStepDetailsModel(**step))
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
def manual_complete_task(self, task_id: str, execute: bool) -> None:
|
def manual_complete_task(self, task_id: str, execute: bool) -> None:
|
||||||
"""Mark the task complete optionally executing it."""
|
"""Mark the task complete optionally executing it."""
|
||||||
spiff_task = self.bpmn_process_instance.get_task(UUID(task_id))
|
spiff_task = self.bpmn_process_instance.get_task(UUID(task_id))
|
||||||
|
@ -768,18 +772,64 @@ class ProcessInstanceProcessor:
|
||||||
)
|
)
|
||||||
spiff_task.complete()
|
spiff_task.complete()
|
||||||
else:
|
else:
|
||||||
current_app.logger.info(
|
spiff_logger = logging.getLogger("spiff")
|
||||||
f"Skipping Task {spiff_task.task_spec.name} of process instance"
|
spiff_logger.info(
|
||||||
f" {self.process_instance_model.id}"
|
f"Skipped task {spiff_task.task_spec.name}", extra=spiff_task.log_info()
|
||||||
)
|
)
|
||||||
spiff_task._set_state(TaskState.COMPLETED)
|
spiff_task._set_state(TaskState.COMPLETED)
|
||||||
for child in spiff_task.children:
|
for child in spiff_task.children:
|
||||||
child.task_spec._update(child)
|
child.task_spec._update(child)
|
||||||
self.bpmn_process_instance.last_task = spiff_task
|
self.bpmn_process_instance.last_task = spiff_task
|
||||||
self._save()
|
self.increment_spiff_step()
|
||||||
|
self.add_step()
|
||||||
|
self.save()
|
||||||
# Saving the workflow seems to reset the status
|
# Saving the workflow seems to reset the status
|
||||||
self.suspend()
|
self.suspend()
|
||||||
|
|
||||||
|
def reset_process(self, spiff_step: int) -> None:
|
||||||
|
"""Reset a process to an earlier state."""
|
||||||
|
spiff_logger = logging.getLogger("spiff")
|
||||||
|
spiff_logger.info(
|
||||||
|
f"Process reset from step {spiff_step}",
|
||||||
|
extra=self.bpmn_process_instance.log_info(),
|
||||||
|
)
|
||||||
|
|
||||||
|
step_detail = (
|
||||||
|
db.session.query(SpiffStepDetailsModel)
|
||||||
|
.filter(
|
||||||
|
SpiffStepDetailsModel.process_instance_id
|
||||||
|
== self.process_instance_model.id,
|
||||||
|
SpiffStepDetailsModel.spiff_step == spiff_step,
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if step_detail is not None:
|
||||||
|
self.increment_spiff_step()
|
||||||
|
self.add_step(
|
||||||
|
{
|
||||||
|
"process_instance_id": self.process_instance_model.id,
|
||||||
|
"spiff_step": self.process_instance_model.spiff_step or 1,
|
||||||
|
"task_json": step_detail.task_json,
|
||||||
|
"timestamp": round(time.time()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
dct = self._serializer.workflow_to_dict(self.bpmn_process_instance)
|
||||||
|
dct["tasks"] = step_detail.task_json["tasks"]
|
||||||
|
dct["subprocesses"] = step_detail.task_json["subprocesses"]
|
||||||
|
self.bpmn_process_instance = self._serializer.workflow_from_dict(dct)
|
||||||
|
|
||||||
|
# Cascade does not seems to work on filters, only directly through the session
|
||||||
|
tasks = self.bpmn_process_instance.get_tasks(TaskState.NOT_FINISHED_MASK)
|
||||||
|
rows = HumanTaskModel.query.filter(
|
||||||
|
HumanTaskModel.task_id.in_(str(t.id) for t in tasks) # type: ignore
|
||||||
|
).all()
|
||||||
|
for row in rows:
|
||||||
|
db.session.delete(row)
|
||||||
|
|
||||||
|
self.save()
|
||||||
|
self.suspend()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_parser() -> MyCustomParser:
|
def get_parser() -> MyCustomParser:
|
||||||
"""Get_parser."""
|
"""Get_parser."""
|
||||||
|
|
|
@ -269,10 +269,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||||
return spiffStepLink(<CaretRight />, 1);
|
return spiffStepLink(<CaretRight />, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const returnToLastSpiffStep = () => {
|
||||||
|
window.location.href = `/admin/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||||
|
};
|
||||||
|
|
||||||
const resetProcessInstance = () => {
|
const resetProcessInstance = () => {
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: `${targetUris.processInstanceResetPath}/${currentSpiffStep()}`,
|
path: `${targetUris.processInstanceResetPath}/${currentSpiffStep()}`,
|
||||||
successCallback: refreshPage,
|
successCallback: returnToLastSpiffStep,
|
||||||
httpMethod: 'POST',
|
httpMethod: 'POST',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -647,8 +651,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: `/task-complete/${modifiedProcessModelId}/${params.process_instance_id}/${taskToUse.id}`,
|
path: `/task-complete/${modifiedProcessModelId}/${params.process_instance_id}/${taskToUse.id}`,
|
||||||
httpMethod: 'POST',
|
httpMethod: 'POST',
|
||||||
successCallback: saveTaskDataResult,
|
successCallback: returnToLastSpiffStep,
|
||||||
failureCallback: saveTaskDataFailure,
|
|
||||||
postBody: { execute },
|
postBody: { execute },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -727,7 +730,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||||
data-qa="mark-task-complete-button"
|
data-qa="mark-task-complete-button"
|
||||||
onClick={() => completeTask(false)}
|
onClick={() => completeTask(false)}
|
||||||
>
|
>
|
||||||
Mark Complete
|
Skip Task
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
buttons.push(
|
buttons.push(
|
||||||
|
@ -755,7 +758,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||||
data-qa="reset-process-button"
|
data-qa="reset-process-button"
|
||||||
onClick={() => resetProcessInstance()}
|
onClick={() => resetProcessInstance()}
|
||||||
>
|
>
|
||||||
Resume Process Here
|
Reset Process Here
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue