Welcome to the OPA Hub!

Tag Archives: Tutorial

List of Values, Display Values and Translations in Oracle Policy Automation

List of Values, Display Values and Translations  in Oracle Policy Automation

A common List of Values question that comes up is the following:

“How are list of values handled in Oracle Policy Automation, when I have more than one language? What gets put into the database?”

Of course, by “database” I mean whatever platform you are using to save the response from Oracle Policy Automation  : Oracle Sales Cloud, Oracle Service Cloud, Oracle Siebel CRM, Salesforce or any other.  For the record, the exact behaviour of your Connector will depend on how it has been programmed,but if it is doing what it should be doing, then the following information will apply.

The question that comes up is actually, to be fair, usually more detailed : people want to know the behaviour of the list of values both when it is created as a Screen element (single-use) or as a Value List (multi-use) and when there is more than one language involved. Well, fear not because the video below will answer all of those questions I hope, in a friendly and easy to follow way.

Imagine you have a Project in Oracle Policy Automation that includes an attribute of type Text, with a drop-down list to display values for the user.

  • What if there are multiple languages?
  • What if you use Screen-based Values?
  • What if you add Display Values as well as Values?
  • What if you migrate to Project Value Lists?
  • What editing might you have to do in your Translation file(s)?
  • What gets into the database?

List of ValuesAll these points will be covered in the video. Hopefully there will be no surprises in the video itself,  but it will be useful to see it in action and get confirmation of what you think might happen. And as mentioned previously, a big thanks to our OPA Hub Website Sponsors Mantis Solutions, makers of the OPA DB Connector, whose assistance made this video way easier to create and much faster to implement. If you are interested in Mantis OPA DB Connector, please reach out here.

 

Until the next post, I hope you are (at least those of you in the Northern Hemisphere) all having a pleasant Summer.

Temporal Reasoning in Oracle Policy Automation #3 : Time Travel

Temporal Reasoning in Oracle Policy Automation #3 : Time Travel

Following on from the previous parts of this series (which looked at the basics of Temporal Reasoning and Temporal Functions), this third post continues our investigation of temporal calculations in general, this time with a focus on another series of functions and concepts, that are closely involved in using temporal data to calculate numeric or currency amounts.

In the previous chapter of this series, we saw how the functions such as WhenLast() give us the capability to investigate the temporal data at our disposal and find out what was happening on a given date, according to the information you have.

How much would I have saved if?

Taking the example from the previous post and turning it upside-down, we can use Oracle Policy Automation to find out how much money would could save if we had been good and put money in our bank account. There are two principles here :

  1. We need to know how much money we are willing to save
  2. We need to know how regularly we are willing to put it in the bank account.

In real life, you might say to me:

“Richard, if I saved $1 a day, every day, since the beginning of the year : – how much money would I have now?”

In Oracle Policy Automation we can ask the same sort of question.  And of course, get the answer. The key points here are the daily sum, and the date range. In a sense, you are creating your own change points daily in order to calculate the result.

Again, it probably will not surprise you to know that there are a whole raft of Temporal Reasoning functions that work in similar ways to this one.  Suppose you admit to me, that you cannot save money on the weekend, because you like to go out and spend it instead.

“Richard, if I saved $1 a day every week day since the beginning of the year:- how much money would I have now?”

Your familiarity with Oracle Policy Automation probably helps you guess that the function IntervalDailySumIf exists, so you decide to use it, as in the example below.

At first glance, this looks alright. But it really isn’t. The problem is a common one when imagining Temporal Reasoning. The Boolean attribute “you are not spending the money instead” is not going to be very useful, since it is not a temporal value. You get to set it once in the Debugger – not for every weekend:

So mixing a Boolean and our temporal calculation produces a not very useful result. But thankfully Oracle Policy Automation can help. It includes a function to let us know if a day is a weekday or not, based on a range of dates. It returns a set of values that illustrate the changes. It is another example of a temporal reasoning function.

In the above case, the day is a weekday returns a set of change points showing you the way:

 

In the next episode of this series, we will look at the display of Temporal data to the end user, in a way that is easily readable.

Have fun

What’s New in Oracle Policy Automation 18B #2 Relationship Control Extensions

What’s New in Oracle Policy Automation 18B #2

The main thrust of this post first came into my head when I was writing one of the recent Back to Basics posts about Relationships. And as if by magic, Oracle Policy Automation went ahead and improved the product with something I felt was lacking. I should ruminate more often, perhaps they have telepathic powers over there. So in this post, What’s New in Oracle Policy Automation 18B #2, we are going to look at the new feature of the Control Extensions : the ability to customise the Relationship experience.

What’s New in Oracle Policy Automation 18B #2

The relationship above is a good example. In the course of a prototype, I designed the car and the passenger entities for a car-sharing enterprise. A car can have many potential passengers. For each journey, however, your passenger can only be in one car at a time. And yes, I understand that I could build a many-to-many and intersection the car and passengers or infer the current passengers or what have you, but this is just an example.

What’s New in Oracle Policy Automation 18B #2

So in the above example, you can see that I am in the process of selecting the passengers for each car. Putting aside the discussion about how best to model the data, there is a challenge here. The checkbox (which is the only display offered) is fine, but due to the lack of dynamism (?) in the display, the choices remain static. I mean by that you are able to choose an incoherent selection, with the same passenger being in multiple cars.

Of course, when you do so, the engine (correctly) gives you an error and you must correct your data entry. But what if we did it another way?

The core of this is the fact that now, in Oracle Policy Automation 18B, you can use the following in your Extensions:

