Copy field values between records on the same table

David Casper
Tera Guru

To start out, I've created a custom field, u_alias_for, on the cmdb_ci table, that is a reference to itself (cmdb_ci). The purpose of this is to handle the multiple acronyms and application/service name changes in the medical industry. 

Whenever someone chooses a CI that is an alias, on any form, it automatically updates to the actual CI via a client script.

What I would like to do is make sure the support_group field is the same between the alias record and the actual CI record which the alias points to. Whenever the support_group field is updated on the "parent" CI record I need that value to copy over to the alias record, IF there is an alias for the CI. 

Trying to come up with a script that does this and also a way that is most efficient. 

Thanks!

1 ACCEPTED SOLUTION

You did mark it correct, I just didn't see it in time!

You can do a background script or a fix script. I prefer fix scripts because it saves the code so you can refer back to it in the future if needed.

execute();

function execute() {

	var ci = new GlideRecord( 'cmdb_ci' );
	ci.addNotNullQuery( 'u_alias_for' ); // only get CIs that are an alias to another
	ci.query();

	while ( ci.next() ) {
		ci.support_group = ci.u_alias_for.support_group;
		ci.autoSysFields( false ); // on clean up scripts I usually don't like to update the 'updated' fields on the record... 
		ci.update();
	}

}

Give this a shot and let me know how it goes. 

 

View solution in original post

8 REPLIES 8

Zach Biewend1
Giga Expert

Hi David,

You'll want two business rules on cmdb_ci.

 

The first one is a before insert or update business rule when u_alias_for changes and u_alias_for is not empty.

current.support_group = current.u_alias_for.support_group;

This will keep the CI up-to-date any time it's u_alias_for field is changed. 

 

The second rule is an after update rule when support_group changes.

var ci = new GlideRecord( 'cmdb_ci' );
ci.addQuery( 'u_alias_for', current.sys_id.toString() );
ci.query();

while ( ci.next() ) {
	ci.support_group = current.support_group;
	//ci.autoSysFields( false );
	//ci.setWorkflow( false );
	ci.update();
}

/*

you can use autoSysFields so this update will not modify the system fields (sys_updated_on and sys_updated_by). 

you can use setWorkflow to not run business rules on those alias records. This makes your code run a little faster, but I would probably leave it commented so all business rules run. 

*/

 

And the last thing I would caution, if you're using the client to update the CI to be the parent rather than the alias, I would also include a business rule that makes the same update. That way if the CI gets modified in a list view or in some other code (a fix script for example) it will keep the data clean. 

Zach:

 

Thanks for the reply. Couple thoughts. First, what if i reversed your first script?

current.u_alias_for.support_group = current.support_group;

My thought is that we would have to have this run after and then the actual alias CI would be updated correctly and we wouldn't need anymore rules? 

If that was a crazy suggestion cut me a little slack haha. Scripting is not my strong suite. 😉

As for the users updating from lists, I have it locked down so that you have to be member of a specific role to make changes to the cmdb_ci table. This is to enforce that changes are reviewed and approved by config management. 

Hey David,

We can't reverse the first script because that one is running on the alias record (think of it as the child). There could be many child records to one parent. So that first record is looking for updates to the 'parent' field on the child record. So if it becomes associated to another 'parent' CI in the future, this rule will update its support group. 

The second rule is looking for updates to the parent CI, specifically when its support group changes. And since it's the parent in a one-to-many relationship, it could potentially have multiple child CIs. That's why we add the GlideRecord and the while loop to iterate through all the child records, not just one. 

 

And restricting updates to a smaller subset of users is a great first step. Personally I would still add a business rule to ensure no edits are made in the list. Or at least add a list_edit ACL to prevent edits in the list. I like to make my solutions as user proof as possible 🙂 

Zach:

 

That seems to done done it. I created the BRs in our DEV and tested it with a couple updates. Worked flawlessly. 

 

Thanks so much for your help on this. 🙂 Our go-live is Tuesday so this was invaluable!!!