Tag: Tutorial

AWS Accelerated A to Z Intelligent Advisor Install

AWS Accelerated A to Z Intelligent Advisor Install

The other day an esteemed reader of this humble blog asked me a question about installing Intelligent Advisor on Amazon Elastic Cloud. Of course I immediately sugested they try Oracle Cloud instead but the questions were valid and it soon struck me that this site has not, for a long time updated it’s installation posts and guides (notably the Create an OPA Self-Study Series). So I had a few minutes to spare while waiting for a train the other day and I sat down and recorded an example. To assist with the example, which is extremely edited to simply hightlight he key points, here are the things that I needed to install the entire stack for an Intelligent Advisor Install.

  1. I started with Windows 2012 R2 Server as the base image. Old, stable and easy to navigate
  2. I choose 100Gb for the disk size and Large for the image
  3. I downloaded WebLogic 12.2.1.3 Quick Installer
  4. I downloaded Oracle Database 12c database
  5. I downloaded JDK 8 261
  6. I downloaded the latest version of SQL Developer
  7. I downloaded the 20B release of Intelligent Advisor

The install routine is very well documented here online and you could pretty much follow that as-is. my own way of installing in this demonstration focuses at the end on the Data Source, which is often forgotten about during the install. Here are the stumblng blocks you might come across:

  1. Local Security Policy stopping IE from being launched so you cannot install Chrome.
  2. Local Server setup put IE in enhanced security mode which slows everything down.
  3. Microsoft Visual C++ Runtime Missing which stops SQL Developer running. (See the section entitled Note: the Windows EXE requires a MSVCR100.dll to run. Most computers will already have this file and in the Windows PATH. However, if the first copy of the file found by the EXE is a 32-bit copy of the DLL, then SQL Developer will fail to start. You can fix this by copying a 64-bit version of the DLL into the BIN directory or updating your OS PATH such that a 64 bit copy of the DLL is found first.).
  4. Creating the database user for the install with the correct permissions.
  5. Ensuring the Data Source in your WebLogic is targeting the database and can connect / the database name is correct and the data source is accessible from the WebLogic server you created
  6. Ensuring for this demonstration machine that Node Manager is not using a secure connection

As I state clearly in the beginning of this video, this is for demonstration purposes only, and it is entirely your responsibility to ensure that you have licenses, permission and authority to do any of this. Good luck with your Intelligent Advisor Install and do not hesitate to leave a comment if you run into issues.

Continuous Delivery – OPA and Postman, Newman and Jenkins #4

Continuous Development – OPA and Postman, Newman and Jenkins #4

In this part of our series, we will take our existing platform composed of Postman, Newman and Oracle Intelligent Advisor and plug it into Jenkins, to allow us to run lights-out tests according to a schedule, and to enable the testing team to receive emails when the tests have completed.

For reference, the other parts of this series are here : Part 1, Part 2, Part 3.  For the record, let’s be absolutely clear about one thing – this is not the only way to automate this process, and there are other tools and platforms that can do the same job. Heck, if you are lucky you will not even have to worry about this because some other team or department already has this thought through and all you have to do is deliver projects. But you might want to understand the mechanics of this process anyway, or if you are unlucky (or lucky, depending on your point of view)  then when the musical chairs are happening and you are the one left standing so you inherit responsibility for this, at least you will have a head start.

So, off to work. Many of you will know Jenkins, the stable, powerful open source automation platform that allows us to pretty much build, deploy or test anything. The biggest bonuses of Jenkins are that it is free to use, easy to install and that it comes with an incredibly large set of plugins, which extend the functionality to include lots of other things.

If you have installed Jenkins, which is about as easy as it can be, you should find yourself looking at the basic setup screen of Jenkins:

If you are pressed for time, just accept the suggested plugins first, and then return to the list of plugins later. You will need to add several, if they are not already present. The most important one is the Node.JS plugin, since we want to use Jenkins to communicate via Newman, and you will remember from the last post in this series that Newman runs on Node.js.

 

  1. Manage Jenkins, Plugin Manager
  2. Click Available to find more plugins
  3. Filter for nodejs
  4. Select the plugin
  5. Install without a restart or with a restart as you wish depending on whether you have more to install.

Other important plugins include potentially the Email Extension Plugin which you might find useful, and potentially lots of others. You will also need to make sure that you have installed any plugins you want to use with Newman, recall that in the last post in the series you added an HTML report generation to Newman. If you didn’t do that yet, you should do it now. There are a few other settings in Jenkins that you need to setup, notably the System Admin Email Address but most of it should be fairly straightforward and you will find out that you need it when Jenkins complains.

Now you need to tell Jenkins a little more about Newman. In the Global Tool Configuration of Jenkins, via the Manage Jenkins option, scroll down to the Node.js seection and ensure you have added the details about your Node.js installation, and that you want to use Newman with it.

