Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Only one primary contact for each company

Rajendar3
Tera Contributor

Only one primary contact for each table when ever we hit on new button to create a new vendor contact it should check the primary contact check box for existing records with the same vendor name("company" backend name) , If exists it should not allow us to make it true for other users it needs to be done in list layout and form layout.

find_real_file.png

find_real_file.png

 

find_real_file.png

Thanks in advance for your guidance.,

Rajendar.

@Ankur Bawiskar @Pradeep Sharma  @Aman Kumar @Jaspal Singh @Sandeep Dutta 

1 ACCEPTED SOLUTION

Markus Kraus
Kilo Sage

Please note @Ahmed Drar answers. If you still want to implement this, you will need the following artifacts:

  1. Script Include (implements the necessary lookup used by Business Rule and Client Script):
    Name: PrimaryContactCheckHelper
    Client callable: true
    Script:
    var PrimaryContactCheckHelper = Class.create();
    PrimaryContactCheckHelper.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
    	
    	getPrimaryContact: function (company) {
    		company = company || this.getParameter('company');
    		if (company) {
    			var contactGr = new GlideRecord('vm_vdr_contact');
    			contactGr.addQuery('company', company);
    			contactGr.addQuery('primary_contact', true);
    			contactGr.setLimit(1);
    			contactGr.query();
    			if (contactGr.next()) {
    				return JSON.stringify({
    					sys_id: contactGr.getUniqueValue(),
    					display_value: contactGr.getDisplayValue()
    				});
    			}
    		}
    		
    		return '';
    	},
    
        type: 'PrimaryContactCheckHelper'
    });​
  2. Business Rule (prevents List Edit and for generally enforcing the "only one primary contact" rule):
    Name: Only one primary contact
    Advanced: true
    Insert: true
    Update: true
    When: before (default)
    Filter Conditions: Vendor <is not empty> [AND] Primary contact <is> true
    Advanced > Script:
    (function executeRule(current, previous /*null when async*/) {
    
    	var helper = new PrimaryContactCheckHelper();
    	var contact = helper.getPrimaryContact(current.company);
    	if (contact) {
    		contact = JSON.parse(contact);
    		if (contact.sys_id != current.sys_id) {
    			gs.addErrorMessage('Only one primary contact is allowed. Current primary contact: ' + contact.display_value);
    			current.setAbortAction(true);
    		}
    	}
    
    })(current, previous);
  3. Client Script (will set the 'Primary contact' to readonly whenever required):
    Name: Check Primary Contact
    Table: vm_vdr_contact
    UI Type: All
    Type: onChange
    Field name: Vendor
    Script: 
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    	if (newValue === '') {
    		g_form.setReadOnly('primary_contact', false);
    		return;
    	}
    
    	var ga = new GlideAjax('PrimaryContactCheckHelper');
    	ga.addParam('sysparm_name', 'getPrimaryContact');
    	ga.addParam('company', newValue);
    	ga.getXMLAnswer(function (contact) {
    		if (contact) {
    			contact = JSON.parse(contact);
    			if (contact.sys_id != g_form.getUniqueValue()) {
    				if (!isLoading) {
    					// only show the message for changed values (the readonly-part is desired on the initial load!)
    					g_form.addInfoMessage('Only one primary contact per Vendor is allowed. Current primary contact: ' + contact.display_value);
    				}
    				
    				g_form.setValue('primary_contact', false);
    				g_form.setReadOnly('primary_contact', true);
    				return;
    			}
    		}
    
    		g_form.setReadOnly('primary_contact', false);
    	});
    }

     

Please let us know if this solution solved your problem.

View solution in original post

7 REPLIES 7

Markus Kraus
Kilo Sage

Please note @Ahmed Drar answers. If you still want to implement this, you will need the following artifacts:

  1. Script Include (implements the necessary lookup used by Business Rule and Client Script):
    Name: PrimaryContactCheckHelper
    Client callable: true
    Script:
    var PrimaryContactCheckHelper = Class.create();
    PrimaryContactCheckHelper.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
    	
    	getPrimaryContact: function (company) {
    		company = company || this.getParameter('company');
    		if (company) {
    			var contactGr = new GlideRecord('vm_vdr_contact');
    			contactGr.addQuery('company', company);
    			contactGr.addQuery('primary_contact', true);
    			contactGr.setLimit(1);
    			contactGr.query();
    			if (contactGr.next()) {
    				return JSON.stringify({
    					sys_id: contactGr.getUniqueValue(),
    					display_value: contactGr.getDisplayValue()
    				});
    			}
    		}
    		
    		return '';
    	},
    
        type: 'PrimaryContactCheckHelper'
    });​
  2. Business Rule (prevents List Edit and for generally enforcing the "only one primary contact" rule):
    Name: Only one primary contact
    Advanced: true
    Insert: true
    Update: true
    When: before (default)
    Filter Conditions: Vendor <is not empty> [AND] Primary contact <is> true
    Advanced > Script:
    (function executeRule(current, previous /*null when async*/) {
    
    	var helper = new PrimaryContactCheckHelper();
    	var contact = helper.getPrimaryContact(current.company);
    	if (contact) {
    		contact = JSON.parse(contact);
    		if (contact.sys_id != current.sys_id) {
    			gs.addErrorMessage('Only one primary contact is allowed. Current primary contact: ' + contact.display_value);
    			current.setAbortAction(true);
    		}
    	}
    
    })(current, previous);
  3. Client Script (will set the 'Primary contact' to readonly whenever required):
    Name: Check Primary Contact
    Table: vm_vdr_contact
    UI Type: All
    Type: onChange
    Field name: Vendor
    Script: 
    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    	if (newValue === '') {
    		g_form.setReadOnly('primary_contact', false);
    		return;
    	}
    
    	var ga = new GlideAjax('PrimaryContactCheckHelper');
    	ga.addParam('sysparm_name', 'getPrimaryContact');
    	ga.addParam('company', newValue);
    	ga.getXMLAnswer(function (contact) {
    		if (contact) {
    			contact = JSON.parse(contact);
    			if (contact.sys_id != g_form.getUniqueValue()) {
    				if (!isLoading) {
    					// only show the message for changed values (the readonly-part is desired on the initial load!)
    					g_form.addInfoMessage('Only one primary contact per Vendor is allowed. Current primary contact: ' + contact.display_value);
    				}
    				
    				g_form.setValue('primary_contact', false);
    				g_form.setReadOnly('primary_contact', true);
    				return;
    			}
    		}
    
    		g_form.setReadOnly('primary_contact', false);
    	});
    }

     

Please let us know if this solution solved your problem.

Thank you so much it works for me, however the primary contact shouldn't be read-only when we try to make it as true an alert needs to be populated if the vendor has already a primary contact.

Your welcome 🙂

If you don't it to be read-only, you have to remove all the g_form.setReadOnly calls (removing the g_form.setValue doesn't hurt either).