Using UI action to update multiple child records
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-03-2019 01:24 PM
Hello everyone,
Thank you in advance for your interest and assistance! I am trying to create a UI action that will live on the project record that if clicked will update a custom field on it's associated cost plans. I am combing through existing UI actions for guidance, if anyone knows of any threads or has any suggestions on how I can best accomplish this I would be incredibly grateful.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-04-2019 11:22 AM
First of all you should use the value "1" instead of "Pending" if you set the value.
The second problem: it's important to write different code depend on "Client" is checked or not. If you create server side UI Action ("Client" is unckecked) then you should use current to access the data. If you create client side UI Action ("Client" is ckecked) then current is unavailable and you can use g_form to access the data.
The code, which you posted contains mix of usage current and g_form. This will never work. I suppose that you can fix the code verifying that ("Client" is unckecked), remove unneeded onclick: propose(); and fixing the code to for example
current.u_funding_approval_state = "1";
current.update();
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-04-2019 12:53 PM
Hello Olegki,
Thank you very much for pointing out the mix up. That was my issue entirely. Thank you very much for helping me figure out the UI action conundrum!
I do have one question regarding the BR script. Currently I am manually setting the one state, how much more complicated would it be to simply insure that whatever state was selected on the project level is reflected in the cost plan level? The Funding Approval state variable exists on both tables and is identical in value and label. Ideally I would like the BR to be able to keep them in sync. If this is not a good fit, is there a better way to do it?
(function executeRule(current, previous /*null when async*/) {
var gr = new GlideRecord("cost_plan");
gr.addQuery("task", current.sys_id);
gr.query();
while(gr.next()){
//gs.addErrorMessage('BR is executing');
gr.u_funding_approval_state = 2;
gr.update();
}
})(current, previous);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-04-2019 01:26 PM
I'm not sure that I correctly understand all your customization. Is seems that you extended Project table [pm_project] and Cost Plan table [cost_plan] with the field u_funding_approval_state. Cost Plan table has two fields, which simplifies reference to the corresponding Task (Project Task, Demand or Project): task Field reference the owner of the Cost Plan and top_task, which reference the top task in the hierarchy (it's Project or Demand).
You can create Business Rule, which run on Insert or Update of u_funding_approval_state field of Project table and, which search Cost Plans by top_task and set u_funding_approval_state of the cost plans to 2. The code of the corresponding BR on Project table could be the following
(function (current) {
var gr = new GlideRecord("cost_plan");
gr.addQuery("top_task", current.getUniqueValue()); // or String(current.sys_id)
gr.setValue("u_funding_approval_state", "2");
gr.updateMultiple();
})(current);
or
(function (current) {
var gr = new GlideRecord("cost_plan");
gr.addQuery("top_task", current.getUniqueValue()); // or String(current.sys_id)
gr.query();
while (gr.next()) {
gr.u_funding_approval_state = "2";
gr.update();
}
})(current);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-05-2019 09:21 AM
Hi Olegki,
I was wondering, can I set this to simply mirror the state since they are identical? For example something like this.
(function executeRule(current, previous /*null when async*/) {
var gr = new GlideRecord("cost_plan");
gr.addQuery("task", current.sys_id);
gr.query();
while(gr.next()){
gr.u_funding_approval_state = current.u_funding_approval_state;
gr.update();
}
The current.u_funding_approval_state is the value on the project record that we are executing off of.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-05-2019 09:48 AM
I can't answer exactly because I don't know the meaning of u_funding_approval_state and I don't know what you want to implement exactly.
A Project can contains Project Tasks, which can contains another Project task (subtasks) and so on. One can create Cost Plan on any level of the task hierarchy. On which cost plans you want to set u_funding_approval_state if u_funding_approval_state of the project will be changed. If you use
gr.addQuery("task", current.sys_id);
then you will find only cost plans directly related to the project. I used
gr.addQuery("top_task", current.getUniqueValue());
which is the same as gr.addQuery("top_task", current.sys_id).
Thus if you want to find all direct const plans of the project, without cost plans created on the child project tasks then you should use "task". If you want to find all cost plans of the project, then you should use "top_task".
Other differences in your last code and my code are not important. I don't know how good you know JavaScript. The best practice of JavaScript code is skipping of last parameters, which you not use in the function: so one should remove unneeded previous parameter. In the same way executeRule is local name, visible only inside of the function. You don't call it inside of the body of the function (to have recursive function). Thus you can and based on best practice you should remove the unneeded name. If you do like the usage of the name executeRule and to use previous parameter - you can use it without any side effects.