Jenkins Setup NodeJS

  1. Add NodeJS
  2. Give it a name whatever you would like to see in the logs
  3. Install Automatically
  4. Choose the version that you installed (the installer would have told you that)
  5. Add this to ensure that Newman and the HTML Reporter you used with Newman are available

Save all of that and you are just about ready to use Jenkins for real.

Create a new Freestyle Project in Jenkins and give it whatever name you wish. Then in the Build Environment section, ensure that you signal the need for Node.js. In the Build Step, choose Execute Windows batch command (unless you are not running windows, in which case there is a non-Windows equivalent). Add, for example, the following command line to run Newman with Node.js and use the HTML reporter, with your data file from the previous post in this series. The file name ensures that this file is overwritten each time you run this project. If you don’t you will end up with lots of files, each using a timestamp as the name, which can get confusing.

Having set up our Jenkins Project, we are going to add a Post Build Action to ensure that your team (or just you) gets an email with the report from Newman. The screenshot below assumes you have added the Extended Email Plugin mentioned above. Note the items below the image.

Jenkins Post Build Step

  1. Without going into too much detail, the extended email plugin provides all sorts of options for creating email groups and deciding which email (there can be many templates) goes to which person.
  2. This is where you add the Newman HTML report. Note the syntax of the  attachment path is not maybe what you are used to.
  3. The Jenkins build log can also be included with the mail, and can be useful if you have added many build steps and want to see what they did.

At a minimum you might want to set up an email that is sent when there are failures:

You can click the advanced options and begin that process to set up who receives emails in different trigger circumstances.

Save your project. Now, as a final point, you may which to schedule these tests to run when you are not in the office. So you can add Build Triggers from the top of the Project Configuration and use CRON-style syntax to decide when this will run.

Jenkins Setup Build Triggers

Now all you have to do is save your Jenkins Project. Of course, if you don’t want to wait until midnight you can always Build Now. You will recall from the third part of this series that my data file had an iteration in it that was set up to cause the Postman test to fail, because the journey time was too long. So, sure enough, I get an email in my Inbox:

Jenkins Email 5

The HTML report is attached to my email, and I can view the details of the failure, which is indeed the iteration 3 from my data file:

So we are now in a position to test, in an automated fashion, our Web Service from Oracle Intelligent Advisor. Although the example given was using the REST assessor, Postman will happily let you run SOAP XML calls as well, so this would be applicable too. In the next part of the series we will look at using Jenkins to test our HTML-based Interview for the same project.

See you soon!

JavaScript Extension : customEntityRemoveButton

JavaScript Extension : customEntityRemoveButton

Once again I came across this question on another forum, so I answered there and decided to reproduce it here in more detail. As some of you are no doubt aware, there are a number of smaller extensions in respect of Entity Collects, that all the developer to manage the process of deleting, or adding instances without having to completely redesign the Entity Collect which is a heavier task by an order of magnitude. customEntityRemoveButton is a good example.

The question, very pertinent I must say, concerned the deletion of instances, and the fact that there is no confirmation dialog. You click the button and the suppression just happens, without a chance to say “oops, didn’t mean that one”. Enter the customEntityRemoveButton!

customEntityRemoveButton 1

  1. An Entity Collect
  2. The Delete Instance Button that will be customized with a customEntityRemoveButton extension

The extension in question is known as a customEntityRemoveButton, and it has a unique handler which you might not have come across. This handler is known as setInstance – and the job of this handler is to provide the instance identifier. So, for a scenario, if you create three instances, then obviously each button needs to know which instance it belongs to, so to speak. This handler fires first (even before the mount handler it seems) so that you can recover the identifier and then use it to ensure the right button does the right job.

The example scenario is that the user would love to have a confirmation dialog. And since I’m often accused to using too much jQuery, this one is in native JavaScript. It would look like this perhaps:

