cancel
Showing results for 
Search instead for 
Did you mean: 

Appointment - Custom Object to taylor how Archer accounts for utilization

JeffConti
Contributor III

We track resource usage, allocation, and base availability by day. Archer was designed to do this by hour, and disabled the appointment application from being changed. The script I brutally composed (very new to JavaScript) bypasses the need for a scheduler to input a value into the hours box. The box and its field name are hidden upon opening the form. When an appointment is saved, the mouseover of the save button invokes the function to unhide the duration input box while setting that value to 0. This allows the record to be saved without receiving error that a required field was not populated.

 

Additional elements were added to this script but remarked out because I could not get the functions to work. 

 

Element IDs within the Appointment needing to be noted consist of the following:
Phase: master_DefaultContent_rts_s3030_f20450c
Appointment Start Date: master_DefaultContent_rts_s3030_f16683c
Appointment End Date: master_DefaultContent_rts_s3030_f16684c
Save Button: master_btnSave
Duration (Hours): loitem20386 ░░░░░░░░░░░░░░░ : master_DefaultContent_rts_s3030_f16685c
Name Field: loitem20390
Name Input Box: master_DefaultContent_rts_s3030_f16686c
DaysAutoCalc: master_DefaultContent_rts_s3030_f25076c (Created by me - calculates the working days then multiplies that by a Value List allocation of 25, 50, 75, or 100% through an Archer calc field)
HoursAutoCalc: master_DefaultContent_rts_s3030_f25074c (Created by me multiplies daysautocalc by 8)

Time Allocation Value List Combo Box: master_DefaultContent_rts_s3030_f25080c_ddl
Non-Audit Activity Combo Box: master_DefaultContent_rts_s3030_f20449c_ddl
Parent Combo Box Input: master_DefaultContent_rts_s3768_parentLevelComboBox_Input
Parent Lookup Result: master_DefaultContent_rts_s3768_parentLookup
Resource Combo Box Input: master_DefaultContent_rts_s3768_resourceLevelComboBox_Input
Resource Lookup Result: master_DefaultContent_rts_s3768_resourceLookup

 

The following is the current script used :

 

   <script>
    document.getElementById("loitem20386").style.display = "none"; //hide Duration (Hours)
    document.getElementById("master_DefaultContent_rts_s3030_f16685c").style.display = "none"; //Hide Input for Duration (Hours)
    document.getElementById("master_btnSave").onmouseover = function() {setDays()}; //invoke functions when saving

 

  function setDays() {
    var days = 0; //initializing variable to 0
    document.getElementById("master_DefaultContent_rts_s3030_f16685c").style.display = "block"; //reveal hours input
    document.getElementById("master_DefaultContent_rts_s3030_f16685c").value = days; //set hours to 0
    document.getElementById("master_DefaultContent_rts_s3030_f16685c").focus(); //focuses on hours field so record will save without error 
   }
   </script>

 

This was done after struggling and failing at what I really was trying to accomplish which was on saving the form, grab the start and end dates, calculate the number of working days (weekdays), multiply that by the allocation percentage, place the resulting value in a numeric field, multiply that by 8 and have that value placed in the Duration (Hours) field.

 