control.getControlType() – which now will return “OneToMany” or “ManyToMany” and so forth for relationship controls. So your code could adapt the User Experience based on the cardinality.

control.getOptions() – returns an array of the different choices for the user ( the passengers in my case above). So you can retrieve the list of choices.

To help manage this kind of extension, control.getValue() returns an array of the selected values for your relationship (the instances that have been selected). So you can examine the selected values.

Let’s look at this code. It is, as always provided for educational and entertainment purposes (indeed, many will find my stream of consciousness code amusing). It is also available on the OPA Hub Website Shop page as a free PDF download. So let’s see What’s New in Oracle Policy Automation 18B #2 : Relationship Controls with an example.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
(c) 2018 Richard Napier The OPA Hub Website May 2018
Educational Example of Relationship Input Controls
I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xPassengerSelect") {
			return {
				mount: function (el) {
					//console.log("Control " + control.getProperty("name") + " is a " + control.getDataType() + ", originally a " + control.getControlType());
					var myValues = [];
					//Previous values
					myValues = control.getValue();
					var myOptions = control.getOptions();
					//console.log("Obtained list of instances for control " + control.id);
					var myDropDown = document.createElement('select');
					myDropDown.setAttribute('id', control.instance.toString());
					myDropDown.setAttribute('data-instance', control.instance.toString());
					myDropDown.setAttribute('data-entity', control.entity.toString());
					myDropDown.setAttribute('multiple', 'true');
					for (j = 0; j < myOptions.length; j++) {
						var myoption = new Option(myOptions[j].text, myOptions[j].value)
							myoption.setAttribute("data-instance", control.instance.toString());
						myoption.setAttribute("data-entity", control.entity.toString());
						myDropDown.options.add(myoption)
						//console.log("Added list option " + myOptions[j].text);
					}
					for (i = 0; i < myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected");
						}
 
					}
					$(myDropDown).change(function () {
 
						//New Values Selected
 
						for (i = 0; i < myDropDown.length; i++) {
							currentOption = myDropDown[i];
 
							if (currentOption.selected == true) {
								myValues.push(currentOption.value);
 
								//Disable All Values Matching Selected in other instances
								$("select [data-instance!='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("disabled", "true")
 
							} 
 
						}
					});
					var deselectbutton = document.createElement("button");
					deselectbutton.setAttribute("type", "button");
					deselectbutton.setAttribute('data-instance', control.instance.toString());
					var deselectbuttontext = document.createTextNode("Deselect All");
					deselectbutton.appendChild(deselectbuttontext);
 
					el.appendChild(myDropDown);
					$(myDropDown).after(deselectbutton);
 
					$(deselectbutton).click(
 
						function () {
						$("select [data-instance='" + this.getAttribute('data-instance') + "']").filter(":selected").prop("selected", false);
						control.setValue("");
							$("select [data-instance!='" + this.getAttribute('data-instance') + "']").attr("disabled", false);
					});
 
					for (i = 0; i < myDropDown.length; i++) {
						currentOption = myDropDown[i];
 
						if (myValues.indexOf(currentOption.value) != -1) {
							$("select [data-instance='" + myDropDown.getAttribute('data-instance') + "']").filter("option[value='" + currentOption.value + "']").attr("selected", "selected")
 
						}
 
					}
				},
				update: function (el) {},
				unmount: function (el) {}
			}
		}
	}
});

So what are we looking at. There are probably four key areas in this rough prototype.

Lines 18 to 27 build a multiple-select drop-down instead of the check-boxes. Using HTML 5 data attributes, each option and each drop-down (there will be  drop-downs, one for each of the car ) is tagged with the instance name and the entity name. This is useful if you intend to have a page with lots of entity-related things on it , and it was useful in the Entity Collect example from a few weeks ago as well.

Lines  29 to 33 look through the existing values of the Control (maybe the user has already been working on this page, and has now come back to it for further editing) and selects programatically all those values that were chosen previously. Otherwise when you click the Next button and then the Previous button, you will no longer “see” your selections even though they actually have been selected.

Lines 38 to 58 handle the Change event if the user selects other items in the multi-select, and ensures that the corresponding items are deactivated in the other drop-downs.

Lines 58 to 78 create the Deselect All button for each drop-down, which removes all the selected items both from the drop-down and from the underlying control values, and re-enables the values in the other drop-downs.

Once again, I state for the record that this was just a “stream of consciousness” which became a bare-bones prototype. There are lots of holes in the code, and lots of repetition because I just wrote it in a single shot. So you have been warned.

It does, however, demonstrate the new functionality, so our post title What’s New in Oracle Policy Automation 18B #2 is fulfilled. This is something you could not really do in previous versions.


Have fun!

Custom Entity Collect Extension in Oracle Policy Automation #2

Custom Entity Collect Extension in Oracle Policy Automation

In this second part of the series, we continue to investigate building a Custom Entity Collect Extension in Oracle Policy Automation, and complete the basic example of a working collector. The code is once again focused on pointing out big ideas, traps, suggestions and the details are left to you, dear readers. Everything you see here is free and you can use it anywhere but it is for educational and entertainment purposes only. The PDF version of the code is available in the OPA Hub Shop for free.

Building the User Interface