/*  Generated by the OPA Hub Website 07/04/2020 17:54
Educational Example of Custom Remove Instance Button Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
 let mycontext = "";
OraclePolicyAutomation.AddExtension({
	customEntityRemoveButton: function (control, interview) {
		if (control.getProperty("name") == "xRemoveButton") {
			return {
				mount: function (el) {
					var div_parent = document.createElement("div");
					div_parent.id = "xButton_parent";
					el.appendChild(div_parent);
					console.log("Button mounted");
					makebutton(mycontext,el,control);
				},
				setInstance: function (el) {
					console.log("Button set Instance for " + el.toString());
					mycontext = el;
				},
				update: function (el) {
					console.log("Button updated for " + el.innerText);

				},
				unmount: function (el) {
					if (control.getProperty("name") == "xRemoveButton" ) {
						console.log("Unmount");
					}
				}
			}
		}
	}
})

function makebutton(instance, mycontext,control) {

	var div = document.createElement("button");
	div.id = "xRemoveButton" + instance;
		div.innerHTML = "Remove Me " + instance;
	div.onclick = function () {
		var goahead = confirm("Are you Sure?");
		

		if(goahead === true) 
		{control.removeInstance(instance);return false;}
	
	else{
		alert("No delete");return false;
	}
			
	};
	mycontext.appendChild(div);

}

I repeat that this is just a quick demonstration that I pulled together from somewhere in my head. The documentation on line is very thin concerning this particular handler and indeed these extensions in general.

customEntityRemoveButton 2

In the screenshot above and below you can see the new improved custom Button!

customEntityRemoveButton 3

Users now relax safe in the hands of our sanity checking dialog box 🙂

If you are interested in the Zip Archive just leave a comment and I will share it. This was done in 20A.

Have a nice day!

Input Validation in an Input Extension – IBAN Validation

Input Validation in an Input Extension – IBAN Validation

A funny thing happened today – I came across a forum post that was talking about exactly what we had been describing to someone else the same day. Odd. These confinement measures play tricks with your mind. Anyway here is the scenario, it’s about input validation.

The customer needs to validate a banking account number in IBAN format in Oracle Policy Automation as part of an HTML Interview. What are the options for input validation?

There are several ways to handle this

  1. If you are just validating one country-origin IBAN numbers then you could certainly use Regular Expressions on your Input Text Attribute. A checksum rule would provide extra validation.
  2. Write a lot of Error or Warning Rules to achieve the same.
  3. But given there are many formats and many countries, if you need something bigger then you had better use some help!

There are standalone JavaScript libraries like this one, or you might use the jQuery Validator instead. It comes with IBAN validation as part of the additional methods supplied with it.  Since a lot of people are familiar with jQuery, and since Oracle Policy Modeling already uses it, we decided to opt for that solution for input validation.

We downloaded the validator and the additional files. we ensured that jQuery was accessible to the Project (in short, we clicked the Styles button in the Interview, then the Custom.. button and said OK before pasting the files in the folder). If this was a real-life case we would load the files in the correct order programmatically (jQuery, Validator, then additional stuff) but for this quick hack we renamed the files in alphabetical order to make sure they loaded like A, B and C.

We created an Input attribute, and named it something like this:

Input Validation - Create Attribute

Then we added it to the Screen and hooked up a custom property to make sure the code is executed for the IBAN element.

Input Validation Setup Screen

Then I fired up my trusty Code Generator and created a template Input Extension. I edited the Validate handler and this is the complete input extension. Of course this is the bare bones but it will do for a start :

//*  Generated by the OPA Hub Website 18/03/2020 08:06
Educational Example of Custom Input Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xIBAN") {
			return {
				mount: function (el) {
					console.log("Starting name:xIBAN customInput Mount");
					var div = document.createElement("input");
					div.id = "xIBAN";
					div.value = control.getValue();
					div.setAttribute("data-rule-iban", "true");
					el.appendChild(div);
					console.log("Ending name:xIBAN customInput Mount");
				},
				update: function (el) {
					console.log("Starting name:xIBAN customInput Update");
					console.log("Ending name:xIBANcustomInput Update");
				},
				validate: function (el) {
					console.log("Starting name:xIBAN customInput Validate");
					//errorplacement ensures the standard message is not visible
					var validator = $(".opa-interview").validate({
							errorPlacement: function (error, element) {
								return true;
							}
						});
					var returnvalue = validator.element("#xIBAN")
					if (returnvalue === true) {
						control.setValue(document.getElementById("xIBAN").value);
						return true;
					} else {
						return 'Your Message Here - THIS IS NOT A VALID IBAN'
					}
					console.log("Ending name:xIBAN customInput Validate");
				},
				unmount: function (el) {
					if (control.getProperty("name") == "xIBAN") {
						console.log("Starting name:xIBAN customInput UnMount");
						var xIBAN = document.getElementById("xIBAN");
						xIBAN.parentNode.removeChild(xIBAN);
						console.log("Ending name:xIBAN customInput UnMount");
					}
				}
			}
		}
	}
})



Input Validation

Input Extension – Summary

The basic idea is simple – when the Validate handler fires, pull the form and the input element and validate it as an IBAN number. If it passes, then there is no error message. Otherwise the validate fails and you can tell the user. You can have a more interesting message than this of course.

The Zip Archive is in the OPA Hub Shop. Have fun!

JavaScript Extensions for Oracle Policy Modeling

JavaScript Extensions for Oracle Policy Modeling

It’s almost ready. The perfect Christmas gift (yeah, right, in bizarro-world) or New Year workout kit. The new book is due out in a few weeks, and you have the chance to win a free copy ahead of everyone else by entering our prize Survey (30 seconds) right now.

The book comes with 50 examples. You get them as Zip Files as well when you buy the book. The book covers all the different types of JavaScript Extensions that are currently available, with examples of each of them (sometimes many different examples) using easily-understandable business scenarios as the starting point, and using example projects from Oracle Policy Modeling – so you don’t need to install a Hub, or do anything special – which let’s you get started straight away.

  • Label Extensions
  • Input Extensions
  • Search Extensions
  • Options Extensions
  • Entity Collect Extensions
  • Entity Container Extensions
  • Button Extensions
  • Event Extensions
  • Navigation, Header and Footer Extensions

The OPA Hub Website Community has also stepped up and I am delighted to say that 8 examples (with credits) came from readers of this website. I am very grateful to them and encourage all of you to submit your ideas and code snippets for the next version.

Hopefully this book will appeal to non-technical people too – I wrote it in the same style as the others (Getting Started with OPA, Getting Started with OSvC) and tried to make it as accessible as possible to everyone.

Here, in avant-premiere, is the cover. And no, I’m not sure what those things are either. But they sure look exotic and tasty. I wanted a parsnip on the cover but these were available and they look good. These are important questions that you worry about late at night. The publisher’s website has been updated, watch this space for the launch date!

 

JavaScript Extensions

Table Headers : Tabular Layout Trick

Table Headers : Tabular Layout Trick

Updated 18th March 2020

[Update Start

Thanks to assiduous reader Steven Robert (see the comments) who reached out and pointed out some annoying side effects and  a requirement, now I get to revisit this topic after a while away. As luck would have it, I was working on a similar situation to the one Steven describes, and I had not been timely in updating this post. Thanks to him and here is the updated version of the concept, with explanations.

  1. As the original post mentioned, and Steven pointed out, the selector used in the example is unreliable
  2. Steven proposed a new selector and solved that issue, making it multi-column as well

But the downside is the lack of display when the table is first instantiated. We need something capable of reacting before the think cycle kicks in.

In order to  achieve something like this, our “payload” needs to be part of the table that is displayed automatically. So the obvious candidate in this case is the label extension, since the first column is actually a label anyway. You could extend this concept to include other controls, but  it would require more heavy lifting as you would probably end up, if you were unlucky, building an entire Entity Container. We covered that in the JavaScript Extensions book and it isn’t usually a short effort. Anyway, we have a label so we are cool.

Our label extension has a mount key which fires when the label is displayed. So if the table is displayed, the label code will kick in. So we can be ready as soon as the table is ready. Secondly, we could in theory add several label columns and have custom headers for each of them (you could of course achieve that using non-JavaScript techniques).

Here is the walkthrough based on the previous Project (with the credit cards and visa cards which are derived as a subset of the credit cards).

  1. Add a label in the row in the table and add custom properties. It should display whatever attribute is appropriate.
  2. Generate a standard label extension and edit it a bit.
  3. Add the custom properties to trigger the code when the label is displayed.
  4. Add another label if you want (I ran out of originality but added a second one for demonstration purposes).
  5. Fire it up in the Debugger, and then in the Browser.

I didn’t go all the way to deployment but it looks like it could be elevated into a viable concept. Also, I wasn’t a very good citizen as I didn’t do any checking to avoid my code running every time the label is instantiated – I would most likely check to see if the header already had the text I wanted to avoid setting it again.

And finally, of course if you want the Project Zip just leave a note in the comments!

Here is a walkthrough video. Hope it makes sense!

Update End]

Original Post :

There is always much discussion when users first discover the Interview tab. Let’s be honest – not all of the comments are exactly positive. It all feels a bit, well, basic.

There are a number of things that catch you out at first (and indeed, later). So let’s take a moment to study tabular layouts and a common issue.

For this example I’m going to use the same project (Credit and Visa Cards) as the previous post, since that gives us two entities to work with.

Tabular Layout

Let’s consider that you want to display both entities using tabular layout. You create a Screen and set them both to tabular display. But let’s assume that you want to display the Visa Card with a couple of specifics. You want to include the provider of the credit card. So let’s set that up as a Value List and use an attribute on the Credit Card, and infer it on the Visa Card:

Table Headers Tabular Layout Trick 1So, with that now done, we want to display the Visa Card provider in the Entity Collect (as it is an inferred entity, we cannot use an Entity Collect). But we want to display it as a label as you can see in this screenshot (we added a name to the attribute as you saw in step one so we can reference it in our Screen:

Table Headers Tabular Layout Trick 2Notice how we added a label and used that to display the text of the provider? Using a label ensures three things

  1. It is read-only
  2. If the user is tabbing from input to input, the cursor will not get stuck in that field
  3. It doesn’t look like a read-only input, just a label (which is what we want).

But the downside is that the label does not have a table header in that column, since the Interview designer only adds those for Inputs:

Table Headers Tabular Layout Trick 4

I find it a shame that we cannot put table headers in this “tabular” column, since in HTML a table should have column headers. In fact if we take a moment to inspect this table in the browser, we note that annoying, there is a table header in the table:

Table Headers Tabular Layout Trick 5

So, we need to get that table header populated with our chosen text. But how shall we do it? We don’t want to create an Entity Container extension, since that would mean we have to do the whole thing from top to bottom. So we only want a little tiny change. We have a couple of choices.

  1. Create a Style Extension for the Entity Collect
  2. Create a Label Extension for stealth modification

Let’s try the first option, since it reveals some interesting facts about Styling Extensions. Firstly, get ready by doing the following; change the text associated with your entity in the Interview by double-clicking where the rectangle is, and entering whatever text you would like to display in the missing header.

Then add a compound Styling Extension to your Project. Tabular Containers allow for nested styling, like this:

OraclePolicyAutomation.AddExtension({
style: {
tabularContainer: function (control) {
if (control.getProperty("name") === "xContainer") {
style: {
headerRow:
YOUR STUFF GOES HERE

}
}
}

}
});

Notice the “headerRow” is a child of “tabularContainer”. And notice the line that says YOUR STUFF GOES HERE. Now for an interesting fact about Styling Extensions. They behave, to a reasonable degree, just like Control Extensions. They are really one and the same thing – the main difference of course is the handlers that are exposed in Control and Interview Extensions.

Drop jQuery into your resources folder, and then replace YOUR STUFF GOES HERE with the following line:

$("#opaCtl4th0").text(control.getCaption());

Of course, the jQuery selector may be different for you but it is easy to find the “header” I illustrated in the previous screenshots. Open your Project in a real Browser (Ctrl+F5) for debugging and take a look at the results:

Final Header Result

Our Styling Extension has added the text to the header, drawing it from the Interview Screen Entity Container definition, and we have it where we want it. Of course, you could style it as well.

But it goes to show that Styling Extensions are really not very different to Control Extensions!

Fun with Aliases and Strings #3

Fun with Aliases and Strings #3

In the previous parts of this article (1, 2) we’ve taken the time to look at an amusing string-based manipulation technique which has helped us create a long string from lots of strings. Of course, the main reason for the example was to showcase two of Oracle Policy Automation’s language features, namely logical loops and aliases.

In this final part we will look at some of the downsides and potential challenges relating to strings and logical loops, and a few other things besides.

  1. Inferring instances of an entity to impress your friends

This can go wrong of course. In the current example you must enter the instances manually either in the Debugger or in the Interview itself. But what if you decided to infer them, for example from an Excel spreadsheet. Regular readers will know that we’ve hacked and worked with Excel many times in the past, and it comes as no surprise to us that on a single instance of Oracle Policy Automation, with the instances inferred from an Excel spreadsheet, the following will occur regularly as soon as you get into the 150,200 instance range:

Aliases and Strings Error

Closely followed (of course) by the following in the Interview:

Aliases and Strings HTTP Error

Obviously there are lots of configuration changes we can make on WebLogic (if you have access to it) to ensure we are running the JVM with appropriate memory, in Production mode and so on. But hopefully the point is clear. Inferring instances (large volumes) can be costly in terms of performance / memory.

2) Entering lots of instances manually to impress your friends.

It is worthwhile remembering that logic loops have a 1000 iteration limit – if they cannot be stabilized by then, an error occurs. So assuming you add 1001 instances of the ticker tape manually using the Interview or the Debug, you would expect to hit the logical loop ceiling. Oracle Policy Automation gets out of the loop, just in case it goes on for ever and ever. The easiest way to test this is to use the Test Case format and try out your logical loop with zero to many iterations in order to verify that you are never going to have the scenario where there are more iterations than the limit.

999 InstancesAliases and Strings 999 Cases
1001 Instances
Aliases and Strings 1001 Cases

For the same reason, the warning about logical loops on the Rules Tab : if you do decide to hide it, will you remember it in 6 months time? Have you documented your tests somewhere?

Have fun!

Calendar Black Out Dates with Control Extensions

Calendar Black Out Dates with Control Extensions

The OPA Hub Website is always happy to hear from readers and learn about the things they are doing and trying to do. In this case, this article was inspired by our reader AF, from Adelaide. The question was; how can we implement a calendar control, to allow the users to select a date – but the calendar control must be able to black-out certain dates (public holidays, non-work days). It’s the sort of thing we probably can all relate to.

The Calendar control that Oracle Policy Automation uses is a very standard JavaScript dropdown, but there is little in the way of configuration in respect of the dates shown. We can style the calendar and we can offer two different ways to enter dates (either as the traditional calendar or the three-fields-in-a-row style that some applications use).

So it comes down to what can be done with an Extension. Regular reader will remember that we have spoken about calendar controls before, on the subject of Year-Only Selection. So that Extension will be the basis of this article.

Firstly, what are the tools we might need?

  • jQuery
  • JQuery UI, especially datepicker

The datepicker widget from jQuery supports a variety of user-related events, including one called BeforeShowDay, which is where we can come in a specify which days should not be clickable. They remain in the calendar display of course.

The basic concept therefore, for this demonstration is:

  1. The user can select a date from the control. Certain days are not available.
  2. The control must handle both adding a date when the date is not currently entered, as well as when the date is already entered and the user wants to correct it (for example, going back to a previous screen in the interview.
  3. The date must of course be saved to our chosen attribute.

As always this is without any warranty or guarantee of fitness for purpose. It’s a quick demonstration that you can then add to and correct yourselves.

 

/**
 * Richard Napier The OPA Hub Website March 2019
 * Educational Example of Custom Date Control Extension
 * I will remember this is for demonstration purposes only
 */
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xDate") {
			return {
				mount: function (el) {
					
					var myDatePicker = document.createElement('input');
					myDatePicker.setAttribute("id", "dateselect");
					var mySessionDate = interview.getValue("dt_session");
					

					el.appendChild(myDatePicker);
					

					$('#dateselect').datepicker({
						dateFormat: "yy-mm-dd",
						onSelect: function (dateText) {
							var RecoveredDate = dateText;
							
							interview.setInputValue("dt_circ", RecoveredDate);
							
						},
						beforeShowDay: function (date) {
							var array = ["2019-03-14", "2019-03-15", "2019-03-16"]
							var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
							
							return [array.indexOf(string) == -1]
						}
					});

					var mySelectedDate = "";

					if (interview.getValue("dt_circ") == null) {
					
						$('#dateselect').datepicker("setDate", mySessionDate);
						var RecoveredDate = mySessionDate;
						
						interview.setInputValue("dt_circ", RecoveredDate);
						

					} else {

						var myPreviouslySelectedDate = new
							Date(interview.getValue("dt_circ"));
						

						var myPreviouslySelectedDateAsDate = new
							Date(myPreviouslySelectedDate);
						
						var myDayPrefix = "";
						var myMonthPrefix = "";
						if (myPreviouslySelectedDateAsDate.getDate() < 10) {
							myDayPrefix = "0"
						}
						if (myPreviouslySelectedDateAsDate.getMonth() < 10) {
							myMonthPrefix = "0"
						}
						var myConvertedYear = myPreviouslySelectedDateAsDate.getFullYear();
						var myConvertedMonth = myPreviouslySelectedDateAsDate.getMonth() + 1;
						var myConvertedDay = myPreviouslySelectedDateAsDate.getDate();
						var myPreviouslySelectedDateOnly =
							myConvertedYear + "-" + myMonthPrefix + (myConvertedMonth) + "-" + myDayPrefix + myConvertedDay;
						

						mySelectedDate = myPreviouslySelectedDateOnly;

						
						$('#dateselect').datepicker("setDate", mySelectedDate);

						
						var RecoveredDate = $('#dateselect').datepicker("getDate");
						
						interview.setInputValue("dt_circ", new Date(RecoveredDate));
					}
				},
				update: function (el) {},
				unmount: function (el) {
					var RecoveredDate = $('#dateselect').datepicker("getDate");
					
					interview.setInputValue("dt_circ", new Date(RecoveredDate));
					
					var myPicker = $('#dateselect');
					myPicker.remove();
					

				}
			}
		}
	}
});

