Skip to content

Commit

Permalink
Capture task variables on application creation without FormBPMFiltere…
Browse files Browse the repository at this point in the history
…dDataPipelineListener. (#1797)

* Capture task variables without listener

Capture task variables on application creation without FormBPMFilteredDataPipelineListener.

* pytest fix

* updated payload

* Add get process instance variables to api-spec

* Add test case

---------

Co-authored-by: abilpraju-aot <[email protected]>
  • Loading branch information
auslin-aot and abilpraju-aot authored Dec 14, 2023
1 parent 7f31a28 commit f797276
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 7 deletions.
2 changes: 2 additions & 0 deletions forms-flow-api/src/formsflow_api/schemas/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Meta: # pylint: disable=too-few-public-methods
web_form_url = fields.Str(data_key="webFormUrl", load_only=True)
is_resubmit = fields.Bool(data_key="isResubmit", dump_only=True)
event_name = fields.Str(data_key="eventName", dump_only=True)
data = fields.Dict(data_key="data", load_only=True)


class ApplicationUpdateSchema(Schema):
Expand Down Expand Up @@ -92,3 +93,4 @@ class Meta: # pylint: disable=too-few-public-methods
form_url = fields.Str(data_key="formUrl", required=True)
submission_id = fields.Str(data_key="submissionId", required=True)
web_form_url = fields.Str(data_key="webFormUrl", load_only=True)
data = fields.Dict(data_key="data", load_only=True)
10 changes: 9 additions & 1 deletion forms-flow-api/src/formsflow_api/services/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ def get_start_task_payload(
mapper: FormProcessMapper,
form_url: str,
web_form_url: str,
variables: Dict,
) -> Dict:
"""Returns the payload for initiating the task."""
return {
"variables": {
**variables,
"applicationId": {"value": application.id},
"formUrl": {"value": form_url},
"webFormUrl": {"value": web_form_url},
Expand Down Expand Up @@ -107,6 +109,12 @@ def create_application(data, token, **kwargs):
if tenant_key is not None and mapper.tenant != tenant_key:
raise BusinessException(BusinessErrorCode.PERMISSION_DENIED)
data["form_process_mapper_id"] = mapper.id
task_variables = (
json.loads(mapper.task_variable) if mapper.task_variable is not None else []
)
variables = ApplicationService.fetch_task_variable_values(
task_variables, data.get("data", {})
)
# Function to create application in DB
application = Application.create_from_dict(data)
# process_instance_id in request object is usually used in Scripts
Expand All @@ -117,7 +125,7 @@ def create_application(data, token, **kwargs):
form_url = data["form_url"]
web_form_url = data.get("web_form_url", "")
payload = ApplicationService.get_start_task_payload(
application, mapper, form_url, web_form_url
application, mapper, form_url, web_form_url, variables
)
ApplicationService.start_task(mapper, payload, token, application)
return application, HTTPStatus.CREATED
Expand Down
9 changes: 8 additions & 1 deletion forms-flow-api/src/formsflow_api/services/draft.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""This exposes submission service."""

import json
from typing import Dict

from formsflow_api_utils.exceptions import BusinessException
Expand Down Expand Up @@ -127,8 +128,14 @@ def make_submission_from_draft(data: Dict, draft_id: str, token=None, **kwargs):
# The form mapper version got updated after the draft entry
# was created, update the application with new mapper
application.update({"form_process_mapper_id": mapper.id})
task_variables = (
json.loads(mapper.task_variable) if mapper.task_variable is not None else []
)
variables = ApplicationService.fetch_task_variable_values(
task_variables, data.get("data", {})
)
payload = ApplicationService.get_start_task_payload(
application, mapper, data["form_url"], data["web_form_url"]
application, mapper, data["form_url"], data["web_form_url"], variables
)
ApplicationService.start_task(mapper, payload, token, application)
return application
Expand Down
2 changes: 1 addition & 1 deletion forms-flow-api/tests/docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
image: stoplight/prism:3.3.0
command: >
mock -p 4010 --host 0.0.0.0
https://raw.githubusercontent.com/AOT-Technologies/forms-flow-ai/develop/forms-flow-bpm/api-spec/forms-flow-bpm-api-spec.yaml
https://raw.githubusercontent.com/auslin-aot/forms-flow-ai/FWF-2820_capture_task_variables/forms-flow-bpm/api-spec/forms-flow-bpm-api-spec.yaml
analytics:
image: stoplight/prism:3.3.0
command: >
Expand Down
68 changes: 68 additions & 0 deletions forms-flow-api/tests/unit/api/test_application.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
"""Test suite for application API endpoint."""
import os

import pytest
import requests

from tests.utilities.base_test import (
get_application_create_payload,
get_draft_create_payload,
get_form_request_payload,
get_formio_form_request_payload,
get_token,
)

Expand Down Expand Up @@ -344,3 +348,67 @@ def test_application_resubmit(app, client, session, jwt):
f"/application/{application_id}/resubmit", headers=headers, json=payload
)
assert rv.status_code == 200


def test_capture_process_variables_application_create(app, client, session, jwt):
"""Tests the capturing of process variables in the application creation method."""
token = get_token(jwt, role="formsflow-designer", username="designer")
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
}
# Design form
response = client.post(
"/form/form-design", headers=headers, json=get_formio_form_request_payload()
)
assert response.status_code == 201
form_id = response.json.get("_id")
# Added task variable to the form
payload = {
"formId": form_id,
"formName": "Sample form",
"processKey": "two-step-approval",
"processName": "Two Step Approval",
"status": "active",
"formType": "form",
"parentFormId": "1234",
"taskVariable": [
{
"key": "textField",
"defaultLabel": "Text Field",
"label": "Text Field",
"showInList": False,
}
],
}
rv = client.post("/form", headers=headers, json=payload)
assert rv.status_code == 201
form_id = rv.json.get("formId")

# Submit new application as client
payload = get_application_create_payload(form_id)
payload["data"] = {
"textField": "Test",
"applicationId": "",
"applicationStatus": "",
}
token = get_token(jwt)
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
}
rv = client.post(
"/application/create",
headers=headers,
json=payload,
)

assert rv.status_code == 201
processInstanceId = rv.json.get("processInstanceId")
assert processInstanceId is not None
# Check variable added to process
bpm_api_base = os.getenv("BPM_API_URL")
url = f"{bpm_api_base}/engine-rest-ext/v1/process-instance/{processInstanceId}/variables"
response = requests.get(url, headers=headers)
assert response.status_code == 200
assert response.json().get("textField") == {"type": "String", "value": "Test"}
66 changes: 66 additions & 0 deletions forms-flow-api/tests/unit/api/test_draft.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Test suite for 'draft' namespace API endpoints."""
import os

import requests
from formsflow_api_utils.utils import (
ANONYMOUS_USER,
DRAFT_APPLICATION_STATUS,
Expand All @@ -13,6 +16,7 @@
get_draft_create_payload,
get_form_model_object,
get_form_request_payload,
get_formio_form_request_payload,
get_token,
)

Expand Down Expand Up @@ -241,3 +245,65 @@ def test_delete_draft(app, client, session, jwt):
headers = {"Authorization": f"Bearer {token}", "content-type": "application/json"}
rv = client.delete(f"/draft/{draft_id}", headers=headers)
assert rv.status_code == 400


def test_capture_process_variables_draft_create_method(app, client, session, jwt):
"""Tests the capturing of process variables in the draft create method."""
token = get_token(jwt, role="formsflow-designer", username="designer")
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
}
# Design form
response = client.post(
"/form/form-design", headers=headers, json=get_formio_form_request_payload()
)
assert response.status_code == 201
form_id = response.json.get("_id")
# Added task variable to the form
payload = {
"formId": form_id,
"formName": "Sample form",
"processKey": "two-step-approval",
"processName": "Two Step Approval",
"status": "active",
"formType": "form",
"parentFormId": "1234",
"taskVariable": [
{
"key": "textField",
"defaultLabel": "Text Field",
"label": "Text Field",
"showInList": False,
}
],
}
rv = client.post("/form", headers=headers, json=payload)
assert rv.status_code == 201
form_id = rv.json.get("formId")
# Draft submission
token = get_token(jwt)
headers = {
"Authorization": f"Bearer {token}",
"content-type": "application/json",
}
draft = client.post(
"/draft", headers=headers, json=get_draft_create_payload(form_id)
)
assert draft.status_code == 201
draft_id = draft.json.get("id")
payload = get_application_create_payload()
payload["data"] = {
"textField": "Test",
"applicationId": "",
"applicationStatus": "",
}
response = client.put(f"/draft/{draft_id}/submit", headers=headers, json=payload)
processInstanceId = response.json.get("processInstanceId")
assert processInstanceId is not None
# Check variable added to process
bpm_api_base = os.getenv("BPM_API_URL")
url = f"{bpm_api_base}/engine-rest-ext/v1/process-instance/{processInstanceId}/variables"
response = requests.get(url, headers=headers)
assert response.status_code == 200
assert response.json().get("textField") == {"type": "String", "value": "Test"}
50 changes: 50 additions & 0 deletions forms-flow-bpm/api-spec/forms-flow-bpm-api-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1851,3 +1851,53 @@ paths:
processVariables:
aVariable:
value: aNewValue
/engine-rest-ext/v1/process-instance/{id}/variables:
get:
tags:
- Process
summary: Get process instance variables by id
description: |-
Retrieves a process instance variables by id.
#### Method
GET /process-instance/{id}/variables
parameters:
- name: id
in: path
schema:
type: string
required: true
responses:
'200':
description: Successful response
content:
application/json:
examples:
example-1:
value:
applicationStatus:
type: String
value: New
formUrl:
type: String
value: 'http://localhost:3001/form/626ba203004a95dd15f6b3ad/submission/6273a24051ae2f25bd45793c'
tenantKey:
type: 'Null'
value: null
formName:
type: String
value: dashboard check
webFormUrl:
type: String
value: 'http://localhost:3000/form/626ba203004a95dd15f6b3ad/submission/6273a24051ae2f25bd45793c'
submissionDate:
type: String
value: '2023-02-02 05:53:49.708258'
submitterName:
type: String
value: Test-user
applicationId:
type: Integer
value: 1113
textField:
type: String
value: Test
5 changes: 3 additions & 2 deletions forms-flow-web/src/apiManager/services/bpmServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { StorageService, RequestService } from "@formsflow/service";
import API from "../endpoints";
import {getFormUrlWithFormIdSubmissionId} from "./formatterService";

export const getProcessReq = (form, submissionId, origin ) => {
export const getProcessReq = (form, submissionId, origin, submissionData ) => {
const requestFormat = {
formId: form._id,
submissionId: submissionId,
formUrl: getFormUrlWithFormIdSubmissionId(form._id, submissionId),
webFormUrl: `${origin}form/${form._id}/submission/${submissionId}`
webFormUrl: `${origin}form/${form._id}/submission/${submissionId}`,
data: submissionData
};
return requestFormat;
};
Expand Down
3 changes: 2 additions & 1 deletion forms-flow-web/src/components/Draft/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,14 +367,15 @@ const doProcessActions = (submission, ownProps) => {
const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : `/`;
dispatch(resetSubmissions("submission"));
const origin = `${window.location.origin}${redirectUrl}`;
const data = getProcessReq(form, submission._id, origin);
const data = getProcessReq(form, submission._id, origin, submission?.data);
let draft_id = state.draft.submission?.id;
let isDraftCreated = draft_id ? true : false;
const applicationCreateAPI = selectApplicationCreateAPI(
isAuth,
isDraftCreated,
DRAFT_ENABLED
);

dispatch(
applicationCreateAPI(data, draft_id ? draft_id : null, (err) => {
dispatch(setFormSubmissionLoading(false));
Expand Down
2 changes: 1 addition & 1 deletion forms-flow-web/src/components/Form/Item/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ const doProcessActions = (submission, ownProps) => {
const redirectUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : `/`;
const origin = `${window.location.origin}${redirectUrl}`;
dispatch(resetSubmissions("submission"));
const data = getProcessReq(form, submission._id, origin);
const data = getProcessReq(form, submission._id, origin,submission?.data);
let draft_id = state.draft.draftSubmission?.id;
let isDraftCreated = draft_id ? true : false;
const applicationCreateAPI = selectApplicationCreateAPI(
Expand Down

0 comments on commit f797276

Please sign in to comment.