Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

Parent-Child Relationship Implementation

Parent-Child Relationship-Sample
Implementation

Table of Contents

1. Purpose of the Document ..................................................................................................................... 1


2. Problem Statement ............................................................................................................................... 1
3. Use Cases .............................................................................................................................................. 2
4. Implementation .................................................................................................................................... 2
4.1 High-Level Steps .............................................................................................................................. 2
4.2 Detailed Steps ................................................................................................................................. 2
4.3 CPM Script for Incident Status Update ......................................................................................... 11
5. Appendix ............................................................................................................................................. 15

1. Purpose of the Document

The document outlines the need for the implementation of Parent-Child relationship and also the detailed
steps of its implementation using Custom Objects and other modules available in Oracle Service Cloud
product.

2. Problem Statement

In the current business requirements, there are cases when an object needs to be tied to one another in a
parent-child relationship, ie. An incident having many child incidents or an organization having multiple
child organizations, etc. In such cases, there should be a capability in the product to properly define the
parent-child relationship in an object. Also, the parent object might need to have a control on the other
child objects during any updates or for other workflows. Currently, there is no OOTB product functionality
available to have this business logic in place.

1
Parent-Child Relationship Implementation

3. Use Cases

1) To be able to associate an object with another using parent-child relationship


2) Considering the object to be an “Incident”, marking the Parent Incident as “Solved” should mark
all of its corresponding child incidents’ as “Solved” and send out emails to both parent contact
and child contacts respectively
3) The relationship could be many-many. A child can be mapped to multiple parents and vice-versa
4) Ability to identify an object as “Parent” and group the others as “Children”.
5) A report to display such objects having parent-child relationship

4. Implementation

The extensibility framework of the product enables one to have the parent-child relationship implemented
in the objects and also satisfy all of the above listed use cases. Given below are the high level steps and
detailed steps on how to implement the parent-child relationship in the product using the currently
available product capabilities. “Incident” object has been considered here to show this sample
implementation.

4.1 High-Level Steps


 Step 1: Create a System Attribute “ParentIncident” which will serve as the placeholder for Parent
Incident’s Reference Number in all the Incidents
 Step 2: Create an “All_Incidents” Report – one-stop shop to view all the incidents with details
 Step 3: Include “ParentIncident” field in the Incident workspace
 Step 4: Create a “ChildIncidentReport” to show the details of the child incidents for a given Parent
Incident
 Step 5: Include a tab in the Incident workspace to show the related incidents
 Step 6: Make Changes in the “Incident Multi-Edit” Workspace to include “ParentIncident” field
 Step 7: Edit Staff Profile to include the newly created workspaces
 Step 8: Create a CPM script to update the status of the child Incidents when the status of the
Parent Incident is set to “Solved”
 Step 9: Create a report to show the Parent-Child relationship

4.2 Detailed Steps

Step 1 : Create a System Attribute “ParentIncident” which will serve as the placeholder for
Parent Incident’s Reference Number in all the Incidents

1) Launch Configuration -> Database -> Object Designer


2) From the Ribbon in the “Home” tab, click on New -> System Attribute -> Incidents
3) Click on “Add New Field” and choose “Integer”
4) Under the Field Details, fill the following :
a. Name : ParentIncident
b. Package : CO (default package).
c. Note : The rest of the fields can have the default values

2
Parent-Child Relationship Implementation

5) From the Ribbon, click on “Relationships”


6) Click on “Add” against “Parents of Incident Object”
7) Select type as “Association”, Parent Object as “OracleServiceCloud.Incident” and Child Field as
“ParentIncident”. This is done in order to create a self-referential relationship

8) Click on “Save”
9) Click on “Deploy” to deploy the newly created system attribute
10) Once deployed, the System Attribute “ParentIncident” will now be created under “Incident” object

3
Parent-Child Relationship Implementation

Step 2 : Create an “All_Incidents” Report – one-stop shop to view all the incidents with details

This report can be created by having “Incident Search” Report as Reference. Follow the steps given
below –

1) Launch Analytics -> Report Explorer