The next big chunk of code is all about continuing the work begun previously, specifically building the User Interface by adding input boxes and other User Interface elements to the page. We switch according to data type, and as before we add a number of valuable extra HTML attributes to our elements.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//GET KEY INFORMATION
									var theinstancename = myrecords[i][j].instance.toString();
									var theentityname = myrecords[i][j].entity.toString();
									var theattributename = myrecords[i][j]._source.config.attributeId;
 
									var myname = myrecords[i][j].id.toString();
 
									attrInput.setAttribute('id', myId);
									attrInput.setAttribute('data-entityname', theentityname);
									attrInput.setAttribute('data-instancename', theinstancename);
									attrInput.setAttribute('data-attributename', theattributename);
									attrInput.setAttribute('data-rownumber', j.toString());
									attrInput.setAttribute('name', myname);
 
									// CONVERT ATTRIBUTES OBJECT TO ARRAY
									var myAttributeObject = myrecords[i][j]._source.screen.clientState[theentityname];
									myAttributeObject = myAttributeObject[theinstancename];
									var myAttributeArray = $.map(myAttributeObject, function (value, index) {
											return [value];
										});
 
									//DISPLAY THE CORRECT VALUE IN THE INPUT BOX
 
									switch (myattributedatatype) {
									case "boolean":
										var response;
										switch (myAttributeArray[j].toString()) {
 
										case "true":
											response = true;
											break;
										default:
											response = false;
										}
										attrInput.checked = response;
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
 
										break;
 
									case "number":
										attrInput.setAttribute('value', Number(myAttributeArray[j]));
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
										break;
 
									case "text":
										attrInput.setAttribute('value', myAttributeArray[j].toString());
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
										break;
									case "date":
										if ($(attrInput).attr("data-datepicker") === 'true') {
											$(attrInput).datepicker();
											$(attrInput).datepicker("option", "dateFormat", "yy-mm-dd");
											$(attrInput).val( myAttributeArray[j]);
											rowdiv.appendChild(attrLabel);
											$(attrLabel).after(attrInput);
 
 
 
										}
										break;
 
									}

Whoa, easy there! So what is all of that about? The different kinds of data (Boolean, text, numbers, dates) need to be handled slightly differently, to display correctly.

Error Display

What happens if the Interview cannot continue (note that this example Entity Collect only handles errors on navigate, the default for Oracle Policy Automation Interviews) because of an issue? The user needs to know what they have done wrong, so they can correct it. Thankfully the errors are available to us (if they exist).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//HANDLE DATA ENTRY ERRORS AND ERROR DISPLAY
var myerrorobject = myrecords[i][j]._source.screen.errors[theentityname]
if (myerrorobject) {
var myerrorinstance = myerrorobject[theinstancename];
if (myerrorinstance) {
var myerrorattribute = myerrorinstance[theattributename]
if (myerrorattribute) {
var errorrow = document.createElement("div");
errorrow.id = "rowcontainer" + i.toString();
errorrow.setAttribute('data-entityname', theentityname);
errorrow.setAttribute('data-instancename', theinstancename);
errorrow.setAttribute('data-attributename', theattributename);
$("#errordiv").append(errorrow);
 
$(errorrow).append("Attribute : " + myerrorattribute.attributeId.toString() + " - " + myerrorattribute.message);
$("input[data-entityname='" + theentityname + "'][data-instancename='" + theinstancename + "'][data-attributename='" + theattributename + "']").css("border", "3px solid red");
}
}
}

In this section we build a small DIV for the errors, and add any errors that exist as rows within it. At the same time, the relevant attribute is highlighted with a red border.

Updating the User Interface

When the user makes changes, we need to handle them and ensure they are passed on. The last part of the code for today concentrates on handling each of the data types, and making sure the data is correctly passed to Oracle Policy Automation. This is quite tricky, and can necessitate quite a bit of review of the Investigate JSON to try and understand what it does not like, as the error in the Browser will most likely be a generic 500 error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
var inputtype = $(attrInput).attr("type");
var datepicker = $(attrInput).attr("data-datepicker")
 
switch (inputtype) {
case "checkbox":
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, this.checked, event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
break;
case "input":
 
if (datepicker === 'true') {
$(attrInput).change(function () {
var mydate = $(this).datepicker('getDate');
mydate = new Date(mydate);
var mydateinstance = $(this).attr("data-instancename");
var mydateattribute = $(this).attr("data-attributename");
var mydateentity = $(this).attr("data-entityname");
var myisodate = mydate.toString();
function formatDate(mydate) {
var d = new Date(mydate),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
 
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
 
return [year, month, day].join('-');
}
interview.setInputValue(mydateattribute, formatDate(mydate), mydateentity, mydateinstance);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
 
} else {
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, event.target.value.toString(), event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
 
}
 
break;
case "number":
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, Number(event.target.value), event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
break;
}
 
}

And so this pretty much leaves us with a row builder, and an error builder. But the final part of the code is very important, specifically the Delete Button to delete the row you don’t want any more.

Delete Rows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//ADD A DELETE ROW BUTTON  AFTER EACH ROW
								var deletebutton = document.createElement("button");
								deletebutton.setAttribute("type", "button");
								var deletebuttontext = document.createTextNode(control.getRemoveButtonText());
								deletebutton.appendChild(deletebuttontext);
								//SET UP THE CLICK EVENT OF THE DELETE BUTTON
								$(deletebutton).click(function () {
									var myliveinstances = control._source.instances.slice();
									// FIND THE ROW THAT CONTAINS THE DELETED INSTANCE
									var found = myliveinstances.indexOf(event.target.parentElement.getAttribute("data-instancename"));
									control.removeRow(found);
 
									drawrows();
								});
								rowdiv.appendChild(deletebutton);

Delete the Right Row

The delete row feature needs to find the row in the live set of instances (the _source.instances) using the HTML element that is the parent of the button. So if you click the Button, which is on the third row of the HTML User Interface, then using the instance name we can find the correct row and remove it. This is because the control.removeRow() uses the zero-indexed array in control._source.instances, not the user interface you are building. For example, if you have four instances on screen, then you delete one, the HTML will show that instance 1, instance 3 and instance 4 remain for example. But the Array members are now marked as rows 0,1 and 2.

The code closes out with the standard stuff :

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
update: function (el) {$("#errordiv").empty();	drawrows();},
				unmount: function (el) {
 
					if (control.getProperty("name") == "xEntity") {
 
						$("#entitycollector").remove();
					}
				}
			}
		}
	}
})
 
 