Calendar Black Out Dates with Control Extensions – About the Code

The first part of the Mount is basically setting up the jQuery datepicker to be able to hide some days. We also set the date format to the international YYYY-MM-DD that we all know. Of course a more sophisticated approach would check the region and apply the correct format.

Line 22 Sets up the Select Event and Line 29 the BeforeShowDay  Event.

We attempt to grab the value of our user-entered date (dt_circ) and place it in the date control. If that is unknown or null, then we will default to the current date.

When the user selects a valid date, we will of course copy it into the attribute again.
Finally, when the Unmount fires, we will clean up.

The End Result

 

In a later post we will look at using an entity to store the blackout dates. Stay tuned! For the time being the Project is in the OPA Hub Shop.

What is Happening Here – Date Function with Wrong Date

What is Happening Here – Date Function with Wrong Date

See if you can guess : What is Happening Here?

Below is a project written in Oracle Policy Automation 12 (this was actually in 12.18B but it has no bearing on the example). It has only one attribute : the date of the next visit. This is written as follows:

The date of the next visit= YearEnd (AddYears(the current date;1))

The date you are running the Debugger, the current date is November 19, 2018. The rule should perform a simple assignment, taking the current date, adding a year and then using that as the input for the YearEnd function. So :

YearEnd(November 19, 2019)

