Automatically Acquire Revision History of Input Data

I will explain how to realize an automatic Step (Process Modeler Add-on) that checks differences in entered contents between Steps and records them as revision history.

Hi, there!

In Questetra, we are working on “automating on work” variously.
Various automation has been made possible in a method of Process Modeler Add-on.

Process Modeler Add-ons
The “Modeling function” that defines a Business Process can be enhanced by three aspects: a) Addition of a modeling icon, b) Mastering choice options, and c) PDF Auto-generation. By importing the following Add-ons, you can more efficiently define further advanced Business Processes. You can also create your own Add-on file by yourself.

https://www.questetra.com/addon/#tax-term-browser-api-orchestration-en

This time, I would like to automate operations to which I had corresponded by copy & paste so far.

Scenario

We are going to create an example of automation based on the month-end billing flow that we introduced you in Workflow-sample.

Episode 557: Fully Automatic Billing Flow that Communicates with Various APIs
The monthly billing business at the end of the month has become to be conducted without missing!
With regard to “charged amount” to each customer, it became possible to catch in real time that who has input or who approved and when. Moreover, thanks to the “Automatic Step” which accesses the credit company API (Stripe API), charging to credit cards are…

http://en.workflow-sample.net/2017/10/automatic-billing-operation.html

<Work flow diagram (The original)>

<Operating form: Charge info>

In the started monthly billing flow, it inputs billing information and saves it. And then stands by for change information from the customer, and automatically flows by the Timer Intermediate Event.
If there is a revising request from the customer, it is entered at Steps of “1. Billing info edit” or “1rr. Billing info edit”. Then it flows back to the same Step by the split of “Info updating”.

Correspondingly, there might be a question such as

* What was the original charge info like?

That is, although it would be alright if revising was finished in only one interaction with customers, you would like to record past decisions so that be able to review them later, in cases where revision occurred multiply.

Even so, you may suppose or consider that

* Isn’t it enough by checking to look back the emails which have been sent from the customer?
* I wish I could, but it seems cumbersome and to take lots of effort…

Moreover, it is supposed to take labor to correspond since there are at least more than one steps have a possibility of revision.

I would like to resolve such concerns with auto-step Add-ons (script processing within the workflow platform).

For this time, I will create an automatic processing service under the name “Revision history set service“.
As its requirement, I will set

* Capable of referring which Data Item has been revised.
* Capable of configuring multiple items as the target of revision history.

Implementation

The specification of configuration in “Revision history set service” Add-on is as follows.

* (history acquisition) Target item Name
– Describe the Data Item name (Limited to String/Numeric/Date/DatetTme/Select type)
– Multiple entries possible (Single-byte comma separated)
* Data Item to store history
– Data Item to store the contents of historical revisions
– Select a String type Data Item multiple-line
* Data Item to store the Latest data
– Data Item to store original data to compare
– Select a String type Data Item multiple-line

* “Data Item to store history” and “Data Item to store the Latest data” must have been added to the sample App in advance.

<Revision history set service setting screen: setting example>

* The code will be described later.

Place this “Revision history set service” in the Workflow diagram.
(Place it in locations where splitting of “Info updating” has been set)

<Workflow diagram: “Revision history set service” is placed>

With these settings, revision histories will be recorded automatically through the flow to the service triggered by an occurrence of information revision action.

<Operation consequence screen>

<Codes of “Revision history set service” Add-on>

<?xml version="1.0" encoding="UTF-8"?><service-task-definition>

<label>Revision history set service</label>

<configs>
  <config name="conf_ItemNamesForNoteHistory" required="true" form-type="TEXTFIELD">
    <label>Target item Name * Single-byte comma separated</label>
  </config>
  <config name="conf_NoteHistory" required="true" form-type="SELECT" select-data-type="STRING_TEXTAREA">
    <label>Data Item to store history</label>
  </config>
  <config name="conf_RecentNote" required="true" form-type="SELECT" select-data-type="STRING_TEXTAREA">
    <label>Data Item to store the Latest data</label>
  </config>
  <config name="conf_DebugPrint" required="false" form-type="SELECT" select-data-type="STRING_TEXTAREA">
    <label>Data indication for debugging (No-display if not specified)</label>
  </config>
</configs>