2) Under “Public Reports”, go to Service -> Search Reports – Service
3) Right click on “Incidents” Report and click on “Copy”
4) Give the report a name. (let’s say “All_Incidents”) and click on “Ok”
5) The report by default gets created under the “My Reports” folder.
6) Go to “My Reports”
7) Right click on “All_Incidents” and click on “Edit”
8) The report will open in the “Design View” by default for editing
9) Under “Data Dictionary”, select the columns that you want to add to the report from the “Current
Dataset” or from “All Tables”. The existing columns can be removed by right clicking on the
column and selecting “Delete Column”
Since both parent and child incidents have to be reported, an outer join needs to be performed to
pull all the incidents.
10) From the “Home” tab, click on “Tables”
11) In the “Data Set” window that is opened, select the “right arrow” next to “incidents” table and
select “Join to -> Incidents -> incidents.Co$ParentIncident = incidents_id”
12) Make sure that the join is “Outer Join” to display all the Incidents
13) Click on “OK”

4
Parent-Child Relationship Implementation

14) The join expression in #11 implies that “incidents” table refers to “All Incidents” and “incidents2”
table refers to “Parent Incidents”
15) Choose the columns as needed from both the tables and click on “Save”
16) In order to select the run-time selectable filters for the report, under Home tab, click on “Data Set
View” under “Views”
17) The list of available Filters and Columns for the report will get displayed
18) To add additional filters, click on any one of the available filter column and click on “Add” under
“Design”
19) Include the additional filters such as “Subject”,”Parent Incident Reference Num”, “Incident
Reference Num” for the report

20) Click on “Save and Close”


21) The report will look as shown below -

5
Parent-Child Relationship Implementation

Step 3 - Include “ParentIncident” field in the Incident workspace

1) Launch Application Appearance -> Workspaces


2) Under Standard, right click on “Incident” and click on “Copy”
3) Enter a name for the workspace ( for instance, IncidentCopy) and click on “Ok”
4) Open the “IncidentCopy” workspace
5) Under “Insert Field”, drag “ParentIncident” to the Summary panel
6) Select the workspace (A dotted line appears around the workspace).
7) Go to “Design” tab and set the “Summary Panel Height” under Options group to “0”. This setting
will adjust the panel size.
8) Select “ParentIncident” column
9) Under “Design” tab, click on “Search Report”
10) Choose “All_Incidents” Report under MyReports and click on OK.
11) Repeat the same by clicking on “Secondary Search Report”
12) Click on “Save&Close”. The changes will be saved to the workspace.

Step 4 - Create a “ChildIncidentReport” to show the details of the child incidents for a given
Parent Incident

1) Launch Analytics -> Reports Explorer


2) Under “Public Reports”, go to Common -> Views - Common –> Editor Reports – Custom Objects
3) Right click on “Incident by ParentIncident” and click on Copy
4) Give the report a name (for instance, ChildIncidentReport) and click on OK
5) Go to “My Reports”
6) Right click on “ChildIncidentReport” and click on “Edit”
7) The report will open in the “Design View” by default for editing
8) Under “Data Dictionary”, select the columns that you want to add to the report from the “Current
Dataset” or from “All Tables”. The existing columns can be removed by right clicking on the
column and selecting “Delete Column”
9) Once you have made the changes, click on “Save”

6
Parent-Child Relationship Implementation

Step 5 - Include a tab in the Incident workspace to show the related incidents

1) Launch Application Appearance -> Workspaces


2) Open the “IncidentCopy” workspace
3) Right click next to “Audit Log” tab and click on “Add tab”
4) When the new tab is under focus, go to “Home” tab and Edit the name for the tab under “Text”.
(say, Child Incidents)
5) The tab will be renamed to “ChildIncidents”
6) Under “Insert Control” tab, select “Incidents View” and drag it under the “Child Incidents” tab
7) Go to “Design tab” and select “Report”
8) Choose “ChildIncidentsReport” created in the previous step and click on OK
9) Now select “Search Report” next to “Report”
10) Choose “All_Incidents” Report and click on OK
11) Click on “Save & Close”

Step 6 - Make Changes in the “Incident Multi-Edit” Workspace to include “ParentIncident” field

1) Launch Application Appearance -> Workspaces


2) Under Standard, right click on “Incident Multi Edit” and click on “Copy”
3) Enter a name for the workspace ( for instance, Incident MultiEdit Copy) and click on “Ok”
4) Open the “Incident MultiEdit Copy” workspace
5) Under “Insert Field”, drag “ParentIncident” to the Summary panel
6) Select the workspace (A dotted line appears around the workspace).
7) Go to “Design” tab and set the “Summary Panel Height” under Options group to “0”. This setting
will adjust the panel size.
8) Select “ParentIncident” column
9) Under “Design” tab, click on “Search Report”
10) Choose “All_Incidents” Report under MyReports and click on OK.
11) Repeat the same by clicking on “Secondary Search Report”
12) Click on “Save&Close”. The changes will be saved to the workspace.