This should give the value of December 31 2019. Also, there are no other attributes in this project. There are no JavaScript extensions, no custom controls, no CSS or other additions. The project is being built using English language. The project does not have any translations, forms, or anything else inside it. But the Debugger  session of the Oracle Policy Automation Interview displays the following:

OPA 12 - What is Happening Here

The date is incorrectly showing 12/31/20. So what is happening here? Even more fun, the Data tab of the Debugger shows the following:

OPA 12 - What is Happening Here

The value is correct on the right, wrong on the left. So what has happened to the Oracle Policy Automation project in this example?

You are free to give the answer, if you know it, in the comments. I will come back in a couple of days and explain. And before you ask, yes, I can across this in the real world yesterday and it is not a bug, it did not require a Service Request, and somebody had done something. The behavior is entirely reproducible I would imagine in any language.

Sometimes you want to write about something (in my case, I wanted to look at Silent and Hidden settings) but life gets in the way. This was such an amusing thing (with hindsight) that I decided to write about it instead.

Enjoy this and hopefully you will immediately have spotted the possible culprit. You can peruse the documentation online here.

Guest Post : Time Based Reasoning Worked Example

Guest Post : Time Based Reasoning Worked Example

It’s with great pleasure that I introduce you to Evert Fernandes, CTO at Magia Consulting UK Ltd. A self-confessed OPA geek, Evert has stepped up and written this article about Time Based Reasoning (and hopefully some more ) for the OPA Hub Website. Thank you Evert and…over to you!