<script><![CDATA[
// Script for Revision history set service (ver. 20171015)
// (c) 2017, Questetra, Inc. (the MIT License)

main();

function main(){
	//// == Config Retrieving ==
	var itemNamesForNoteHistory = configs.get("conf_ItemNamesForNoteHistory");
	var noteHistoryNum = configs.get("conf_NoteHistory");
	var recentNoteNum = configs.get("conf_RecentNote");
	var debugPrintNum = configs.get("conf_DebugPrint");

	//// == Data Retrieving, Data Define ==
	var itemNames = new String(itemNamesForNoteHistory).split(",");
	var recentNote = engine.findDataByNumber(recentNoteNum);
	var date = new Date();
	var separateChars = ":";
	var separateStr = "---- " + date.getFullYear() + "/" + (date.getMonth()+1) + "/" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + " ----\n";
	var diffNote = "";
	var diffResult = false;
	var strs;
	var debug = "";

	//// == Calculating ==
	if (recentNote != null){ // For the second and subsequent input
		recentNoteRows = new String(recentNote).split("\n");
		for (var i=0; i < recentNoteRows.length; i++){
    		var itemName = recentNoteRows[i].slice(0,recentNoteRows[i].indexOf(separateChars));
    		var itemValue = recentNoteRows[i].slice(recentNoteRows[i].indexOf(separateChars)+1);
    		debug += itemName + ":" + itemValue + "\n";
			for (var j=0; j < itemNames.length; j++){
    			if (itemName == itemNames[j]){
    				if (!itemValue.equals(converToString(itemNames[j]))){
	  					diffResult = true;
			  			diffNote += itemNames[j] + separateChars + converToString(itemNames[j]) + "\n";
		   			}
	     		}
			}
		}
	}
	else{  // For the initial input
		diffResult = true;
		for (var i=0; i < itemNames.length; i++){
			diffNote += itemNames[i] + separateChars + converToString(itemNames[i]) + "\n";
		}
	}
	//// == Data Updating ==
	if (diffResult){ // When a revision has occurred
		var note = engine.findDataByNumber(noteHistoryNum);
		if (note == null){
    		note = "";
		}
		note += separateStr;
	   	note += diffNote;
	   	engine.setDataByNumber(noteHistoryNum, note);
	   	recentNote = "";
		for (var i=0; i < itemNames.length; i++){
			recentNote += itemNames[i] + separateChars + converToString(itemNames[i]) + "\n";
		}
	   engine.setDataByNumber(recentNoteNum,recentNote);
	}
	
	// for Debug
	if (debugPrintNum != ""){
    	engine.setDataByNumber(debugPrintNum,debug);
	}

}
//// == Return content of Data Item in specified name as strings ==
//// Parameter: Data Item name
//// Return value: Content entered in Data Item of the specified name (strings)
function converToString(name){
	var definitionView = engine.findDataDefinitionByName(name);
	var stringData = "";
	if (engine.findDataByName(name) == null){
		return stringData;
	}
	if ((definitionView.matchDataType("STRING"))||(definitionView.matchDataType("DECIMAL"))){
		stringData = engine.findDataByName(name);
	}
	if ((definitionView.matchDataType("DATE"))||(definitionView.matchDataType("DATETIME"))){
		var formatter = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm");
		stringData = formatter.format(engine.findDataByName(name));
	}
	if (definitionView.matchDataType("SELECT")){
		var selects = engine.findDataByName(name);
		for (var i=0; i < selects.size(); i++){
			stringData += selects.get(i).getDisplay() + ",";
		}
		stringData = stringData.replace(/\,$/,"");
	}
	return stringData;
}
]]></script>


<icon>
(omitted)
</icon>

</service-task-definition>

Closing

As a specification of Questetra, when inputting to the same input form in multiple Steps, the data is overwritten.
Even though in many cases the necessity to know the contents of past input is small, information of the past may be necessary as reference information when data has been changed any number of times at customer ‘s convenience like written in the “scenario”.
In such a case, this is an effective Add-on. (Easy to set up as well.)

Of course, it can be realized with a Script Task, but since it seems that it can be used generically (even in other Apps), so I made it into a package considering common use.

Adding an Auto-Step to be Used for Business Process Definition
When you want to automate Processing-steps, such as “Obtaining Number of characters and Hash value”, it is impossible to define them using only standard [Service Task] and [Event] (You must use [Script Task] ). However, you will be able to automate your business easily by importing [Addon XML], such as “Number of Character Counter-addon.xml” or “SHA Hash-addon.xml”, in advance. (Service-Task Addon)

https://www.questetra.com/tour/m4/m415/

Although it is limited to “String type/Numerical type/Date type/DateTime type/Select type” currently, you will be able to implement User type and Organization type relatively easy.
I hope you to consider using it by all means.

If you have any questions, please feel free to contact us.

2017-10-31

About Masato Furukubo

Questetra, Inc. Sales Department
View all posts by Masato Furukubo

Recommendations
Prev article - 50. Questetra Tips How to Let a Robot Nominates Translators Randomly (3)
Next article - 50. Questetra Tips Let's Create a Cool(?) Questionnaire Management System! (1)
Another article - Masato Furukubo How to Let a Robot Nominates Translators Randomly (2)

Archive

 RSS