And so, what remains to be done? Well, of course, reorganize all that code written as a stream of consciousness!

But seriously, the obvious ones are

  • Ensure that when an instance is created, but the user has not yet entered any data, that the error checking is fired ( you can actually advance to the next page and come back to see the errors, because of the way the error object is handled only on the mount , not on the update.
  • Ensure that errors are removed from the page when they relate to an instance that was deleted by the user.
  • Ensure that the HTML building includes CSS class information to facilitate a new look
  • Build out date-time input and currency input and saving

But I’m sure you will find time for that. Have a nice day and enjoy building your own Custom Entity Collect Extension in Oracle Policy Automation!

We’ll leave you with a short video.

Oracle Policy Automation Embed Website in Interview End

Oracle Policy Automation Embed Website in Interview

Oracle Policy Automation Embed Website in Interview

This request comes up quite often, at least often enough that I feel the need to mention it today. The example we are going to use is to embed the OPA Hub Website in an Oracle Policy Automation Interview. In addition we are going to pass an attribute to the website so that it performs a search for us. So, let us start our tutorial “Oracle Policy Automation Embed Website in Interview”.

Now, I am sure many of you are old enough to have spent years trying to avoid IFRAME integrations in applications : Siebel, SAP, they all do it or have done it at some point in time, and they are awful for the most part – whether it be from an accessibility, SEO, browser restriction or other perspective. So here are our goals for this mission:

  • Don’t use an IFRAME
  • Add the Website in a way that does not destroy the look and feel of the Interview
  • The Website must actually function properly

The steps to create this Project are shown below. You should be aware (and not be surprised) that this will not work well in the built-in embedded Browser in Debug Mode, so run Debug mode using Ctrl+Debug or deploy the Project to see the final results.

Oracle Policy Automation Embed Website in Interview Pre-requisites:

A New Project called “Oracle Policy Automation Embed Website in Interview” or something shorter.

Create a global attribute with the text the subject with a name of subject.

Create a new Screen to ask what is the subject. I suggest a Drop-down list with the Values “Siebel Integration, JavaScript Extensions,Service Cloud”.

Create a second Screen to display the Website.

  1. Create a label, using the name  of  the subject to display the chosen subject.
  2. Place this inside a Container
  3. Make sure you add a Property for the Container, naming the Object.

By now the Screen should look like this:

Oracle Policy Automation Embed Website in Interview Design

Now we come to the code. This is quite simple,although we will also need some CSS to make it look right. Add a JavaScript file and a CSS file to your resources folder for this Project. The explanation is after this code, which is as always provided for educational and investigative purposes only:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * Richard Napier The OPA Hub Website April 2018
 * Educational Example of Custom Container with a Website inside
 * I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customContainer: function (control,interview) {
		if (control.getProperty("name") === "xWebsite") {
 
			return {
				mount: function (el) {
					var myDiv = document.createElement("div");
					myDiv.setAttribute("id", "mySpecialDIV");
					document.body.appendChild(myDiv);
					$("#mySpecialDIV").width(900);
					$("#mySpecialDIV").height(600);
					var mySubject = interview.getValue("subject");
					$("#mySpecialDIV").html('XXXXXX'+ mySubject + '">');
				},
				update: function (el) {},
				unmount: function (el) {
					var myDiv = $("#mySpecialDIV");
					myDiv.remove();
 
				}
 
			}
		}
	}
});

Oracle Policy Automation Embed Website in Interview Code

In the code above, here are the salient points.

Lines 13 to 17 create a DIV and insert it into DOM, appending it to the body of the document.

Line 18 retrieves the value selected by the user on the previous page that is present in the Container as a label.

Line 19 is the most important one. Notice the “XXXXX”. Replace this with the website and any URL construct you need. For example, replace it with the following:

<object data="https://theopahub.com/main/?s=

The code viewer didn’t correctly display that part. Insert it exactly as shown, so that you are concatenating the URL with the user selected subject. The key point here is the use of the object tag rather than an nasty IFRAME. Thanks to Stackoverflow!

The rest of the code just tidies up when the unmount happens.

Oracle Policy Automation Embed Website in Interview CSS

The CSS is quite important here, to ensure that the embedding is seamless. Add this CSS code to your CSS file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
object {
    height: 100%;
    width: 100%;
}
#mySpecialDIV {
	float: left;
    margin: 0px;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	background-color: #404040;
}
html
{
    border: 0px;
    margin: 0px;
    overflow: hidden;
    padding: 0px;
}
body
{
    border: 0px;
    margin: 0px;
    overflow: hidden;
    padding: 0px;
}

Let’s take a look at the CSS. We use styling to position the DIV, as well as styling to ensure the object tag uses all of the available DIV. Finally we use some tricks to eliminate overflowing content and remove the horizontal scrollbar.

Oracle Policy Automation Embed Website in Interview Debugging

As mentioned earlier, this may be best tested in the Browser, not in the Debug Embedded Browser, so make sure you start with Ctrl+Debug.