Time Based Reasoning (TBR) – also known as Temporal Reasoning – is one of those subjects that new OPA developers tend to struggle with. It’s a more advanced subject that – once mastered – can provide huge benefits to your project.

In this article I will try to explain what TBR is, present a use case and provide a walk-through on turning the use case into rules.

So, what exactly is Time Based Reasoning?

Time Based Reasoning allows the rule developer to create rules that include attributes which contain values that are subject to change over time.

It is able to conclude rules like:

  • What’s the amount of daily benefit the citizen was entitled to on June 26th, 2017?

Time Based Reasoning Worked Example

Let’s have a look at the following use case:

“How much benefit is the citizen entitled to between 01-01-2017 and 31-12-2017 (inclusive)”

The following rules apply:

  • If the person is not married, the daily allowance is $10. If the person is married the allowance is $14
  • The person can only claim benefit if the daily income is less than $200.

For the sake of simplicity, we will only look at a binary relationship status, married and single. The real world is more nuanced and complicated, but feel free to expand on this example. 😉

As you can see, the mix of variables already creates quite a complex and fluid situation, especially considering that any of the variables are subject to change over the period in question (01/01/2017 – 31-12-2017).

So, let’s start by looking at the first element and create some rules:

OPA 12 - Time Based Reasoning Worked Example 1