7
Parent-Child Relationship Implementation

Step 7 - Edit Staff Profile to include the newly created workspaces

1) Launch Configuration -> Staff Management -> Profiles


2) Open the profile for which the newly created workspaces need to be assigned
3) Select the “IncidentCopy” against “Incident” and “Incident MultiEdit Copy” against “Incident Multi-
Edit”
4) Click on “Save&Close”

8
Parent-Child Relationship Implementation

Step 8 - Create a CPM script to update the status of the child Incidents when the status of the
Parent Incident is set to “Solved”

1) Launch Configuration -> Site Configuration -> Process Designer


2) Upload the PHP Code File (CPM script) and select “Execute Asynchronously”
3) Click on “Save”
4) Test the code once. If the changes look good, click on “Save” and “Deploy”
5) To add the object event handler, under “Process Model by Object”, expand “OracleServiceCloud”
6) Click on “Incident”
7) Select the script under “Update”
8) Make sure that the “Can Suppress” check box is enabled
9) Click on “Save” and “Deploy”

9
Parent-Child Relationship Implementation

Step 9 - Create a report to show the Parent-Child relationship

1) Launch Analytics->Reports Explorer


2) Click on “New Report” and select “Grid Report”
3) Under the “Data Dictionary”, add the required columns from “All Tables” in the grid and create
necessary joins and save the report.
4) The complete report definition is shown below –

10
Parent-Child Relationship Implementation

All the changes are now made to the workspace. You can test the changes by creating new incidents,
mapping the incidents to a parent incident and updating the status of the Parent incident.

4.3 CPM Script for Incident Status Update

<?

/**
Declare the name of this Object Event Handler:
* CPMObjectEventHandler: parentchildupdate

Declare the package this Object Event Handler belongs to:


* Package: OracleServiceCloud

Declare the objects this Object Event Handler can handle:


* Objects: Incident

Declare the actions this Object Event Handler can handle:


* Actions: Update

Declare the Connect Common Object Model version this


Object Event Handler is bound to:
* Version: 1.3
*/

// An alias to use for the version of the Custom Process Model


// this script is binding to:
use \RightNow\CPM\v1 as RNCPM;

// An alias use for the version of Connect for PHP that


// this script is binding to:
use \RightNow\Connect\v1_3 as RNCPHP;