The first screen will be straightforward:

Oracle Policy Automation Embed Website in Interview 1

The second screen will display and if your Internet connection is slow, you may have time to witness the two stages of display:

Stage 1 : Show the styled DIV that has been added to the Screen. Of course you don’t have to use this colour, I just wanted to use it for positioning and effect.

Oracle Policy Automation Embed Website in Interview DIV

Stage 2 : The embedded Website is displayed. The embedding is seamless (nice colour scheme!).

Oracle Policy Automation Embed Website in Interview End

  1. Notice that the attribute value has been passed to the OPA Hub Website and a search has been performed for you. The site is fully functional and can be accessed from the Interview Window.

Have a nice day! (The PDF is in the OPA Hub Shop).

JavaScript Extensions with a Live Entity-based Chart in Oracle Policy Modelling

JavaScript Extensions with a Live Entity-based Chart in Oracle Policy Modelling

One of the most interesting questions I have been asked during my current assignment in beautiful Madrid has been the following :

“How can I make a Chart”

Well, that’s easy I said : pick your Charting platform (for example, you might choose D3 as the charting library as it is well-known and incredibly powerful. Or alternatively you could manipulate SVG arcs and lines yourself if you want to, to achieve the same thing.

“How can I make a Chart based on Oracle Policy Automation data”

Well, that’s easy I said : you even have an example in the Oracle Policy Automation Example Projects, called the Loan Advisor. You can see a screenshot from that project, right here:

JavaScript Extensions with a Live Entity-based Chart : Intro

Digging deeper into that Project, we discover that the attributes that are used to create the chart are global :

JavaScript Extensions with a Live Entity-based Chart : Intro 2

“How can I make a Chart that uses Entity data”

Well that’s easy I said, you could hook up the D3 library to the entity, and use a similar system to our custom Entity Container example to retrieve the data. After all, the Pie Chart in D3  accepts any array of data organized into labels and values. You may remember in that example, we sought the name of the entity using EntityId and then iterated through the instances in the Entity to display them.

But upon investigation this is not really satisfactory. Adding an instance to the entity container does not refresh the Chart. In fact, you have to navigate forward and then backwards to get the Chart to refresh. That’s because, of course, your new “instance” does not actually exist yet. It does not get added into the entity.instances[i] list until you leave the current screen.

“How Can I make JavaScript Extensions with a Live Entity-based Chart in Oracle Policy Modelling”

You will have guessed by now that my entourage here is pretty demanding! So here goes. Firstly, the scenario. I have created an Entity called the payment. It has two attributes, the identifier, a text attribute, and the payment amount, a currency or number as you wish.

The goal : on ONE Screen, enter data and view a live chart that updates live, without changing Screens, as data is added or removed.

To experiment further with this, I also decided to create another Entity called the shadow payment. This is a copy of the original, created by the simple rule in Word that follows:

JavaScript Extensions with a Live Entity-based Chart Intro 3

The idea was to test if it would work both on inferred and normal entity instances. It seemed to, so you could probably use the code with either. To enable my shadow entities, I set up the relationship for the above Word rules to function properly.

JavaScript Extensions with a Live Entity-based Chart in Oracle Policy Modelling Intro 5

The Code Concept

Now we come to the code itself. This is, as I always state clearly, just code that I have hacked together to see if a concept had the ability to be taken further. It is in no way production or even unit test ready. That’s your problem. But I hope you find it interesting and inspiring.

Another note, I have seen that this “code view” messes with some characters. The OPA Hub Shop has a PDF version which you can use to compare and correct anything that looks wrong, notably the > and < characters don’t show up correctly here.

The code uses D3 for the pie chart, and the explanation follows after the code. Pop D3 in a JS file in the resources folder, as well as the D3 library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
 * Richard Napier The OPA Hub Website April 2018
 * Educational Example of Custom D3 Chart Extension with live refresh on a screen
 * I will remember this is for demonstration and educational purposes only
 */
 
OraclePolicyAutomation.AddExtension({
	customContainer: function (control) {
		if (control.getProperty("name") === "xChart") {
 
			return {
				mount: function (el) {
 
				},
				update: function (el) {
 
					if (document.readyState == "complete") {
 
						var entity = control._source.screen.serverState.shadowpayment;
						var myFlatList = [];
						var myObject;
 
						var width = 300, //width
						height = 300, //height
						radius = 150, //radius
 
						color = d3.scaleOrdinal(d3.schemeCategory10);
						var size = Object.keys(entity).length;
 
						for (i = 1; i &lt; size+1; i++) {
							myObject = new Object();
							myObject.label =control._source.screen.serverState.shadowpayment["@_@opa-rel-target={payment[the payment" + i + "]}/global[global]"].shadow_payment;
							myObject.value = control._source.screen.serverState.shadowpayment["@_@opa-rel-target={payment[the payment" + i + "]}/global[global]"].shadow_amount;
							myFlatList.push(myObject);
							//console.log(" Flattened the list - item " + i);
						}
						data = myFlatList;
						var vis = d3.select(el);
						vis.select("svg").remove();
						var vis = d3.select(el)
						.append("svg")
							.data([data])
							.attr("width", width)
							.attr("height", height)
							.append("g")
							.attr('transform', 'translate(' + (width / 2) +
								',' + (height / 2) + ')'); 
						var arc = d3.arc().outerRadius(radius)
							.innerRadius(0); ;
						var pie = d3.pie()
							.value(function (d) {
								return d.value;
							});
						var arcs = vis.selectAll("g.slice")
							.data(pie)
							.enter()
							.append("svg:g")
							.attr("class", "slice");
						arcs.append("svg:path")
						.attr("fill", function (d, i) {
							return color(i);
						})
						.attr("d", arc);
						arcs.append("svg:text")
						.attr("transform", function (d) {
							d.innerRadius = 0;
							d.outerRadius = radius;
							return "translate(" + arc.centroid(d) + ")";
						})
						.attr("text-anchor", "middle")
						.text(function (d, i) {
							return data[i].label;
						});
					}
				}
			}
		}
	}
});

Review of JavaScript Extensions with a Live Entity-based Chart

Line 8 : This is a Custom Container. So make sure that you drop a container into your Screen, and in the container make sure you add your Entity. In my example, I displayed both the original the payment entity, for the user to add or delete records, as well as the shadow payment which I leveraged to draw the pie chart.

Line 19 ; This example uses control._source.screen.serverState.shadowpayment. This JavaScript object contains the instances of your entity, and is updated as new instances are added, before you leave the page. Of course the name is the technical name  of your entity so don’t forget to add that to your Data tab.

Line 27 : Selecting a standard set of colors from the D3 color categories

Line 28: Finding how many objects are inside the control._source.screen.serverState.shadowpayment object. Each instance is a child object.

Lines 32 and 33 : Creating dynamically the identifiers of each row to select the label and the value using the names of the attributes in your entity, and copying them into a flat object with values and labels

Line 37 : Set the flat list as the data source for the Pie Chart

Line 40 : Add the Chart into the Container

Line 41 : Add the pie chart, setting the origin to the center of the Container, and hooking up to the data we created

Line 50 and beyond : Using D3, draw the arcs and fills that make the Pie Chart by going through the total set of data and dividing the pie into the right number of pieces.

This is the result, in full Hollywood glory, of JavaScript Extensions with a Live Entity-based Chart in Oracle Policy Modelling.

The PDF version is on the OPA Hub Shop, just search for the Pie Chart example.

We will of course be revisiting this to investigate making it more robust, but it’s a good starting point. Have fun and see you soon!

Custom Entity Container with JavaScript Extensions Revisited

Custom Entity Container with JavaScript Extensions Revisited

Assiduous readers will recall that we followed a series of adventures in Entity Container extension some time ago, from a basic tool that worked only in Debug Mode to a more interesting and robust concept that worked once deployed. For reference those Custom Entity Container with JavaScript Extensions articles can be found in the following links

So why come back to this example? For several reasons it seems appropriate to talk again about Custom Entity Container with JavaScript Extensions. Firstly, it is something that is often coming up in classes or on customer sites. So, subjectively I want to talk about it. Secondly, it is a great way of learning the ins and outs of the JavaScript extensions in general.

Yesterday, I was mad

I noticed that the PDF generator I had used for the third (and most interesting and useful example) had pretty much destroyed part of the file : specifically a couple of lines were duplicated and others were truncated. So it is time to revisit this, if only to correct the errors (I have uploaded a more up-to-date file, so that some of the errors have gone).

So let’s set the scene first. We want to display some entity instances. These are generated in my case by an Excel Spreadsheet. They contain one entity, the insult and this entity has three attributes : an Id number, the text of the insult and an insult level – a numeric categorisation of the insult. The higher the number, the more severe the insult. The insults themselves come from Tintin, or more precisely Captain Haddock.

There are no conditions in this Excel file, so the instances are created. There are 240, so we need a good display of our instances. The default display is too long, with no useful scroll bar. We want to replace this with jsGrid, a lightweight jQuery grid. We want something that replaces the style on the left with the style on the right:

Custom Entity Container with JavaScript Extensions Revisited

We would like

  • A grid format using little space
  • A scroll bar
  • A pagination control

The visual elements will be provided by jsGrid, a lightweight JavaScript control. We are also going to set the bar a little higher than last time. We want to have a dynamic filter of the grid, so that the user can view what they want (and not always have the 240 instances on the grid).

Custom Entity Container with JavaScript Extensions Revisited 2

Note: we must tread very carefully here. We must not change the business logic in any way. We must separate the concerns and provide purely UX elements in our JavaScript extension. But given this is inferred data, I think a little filtering is fine, as long as the underlying relationship is not tampered with.

The code would be based on the standard template, so I will simply put it here, in all of it’s quickly-strung together glory, so that you can read it, learn about it, clean it and make it industrial. As I always like to make clear, anything I post here is strictly not-ready, big-picture, here’s-an-idea for you to look at and make your own. This Custom Entity Container with JavaScript Extensions example is available on the OPA Hub Shop for download, as usual. It is listed as example #3 of Custom Entity Container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* Richard Napier The OPA Hub Website April 2018
* Educational Example of Custom EntityContainer Extension
* I will remember this is for demonstration and educational purposes only
*/
OraclePolicyAutomation.AddExtension({
customEntityContainer: function (control, interview) {
//console.log("Get Array Reference");
if (control.getProperty("name") == "xEntity") {
var entities = interview._session.config.data;
var entityId = "entitypublicname";
var entity;
for (= 0; i &lt; entities.length; i++) {
entity = entities[i];
if (entity.entityId === entityId) {
break;
}
}
return {
mount: function (el) {
//console.log("Beginning customEntityContainer jsGrid");
var myDiv = document.createElement("div");
myDiv.setAttribute("id", "mySpecialDIV");
//console.log("Styled customEntityContainer");
el.appendChild(myDiv);
var myFlatList = [];
var myObject;
for (= 0; i &lt; entity.instances.length; i++) {
myObject = new Object();
myObject.insult = entity.instances[i].attributes[0].value.toString();
myObject.insult_text = entity.instances[i].attributes[1].value.toString();
myObject.insult_score = entity.instances[i].attributes[2].value.toString();
myFlatList.push(myObject);
//console.log(" Flattened the list - item " + i);
}
$("#mySpecialDIV").jsGrid({
width: "80%",
height: "400px",
sorting: true,
paging: true,
pagelndex: 1,
pageSize: 10,
pageButtonCount: 10,
data: myFlatList,
fields: [{
name: "insult",
type: "text",
width: 20,
title: "id"
}, {
name: "insult_text",
type: "text",
width: 150,
title: "text"
}, {
name: "insult_score",
type: "number",
width: 20,
title: "score"
}
],
controller: {
loadData: function (filter) {
return $.grep(myFlatList, function (item) {
return item.insult_score === filter.insult_score
})
}
}
});
//console.log("Finished customEntityContainer");
},
update: function (el) {
var myslidervalue = $("[role*='slider']").attr("aria-valuetext");
$("#mySpecialDIV").jsGrid("search", {
insult_score: myslidervalue
}).done(function () {
//console.log("filtering completed with slider value " + myslidervalue);
});
},
unmount: function (el) {
var myDiv = $("#mySpecialDIV");
myDiv.remove();
//console.log(" Removed the customEntityContainer ");
}
}
}
}
});

So now let’s look at the key elements (don’t forget to download and place jQuery and jsGrid files into your resources folder) :

Line 11 – this should be replaced with the name of your entity (not the text, but the name or XML tag as some call it). We are going to search amongst the entities until we find yours.

Lines 30 to 35 –  the code extracts your entity and pulls out three attributes from the entity. Note of course that these three attributes need to be placed in your Interview Screen, inside the Entity Container, for this data to be available. Essentially the extracted information is made into a JavaScript object, and the object added to an array.

Line 38 – this is the start of the jsGrid code.

Line 47 – this is the definition of the three columns of data in the table and how to display them.

Line 66 – this is the custom filter function which will hide any instances that do not have the selected score.

Line 77 – this is where we obtain the value of the slider and we refresh the table to only show those records using the filter function.

Thanks to the Madrid crew for their suggestions. In the next few days we will look at another Custom Entity Container with JavaScript Extensions example, this time with a dynamic chart using the same principle. Please note as usual that for best results when debugging, use Ctrl+F5 to debug in a decent browser.

Oracle Policy Automation and Siebel Innovation Pack 16 #6

Oracle Policy Automation and Siebel Innovation Pack 16 #6

Oracle Policy Automation and Siebel Innovation Pack 16The final post in this series looks at some of the “extras” that facilitate the integration of Oracle Policy Automation and Siebel Innovation Pack 16. By “extras” I mean other Web Services provided by Oracle Policy Automation, which will need to be taken into consideration when designing how these two applications can best work together but that are not directly related to the subject of getting the two applications to integrate using Applets, Integration Components, Workflow Processes and so on. Some of the content that follows is license-dependent, but should be of interest to any Oracle Policy Automation person.

Overview

Given that there are a number of different services to review, this post therefore is necessarily a mixture of many things. To summarise, there are

  • Administrative Services : The REST API of Oracle Policy Automation allows the creation of users of all the main types (integration users as well as normal ones) and also for the automation of deployment, and retrieval of associated information.
  • Execution Services : Assess, Interview and Answer (and the Server service, although it does not really need to be covered here).
  • Batch Execution Service : The REST API for Batch Execution allows for batched execution of goal determination

Together these are referred to as the Determinations API. The API is version specific in the sense that features are constantly being added (for example, integration user management is new to release 18A) so make sure you are using the correct WSDL file. For specific Oracle Policy Automation rulebases you can download the WSDL easily and that is shown in the videos below.

Assess Service

The Assess Web Service is probably the most famous service from a Siebel developer perspective, since it allows Siebel Enterprise to call Oracle Policy Automation and obtain an XML response (in the manner of a typical SOAP Web Service). It is often used therefore when no user interface is required.

The above video provides a short overview of how to derive the necessary information from Oracle Policy Automation and to use it in standard Web Service fashion. Developers should note that the post-processing of the Response will most likely occur in a Siebel Workflow Process or Script, in order to parse the response and deal with it.

As such, accessing an Oracle Policy Automation rulebase with Assess can be done very simply indeed. If the Oracle Policy Automation rulebase you are working with has a Connection in it (to Siebel or anything else) then you may also wish to use the Answer Service (see below).

Interview Service

The Interview Web Service was heavily used in the Oracle Policy Automation and Siebel Innovation Pack 15 integration, in order to mimic the behavior of the standard Interview using the Siebel Open UI framework. This Service is best suited to applications needed to provide the Interview User Interface in another technology (a Java application, a Silverlight Client, a Visual Studio application or whatever). It has a number of specifics and developers must manage session control, as the short video below illustrates.

Answer Service

The Answer service is reserved for Projects where there is a Connection object in Oracle Policy Automation, and as such provides a SOAP-based tool to pass data sets to the Project and receive the response. Amongst other things, therefore, it can be used to test the behaviour of an Oracle Policy Automation project when the external application (for example Siebel Enterprise) is not available.

REST API Services

As outlined above, there are in fact two REST API areas of interest : the administrative platform and the Batch Assessment service. Both require OAuth2 authentication and session management.

What’s Left to Do with Oracle Policy Automation and Siebel Innovation Pack 16?

So what is there still to do, for the Siebel Developer who has followed all the different posts and videos in this series? Well of course it is not possible to show everything, so here are the main points that you will now need to finish on your own : but most of them are entirely non-specific to Oracle Policy Automation and Siebel Innovation Pack 16.

There are of course many different things that you might want to do with Oracle Policy Automation and Siebel Innovation Pack 16, so at the OPA Hub Website we are always happy to hear from our readers with comments and questions : all you have to do is post at the bottom of the article. We obviously cannot run your project from here (but if you want us to, just get in touch!)  but you should feel free to contact us with questions, ideas for articles or anything else that is Oracle Policy Automation-related.

As Siebel Developers will know, Siebel Enterprise is now in version 17 and the next big thing, Siebel 18, is expected soon. The good news is that almost all of the steps shown here are completely identical in the newer version, since the changes are architectural rather than functional for the most part. If you come across anything completely different then, again, just let us know. We do plan on providing an update to this post series as and when the Siebel 18 is made generally available.

Finally

The OPA Hub hopes you all enjoyed the different posts in this series. For your bookmarks, here are the other posts in the series:

Oracle Policy Automation and Siebel Innovation Pack 16 #4

Oracle Policy Automation and Siebel Innovation Pack 16 #4

Welcome back to part four of our ongoing series about Oracle Policy Automation and Siebel Innovation Pack 16 . This post continues with the setup and testing that began three posts ago. For reference here are the links to the previous parts of the series:

Oracle Policy Automation and Siebel Innovation Pack 16 Load and SaveThis particular article continues working on the core data transfer operations, namely Load and Save. I also have a tendency to call the Save operation Submit, because it reminds me that not only must the request be submitted to Siebel to save any mapped out data, but a response needs to be sent back from Siebel to Oracle Policy Automation to, for example, display a message in Oracle Policy Automation confirming that the save was a success (or whatever).

This need for a two step approach (Save in Siebel and Respond to Oracle Policy Automation) means your Workflow Process is likely to have both typical Siebel Operations to update the database but also typical transformation and response creation like the previous operations.

The example Workflow Process for Save will require, therefore, quite a bit of work before it is fully functional. In the video I try to highlight this, but it is worthwhile mentioning the key issues again here:

  • You will need to extract any data from the hierarchy sent to your by Oracle Policy Automation
  • You might well need to use scripting if the hierarchy you receive has multiple entity instances (for example, the Oracle Policy Automation Project infers multiple vehicles and you want to save each of them in Siebel).
  • You will need to make sure that you create a Response that updates one of the input mapped, load after submit attributes to show it in the Interview.

In this video which follows on from the previous set of SOAP UI tests, build and troubleshoot your Save operation with Siebel CRM to check for errors. There are lots of places where you will need to put in a bit of work on the example Workflow Processes (since they do not actually save much at all) and more complex (and therefore more interesting) business requirements may require a Business Service approach, namely to iterate through multiple instances of data returned to Siebel.

Whilst the videos cannot give you all the details, they definitely will put you in the right direction!

Oracle Policy Automation and Siebel Innovation Pack 16 Load and Save Testing in Siebel

Remember you can find the White Paper and associated files  (at time of writing) at this Oracle Website location.

Next…

In the next part of this series, we look at two supplementary operations, GetCheckpoint and SetCheckpoint : whilst a Connection does not have to support these operations, if you plan on allowing users to stop and resume their interview before it is finished then you definitely need these operations. See you next time!

 

Oracle Policy Automation and Siebel Innovation Pack 16 #1

Oracle Policy Automation and Siebel Innovation Pack 16 #1

Oracle Policy Automation and Siebel Innovation Pack 16 : Tutorial Part OneFor some considerable time now, the good people at Oracle have made available a White Paper describing an alternative integration to Oracle Policy Automation and Siebel Innovation Pack 16 integration (as opposed to the Siebel Innovation Pack 15 approach involving a good deal of HTML and so forth, and not supporting some of the new screen layout features and dynamic elements of Oracle Policy Automation).

The white paper is clear enough on the concepts, and some of the screenshots are excellent 😉 but I am often asked about the details of the setup and implementation. In fact it is something I have to do quite often anyway. So I thought I would publish here some content that shows how Oracle Policy Automation and Siebel Innovation Pack 16 can work together.

This content is obviously a mixture of technical and functional, and by definition quite “Siebel-oriented” but I figured it would be of interest here as well, since we all might find ourselves in projects where the two behemoths meet. And I suppose that even someone who just wants to figure out how Oracle Policy Automation connects to “something” might find it interesting as well.

A word of warning : these videos were recorded “live” without editing – or at least without much editing – so there are “troubleshooting” sequences where I do something wrong and then go off and fix it : I figure that keeping that stuff in makes for a bit of “reality TV” so you can maybe gain time yourselves when you get into similar problems. Oracle Policy Automation and Siebel Innovation Pack 16 integration sometimes takes a bit of getting used to.

Finally, in case you were wondering, this is also the foundation for the Oracle Policy Automation and Siebel 16 Workshop that I run from time to time. So, to keep the post from becoming too long, I am going to publish this in several parts. The first part (this post) looks at the various options, the different functional scenarios and the technical approaches that we might encounter in Oracle Policy Automation and Siebel 16 environments. The next post will continue the process.

Welcome to the Videos

What will you need : an Introduction and some Prerequisites

Getting Oracle Policy Automation and Siebel 16 Connected : Part One – Design Time

Next…

In the next post in a couple of days, you will continue to learn about the Connection and test the first two operations using SOAP UI, before you move on to the core of the integration.