Also, and this is huge, I needed to get the phase value concatenate it with colon, and concatenate that with a space and concatenate that with the Parent field lookup value(indicating the audit name) and use that to populate the optional Name field.  I ended up just moving the Name field off of layout (because I couldn't get it to work), but need to put it back and populate it if I can get it done.  Oh, but if Non Audit Activity was chosen, then Name would be populated with that Value List selection.

 

My biggest problem.....  and don't laugh....  I could not for my life figure out how to extract the data from within a field on a form.  I even found a great JavaScript that would calculate the working days (week days) between two dates (to take the place of the calculated field).  

 

Alternatively, I figured...  If I could just get the form to save first...  and by save I mean element ID master_btnApply, then i could just use Archer's calculation engine and leverage the output to those assigned field where I have already calculated the days, hours, etc.  

 

pastedImage_19.png

1 ACCEPTED SOLUTION

Accepted Solutions

WOW!!!!  Just some minor tweaks and it is working great!  Serioulsy, it feels like I dropped off my stinky dirty script off at the cleaners and it comes back fresh and smelling good.  I cannot tell you all how much I appreciate your help and suggestions!  Here is the working script:

 

<script type="text/javascript">

Sys.Application.add_load(function() {
$("#loitem20386").hide(); //hide Duration (Hours)
$("#master_DefaultContent_rts_s3030_f16685c").hide(); //Hide Input for Duration (Hours)
$("#master_DefaultContent_rts_s3030_f16686c").hide(); //hide name input box
$("#loitem20390").hide(); //hide name field

$("#master_btnSave").mouseover(function() {setDays();
});//invoke functions when saving
});

function setDays() {
var days = 0; //initializing variable to 0
var start = $CM.getFieldValue(16683); //get start date value
var end = $CM.getFieldValue(16684); //get end date value
var allocation = $CM.getFieldValue(25080); //get allocation value list value
var phase = $CM.getFieldValue(20450); //get value of phase
var audit = $("#master_DefaultContent_rts_s3768_parentLookup").text(); //get value of apppointment detail

//set allocation numeric value
var pct;
switch (String(allocation)) {
case '161465:0':
pct = .25;
break;
case '161466:0':
pct = .50;
break;
case '161467:0':
pct = .75;
break;
case '161468:0':
pct = 1;
break;
case '161499:0':
pct = 0;
break;
}
//set phase value
var phasetext;
switch (String(phase)) {
case '155194:0':
phasetext = 'Planning: ';
break;
case '155195:0':
phasetext = 'Fieldwork: ';
break;
case '155197:0':
phasetext = 'Wrap Up: ';
break;
case '155196:0':
phasetext = 'Reporting: ';
break;
}
// Validate input
if (end < start)
abort();

// Calculate days between dates
var millisecondsPerDay = 86400 * 1000; // Day in milliseconds
start.setHours(0,0,0,1); // Start just after midnight
end.setHours(23,59,59,999); // End just before midnight
var diff = end - start; // Milliseconds between datetime objects
var days = Math.ceil(diff / millisecondsPerDay);

// Subtract two weekend days for every week in between
var weeks = Math.floor(days / 7);
days = days - (weeks * 2);

// Handle special cases
var start = start.getDay();
var end = end.getDay();

// Remove weekend not previously removed.
if (start - end > 0)
days = days - 2;

// Remove start day if span starts on Sunday but ends before Saturday
if (start == 0 && end != 6)
days = days - 1;

// Remove end day if span ends on Saturday but starts after Sunday
if (end == 6 && start != 0)
days = days - 1;

//return days;

var timehours = days * 8;
var dayscalc = days * pct;
var hourscalc = timehours * pct;
var nameslice = audit.slice(0, 24);
var ellipsis = '...';
var nameinput = nameslice.concat(ellipsis); //phasetext.concat(nameslice)

$("#master_DefaultContent_rts_s3030_f16685c").show(); //reveal hours input
$("#loitem20386").show(); //reveal Duration (Hours)
$("#master_DefaultContent_rts_s3030_f16685c").val(hourscalc); //set hours
$("#master_DefaultContent_rts_s3030_f16686c").show(); //show name input box
$("#loitem20390").show(); //reveal Name field
$("#master_DefaultContent_rts_s3030_f16686c").val(nameinput); //input phase and audit name
$("#master_DefaultContent_rts_s3030_f16686c").focus(); //focuses on nameinput field so record will save
$("#master_DefaultContent_rts_s3030_f16685c").focus(); //focuses on hours field so record will save
}

function abort(){
window.alert("Appointment end date cannot be less than the appointment start date. Please check and adjust the date values accordingly.");
}

</script>

View solution in original post

20 REPLIES 20

Ilya_Khen
Champion III

Jeff, I apologize, but do I get it correct that your main question is how to retrieve data from the Parent and Resource ValuesPopup CR fields?

 

Also, I would recommend to use JQuery pathing, instead of pure JS for accessing elements. Like, instead of:

document.getElementById("master_btnSave")

use

$("#master_btnSave")

but this is just a preference.

DimalZeqiri1
Contributor III

You can also do this through Archer Console Manager ($CM) on the custom object.

 

use $CM.getFieldValue() to get the dates.

 

Do the JS calculations within the custom object.

 

use $CM.setFieldValue() to set the Hours in the Duration field.

Ilya_Khen
Champion III

All in all, I suggest to dig into this forum, which has plenty of custom objects ready and explanations:

https://community.rsa.com/community/products/archer-grc/archer-customer-partner-community/custom-objects 

Ilya, I have and certainly will continue to dig.  This community really has some great content in it (some that I have already applied and put into place).  This last weekend was honestly my first dive into even needing a custom object and finding myself in a crash-course into JavaScript.  Fortunately, I have found JavaScript to be much like VBA.  I also am quite used to PowerShell, so picking up JavaScript and its specific requirements / syntax has been easier (but I think i still have a long way to go).  I am really impressed with the helpful nature of the community.

 

In response to your question, one of my questions in fact was how to retrieve data from the Parent and Resource ValuesPopup CR fields.  I will work to apply any and all suggestions and continue to search for applicable information already within the community.

Yeah, welcome to the Community world  

If you are proficient with VB script, have you tried to write VBScript in Custom Object? In the past VB script was also used in HTML, I wonder if that still works

 

AFAIK, MS do not support VBScript after IE10. Not sure about other browsers. Maybe by adding compatibility tag, VB can be used:

<meta http-equiv="x-ua-compatible" content="IE=10">

Still not a preferred way

Dimal, thank you for the suggestion.  I will work with this today and apply your advice.  

DavidPetty
Archer Employee
Archer Employee

Also, make sure that any code that references field data is inside of the following function

Sys.Application.add_load(function() {
     //Code here
});
The reason being is that sometime the custom object will fire before Archer has a chance to load the data for the fields.  This function will fire after the data is loaded.
In response to your question, one of my questions in fact was how to retrieve data from the Parent and Resource ValuesPopup CR fields.

This is a little tricky being JavaScript can only get what's displayed in the cross-reference grid.  If you need data that resides in the linked record you'll have to use the REST APIs to "dig" into that record and get the data out.

 Advisory Consultant - Archer, an RSA Business

DavidPetty
Archer Employee
Archer Employee

Also for the <script> tag, add the type attribute with the value of 'text/javascript', <script type="text/javascript">.  The reason being is that I've seen IE act weird (no not IE ) if the type attribute is missing.

 Advisory Consultant - Archer, an RSA Business

I'm having confusing on how to properly incorporate your advice on using

Sys.Application.add_load(function() {
     //Code here
});

I'll keep trying to encapsulate everything in that, but I am doing it wrong I think.