There are a number of things happening in these rules, let’s take a closer look.

First of all, a rule table has been created (ALT + Z) to determine the daily allowance amount based on marriage status, $14 when married and $10 when single. The single status is implied by the ‘otherwise’ conclusion, i.e. the person is single because the person is not married.

The second rule calculates the total allowance over the time period, starting on January 1st 2017 and ending on January 1st 2018. The reason the end date is January 1st 2018 and not December 31st 2017 is because the end date is not included, so we simply add a day.

The function is called IntervalDailySum and takes in three parameters:

  • The start date (inclusive) of the period over which the calculation needs to take place;
  • the end date (exclusive) of the period over which the calculation needs to take place;
  • the rule text of the attribute over which the total daily allowance over the period needs to be calculated.

In this example, we provide hard coded values for the start and end dates. In the real world, the start and end dates will most likely come from date attributes.

We now need to test the rules. In order to do this, we start the OPM debugger and head to the data tab:

OPA 12 - Time Based Reasoning Worked Example

As you can see, not a lot is happening here. Let’s give the citizen a marital status by setting the value of ‘The citizen is married’ to ‘True’.

OPA 12 - Time Based Reasoning Worked Example

So far, so good. We have a marital status and OPA is able to work out the total allowance (365 days x $14 = $5110).

Let’s now assume that the person was single at the start of 2017, got married on March 1st 2017 and was single again on September 1st 2017 (don’t worry, they’re still friends! 😉).

How do we enter that data? OPA provides a handy feature called ‘Change Points’ to handle this.

Let’s reset the value for the citizen marital status:

OPA 12 - Time Based Reasoning Worked Example

Click on ‘Change Points’:

OPA 12 - Time Based Reasoning Worked Example

What this allows us to do is to take the attribute and set different values for different slices of time.

You can use ‘Add’ to add a new change point. Once a new point is created, you can set the date and value at that point in time.

Let’s add two change points. One on March 1st 2017 with a value of True and the other on September 1st 2017 with a value of False. Use the Date picker below the change point list to pick the dates.