/**
* This class contains the implementation of the Object Event Handler.

11
Parent-Child Relationship Implementation

* It must be the same name as declared above in the


* CPMObjectEventHandler field in the header.
*/
class parentchildupdate implements RNCPM\ObjectEventHandler
{
/**
* The apply() method "applies" the effects of this handler
* for the given run_mode, action, object and cycle depth.
* Upon a successful return (no errors, uncaught exceptions, etc),
* a "commit" will be implicitly applied.
* @param[in] $run_mode may be one of:
* RNCPM\RunMode{Live,TestObject,TestHarness}
*
* @param[in] $action may be one of:
* RNCPM\Action{Create,Update,Destroy}
*
* @param[in][out] $object is the Connect for PHP object that was
* acted upon. If $action is Update or Destroy,
* then $object->prev *may* have the previous
* values/state of the object before $action was
* applied.
*
* @param[in] $n_cycles is the number of cycles encountered
* so far during this instance of $action upon
* $object.
*/
public static
function apply( $run_mode, $action, $object, $n_cycles )
{

if ( $object::getMetadata()->COM_type != 'Incident' && $action !=


"RNCPM\ActionUpdate")
return;
else
{
if($object->StatusWithType->Status->LookupName=='Solved')
{
#If Incident->Status is "Solved", retrieve all the Child
Incidents
$roql_result_set = RNCPHP\ROQL::query("SELECT Incident.ID ID,
Incident.PrimaryContact.ParentContact.ID CID FROM Incident WHERE
Incident.CustomFields.CO.ParentIncident.ID = ".$object->ID);

$parent_inc = RNCPHP\Incident::fetch($object->ID);

$parent_t_count = count($parent_inc->Threads);

while($roql_result = $roql_result_set->next())
{
while ($row = $roql_result->next())
{
$inc_tmp = RNCPHP\Incident::fetch($row[ID]);
$contact = RNCPHP\Contact::fetch($row[CID]);

$f_count = count($inc_tmp->Threads);
if($f_count == 0)
$inc_tmp->Threads= new RNCPHP\ThreadArray();

12
Parent-Child Relationship Implementation

#Update the child Incident Thread

$inc_tmp->Threads[$f_count] = new RNCPHP\Thread();


$inc_tmp->Threads[$f_count]->EntryType = new
RNCPHP\NamedIDOptList();
$inc_tmp->Threads[$f_count]->EntryType->LookupName =
'Staff Account';

#Check if the recent thread entry is from the agent.


If yes, add the entry in the Child Incident's thread
if($parent_t_count > 0 && $parent_inc->Threads[0]-
>EntryType->LookupName == 'Staff Account' && $parent_inc->Threads[0]-
>CreatedTime >= $parent_inc->UpdatedTime)
{
$inc_tmp->Threads[$f_count]->Text =
strip_tags($parent_inc->Threads[0]->Text);
}
#Else set it to default text.
else
{
$inc_tmp->Threads[$f_count]->Text = "Closing this
incident since Parent Incident Status is set to Solved";
}

#Update the Status of the Child Incident


if($inc_tmp->StatusWithType->Status->LookupName !=
'Solved')
{
$inc_tmp->StatusWithType->Status = new
RNCPHP\NamedIDOptList() ;
$inc_tmp->StatusWithType->Status->LookupName =
'Solved';

$inc_tmp->save();
}
}
}
}
}
$object->save( RNCPHP\RNObject::SuppressAll );
return;
}
}

/**
* This class contains the test harness for the Object Event Handler.
* It must be the same name as declared above but with "_TestHarness"
* added as a suffix on the name.
*/
class parentchildupdate_TestHarness implements
RNCPM\ObjectEventHandler_TestHarness
{

/**
* setup() gives one a chance to do any kind of setup necessary

13
Parent-Child Relationship Implementation

* for the test. The implementation can be empty, but it must exist.
*/
public static function setup()
{
return;
}

/**
* fetchObject() is invoked by the test harness to get the set
* of objects to test with for the given action and object type.
* @param[in] $action may be one of:
* RNCPM\Action{Create,Update,Destroy}
*
* @param[in] $object_type is the PHP class name of the
* Connect object type being tested.
*
* \returns the object or an array of objects to test with.
*/
public static function fetchObject( $action, $object_type)
{
static $test_objs = array();

// For this test, we'll invent what we need.


if ( isset( $test_objs[$object_type] ) )
{
$obj = $test_objs[$object_type];
} else
{
$obj = new $object_type;

$md = $object_type::getMetadata();

switch ( $md->COM_type )
{
case 'Incident':
$obj->Subject = 'Test Incident Subject';
$obj->PrimaryContact = RNCPHP\Contact::fetch(1);
break;
default:
throw new \Exception( "Unexpected type: $object_type" );
}

switch ( $action )
{
case RNCPM\ActionUpdate:
$verb = 'update';
break;
}
$test_objs[$object_type] = $obj;
echo( "Invented " . $object_type::getMetadata()->COM_type . " for
$verb\n" );

// Legacy external events, rules and Custom Processes are


// automatically disabled while in test harness mode.
// So, no need to specify SuppressAll here.
$obj->save();

14
Parent-Child Relationship Implementation

return( $obj );
}

/**
* validate() is invoked by the test harness to validate the
* expected effects of the given action upon the given object.
* Throw an exception or return false to indicate failure.
* @param[in] $action may be one of:
* RNCPM\Action{Create,Update,Destroy}
*
* @param[in] $object is the Connect for PHP object that was
* acted upon.
*
* \returns true if the test for $action, $object succeeded, or
* false otherwise.
* Throwing an exception is another way of communicating
* failure, and will display the exception text as a
* result of the test.
*/
public static function validate( $action, $object )
{
return true;
}

/**
* cleanup() gives one a chance to do any kind of post-test clean up
* that may be necessary.
* The implementation can be empty, but it must exist.
* Note that the test harness is integrated with the Connect API such
* that operations performed thru the Connect API are not committed,
* so there's no need to clean up after the test even if it has created,
* modified or destroyed objects via the Connect API.
*/
public static function cleanup()
{
return;
}

5. Appendix

-------

15

You might also like