OPA 12 - Time Based Reasoning Worked Example

The eagle eyed among you may have spotted that I’ve set the value at the top to ‘False’.

What this is saying is:

  • Until March 1st 2017, the value is False.
  • Between March 1st 2017 (inclusive and August 31st 2017 (inclusive), the value is ‘True’.
  • From September 1st 2017 and after, the value is ‘False’.

So, click ‘OK’ and let’s inspect the effect of our handiwork in the debugger:

OPA 12 - Time Based Reasoning Worked Example

There’s a lot more information here and one of the first things you’ll notice is that the total allowance has changed from $5110 to $4386.

If we break down the individual periods, you will see why:

  • January 1st – February 28th = 59 days x $10 (Single rate) = $590.
  • March 1st – August 31st = 184 days x $14 (Married rate) = $2576.
  • September 1st – December 31st = 122 days x $10 = $1220.

$590 + $2576 + $1220 = $4386!

Have a play with different dates and change points and you will find OPA is very good at working this stuff out for you.

OPA also offers a way to visualize this data. Right click the ‘the daily allowance for the citizen’ attribute and select ‘Show in Temporal Visualization’:

OPA 12 - Time Based Reasoning Worked Example

A new tab will appear top left named ‘Temporal Visualization’. If you click it, you will see:

OPA 12 - Time Based Reasoning Worked Example

This visualization confirms that we start off with $10/day, changing to $14/day from March 1st and changing back to $10/day on September 1st.

Time to complicate things a little by adding another variable to the mix in the shape of the daily income.

Let’s assume that the citizen started 2017 with a daily income of $150. Then later in the year the income rose to $250 and later yet, the income dropped to $180.

In order to deal with this new variable, we will change the rule that calculates the daily allowance to include the daily income for the citizen:

OPA 12 - Time Based Reasoning Worked Example

Remember that OPA will evaluate top down, so first it will check to see if the person is married and whether the daily income is less than $200. If this is false, it will check to see if the income is less than $200 and finally, if the citizen is not married and the daily income is greater or equal to $200, the ‘otherwise’ clause will apply.

Make sure the updated rule validates by pressing the ‘Validate’ button.

Now let’s start a debug session and have a look at the outcomes.

Start your debug session and navigate to the ‘data’ tab.

Supply the exact same values as the first example, making sure to set up the change points correctly.

Fun fact: Chances are that OPA still has your previous values in memory, saving you the need to re-enter them!

Check to see that you’re still getting the correct values.

You should see something like this:

OPA 12 - Time Based Reasoning Worked Example

Let’s set the value and change points for the daily income:

OPA 12 - Time Based Reasoning Worked Example

Click ‘OK’ and inspect the values in the data screen:

OPA 12 - Time Based Reasoning Worked Example

As you can see, the total allowance has now been set to $1926 (down from $4386).

We can have a look at what’s been happening in the Temporal Visualization tab.

Make sure the following attributes are shown by going to the debug data tab and right-clicking and selecting ‘Show in Temporal Visualization‘:

  • the daily income for the citizen
  • the citizen is married
  • the daily allowance for the citizen

Go to the ‘Temporal Visualization’ tab. You should see something like this:

OPA 12 - Time Based Reasoning Worked ExampleOPA 12 - Time Based Reasoning Worked Example

As you can see, there’s quite a bit going on here and the daily allowance for the citizen will vary based on marital status and income.

What you will hopefully be able to see is that, when it comes to dealing with changing circumstances, things can get quite complicated quite quickly. In the example we only dealt with two variables but throw in more variables and working out the right amounts would become very complex! Utilizing the out-of-the-box OPA temporal reasoning functionality allows you to manage the complexity of dealing with changing circumstances over time.

More information on Temporal Reasoning can be found in the OPA documentation:

https://documentation.custhelp.com/euf/assets/devdocs/cloud18c/PolicyAutomation/en/Default.htm#Guides/Policy_Modeling_User_Guide/Temporal_reasoning/Temporal_reasoning.htm

or in the Function Reference:

https://documentation.custhelp.com/euf/assets/devdocs/cloud18c/PolicyAutomation/en/Default.htm#Guides/Policy_Modeling_User_Guide/Work_with_rules/Function_references/FunctionReference.en-US.html

Finally for those who were wondering, the daily amount that the user is entitled to on June 26th is…

OPA 12 - Temporal Reasoning Worked Example

OPA 12 - Temporal Reasoning Worked Examplewhich is $14!

Thanks to Evert for his time and excellent article abut Time Based Reasoning. Readers who what to look at more Time Based Reasoning articles can search here.

Until the next time. If you want to write for the OPA Hub Website, reach out via our Contact Page.

Worldwide
Logo by Southpaw Projects LLC