For Zoho Services only:


I'm actually part of something bigger at Ascent Business Solutions recognized as the top Zoho Premium Solutions Partner in the United Kingdom.

Ascent Business Solutions offer support for smaller technical fixes and projects for larger developments, such as migrating to a ZohoCRM.  A team rather than a one-man-band is always available to ensure seamless progress and address any concerns. You'll find our competitive support rates with flexible, no-expiration bundles at https://ascentbusiness.co.uk/zoho-services/uk-zoho-support.  For larger projects, talk to our experts and receive dedicated support from our hands-on project consultants at https://ascentbusiness.co.uk/zoho-services/zoho-crm-implementation.

The team I manage specializes in coding API integrations between Zoho and third-party finance/commerce suites such as Xero, Shopify, WooCommerce, and eBay; to name but a few.  Our passion lies in creating innovative solutions where others have fallen short as well as working with new businesses, new sectors, and new ideas.  Our success is measured by the growth and ROI we deliver for clients, such as transforming a garden shed hobby into a 250k monthly turnover operation or generating a +60% return in just three days after launch through online payments and a streamlined e-commerce solution, replacing a paper-based system.

If you're looking for a partner who can help you drive growth and success, we'd love to work with you.  You can reach out to us on 0121 392 8140 (UK) or info@ascentbusiness.co.uk.  You can also visit our website at https://ascentbusiness.co.uk.
Zoho Deluge: Using Remove Key on a Map and Copying Record Tags

Zoho Deluge: Using Remove Key on a Map and Copying Record Tags

What?
A quick article on how to use remove() on a map variable as well as a snippet of code to copy tags from a contact to a deal record.

Why?
Anything that stumps me for 30 minutes is worth writing a quick article on. In this case, I had a function querying tags on a contact record which needed to be copied to a deal record. I wanted to copy over the tag but apparently, the ID of the tag is not allowed to be copied over.

The official documentation says to use remove() to remove a key from a map. In this case, the ID key and value pair. It would then tell me the list was null when I thought I was adding the map with the ID removed back into a list. The map itself was null.

How?
We are using an API action called "Add_Tags". I'm going to get the tags of the contact record using an invokeurl because shortcode only gives me name and ID; but I want the color code field as well which I only seem to get with an InvokeURL. I'm then going to create a list map of tags and add these to the deal record.

The key take-away to remember here is that remove() is a void function, similar to the sort() function; in that if you try to assign this to a new variable name, it will fail.

In other words:
copyraw
m_NewTag = m_Tag.remove("id");
// yields null

m_Tag.remove("id");
// returns m_Tag map without the ID key-value pair
  1.  m_NewTag = m_Tag.remove("id")
  2.  // yields null 
  3.   
  4.  m_Tag.remove("id")
  5.  // returns m_Tag map without the ID key-value pair 

The use-case
This is a snippet that gets the tags of a contact and copies it over to the deal record:
copyraw
l_Tags = List();
//
r_DealDetails = zoho.crm.getRecordById("Deals",p_DealID);
if(!isNull(r_DealDetails.get("Contact_Name")))
{
	r_ContactDetails = invokeurl
	[
		url :"https://www.zohoapis.com/crm/v7/Contacts/" + r_DealDetails.get("Contact_Name").get("id")
		type :GET
		connection:"zcrm"
	];
	//
	l_ContactDetails = ifnull(r_ContactDetails.get("data"), List());
	for each m_ContactDetails in l_ContactDetails
    {
		if(!isNull(m_ContactDetails.get("Tag")))
		{
			for each m_Tag in m_ContactDetails.get("Tag")
			{
				m_Tag.remove("id");
				l_Tags.add(m_Tag);
			}
		}
		info l_Tags;
		//
		if(l_Tags.size()>0)
		{
			m_Params = {"tags": l_Tags};
			r_AddTags = invokeurl
			[
				url :"https://www.zohoapis.com/crm/v7/Deals/" + p_DealID + "/actions/add_tags"
				type :POST
				parameters:m_Params.toString()
				connection:"azcrm"
			];
			info r_AddTags;
		}		
    }
}
  1.  l_Tags = List()
  2.  // 
  3.  r_DealDetails = zoho.crm.getRecordById("Deals",p_DealID)
  4.  if(!isNull(r_DealDetails.get("Contact_Name"))) 
  5.  { 
  6.      r_ContactDetails = invokeUrl 
  7.      [ 
  8.          url :"https://www.zohoapis.com/crm/v7/Contacts/" + r_DealDetails.get("Contact_Name").get("id") 
  9.          type :GET 
  10.          connection:"zcrm" 
  11.      ]
  12.      // 
  13.      l_ContactDetails = ifnull(r_ContactDetails.get("data"), List())
  14.      for each m_ContactDetails in l_ContactDetails 
  15.      { 
  16.          if(!isNull(m_ContactDetails.get("Tag"))) 
  17.          { 
  18.              for each m_Tag in m_ContactDetails.get("Tag") 
  19.              { 
  20.                  m_Tag.remove("id")
  21.                  l_Tags.add(m_Tag)
  22.              } 
  23.          } 
  24.          info l_Tags; 
  25.          // 
  26.          if(l_Tags.size()>0) 
  27.          { 
  28.              m_Params = {"tags": l_Tags}
  29.              r_AddTags = invokeUrl 
  30.              [ 
  31.                  url :"https://www.zohoapis.com/crm/v7/Deals/" + p_DealID + "/actions/add_tags" 
  32.                  type :POST 
  33.                  parameters:m_Params.toString() 
  34.                  connection:"azcrm" 
  35.              ]
  36.              info r_AddTags; 
  37.          } 
  38.      } 
  39.  } 

copyraw
/*
{"code":"INVALID_DATA","details":{"api_name":"id","json_path":"$.tags[0].id"},"message":"invalid tag id","status":"error"}
-> Error was due to trying to assign map with removed key to a new map.
-> Solution was to remove the assignment and simply keep m_Tag.remove("id");

{"code":"MAPPING_MISMATCH","details":{"mapped_field":{"api_name":"name","json_path":"$.tags[0].name"},"api_name":"color_code","json_path":"$.tags[0].color_code"},"message":"Given tag present with different colour already.","status":"error"}
-> Error was due to someone already giving tags with the same name 
-> Solution is to remove the color_code key as well... m_Tag.remove("color_code");
*/
  1.  /* 
  2.  {"code":"INVALID_DATA","details":{"api_name":"id","json_path":"$.tags[0].id"},"message":"invalid tag id","status":"error"} 
  3.  -> Error was due to trying to assign map with removed key to a new map. 
  4.  -> Solution was to remove the assignment and simply keep m_Tag.remove("id")
  5.   
  6.  {"code":"MAPPING_MISMATCH","details":{"mapped_field":{"api_name":"name","json_path":"$.tags[0].name"},"api_name":"color_code","json_path":"$.tags[0].color_code"},"message":"Given tag present with different colour already.","status":"error"} 
  7.  -> Error was due to someone already giving tags with the same name 
  8.  -> Solution is to remove the color_code key as well... m_Tag.remove("color_code")
  9.  */ 

Considering that neither the color code nor ID were necessary in the end, I can use shortcode for getting the tag. Note that on a fresh CRM instance where no tags have been used previously, I would use the code above to maintain tag colors. Here's the shortened version where the system chooses the color for the tag:
copyraw
l_Tags = List();
//
r_DealDetails = zoho.crm.getRecordById("Deals",p_DealID);
if(!isNull(r_DealDetails.get("Contact_Name")))
{
	m_ContactDetails = zoho.crm.getRecordById("Contacts", r_DealDetails.get("Contact_Name").get("id"));
	if(!isNull(m_ContactDetails.get("Tag")))
	{
		for each m_Tag in m_ContactDetails.get("Tag")
		{
			m_Tag.remove("id");
			l_Tags.add(m_Tag);
		}
	}
	info l_Tags;
	//
	if(l_Tags.size()>0)
	{
		m_Params = {"tags": l_Tags};
		r_AddTags = invokeurl
		[
			url :"https://www.zohoapis.com/crm/v7/Deals/" + p_DealID + "/actions/add_tags"
			type :POST
			parameters:m_Params.toString()
			connection:"zcrm"
		];
		info r_AddTags;
	}		
}
  1.  l_Tags = List()
  2.  // 
  3.  r_DealDetails = zoho.crm.getRecordById("Deals",p_DealID)
  4.  if(!isNull(r_DealDetails.get("Contact_Name"))) 
  5.  { 
  6.      m_ContactDetails = zoho.crm.getRecordById("Contacts", r_DealDetails.get("Contact_Name").get("id"))
  7.      if(!isNull(m_ContactDetails.get("Tag"))) 
  8.      { 
  9.          for each m_Tag in m_ContactDetails.get("Tag") 
  10.          { 
  11.              m_Tag.remove("id")
  12.              l_Tags.add(m_Tag)
  13.          } 
  14.      } 
  15.      info l_Tags; 
  16.      // 
  17.      if(l_Tags.size()>0) 
  18.      { 
  19.          m_Params = {"tags": l_Tags}
  20.          r_AddTags = invokeUrl 
  21.          [ 
  22.              url :"https://www.zohoapis.com/crm/v7/Deals/" + p_DealID + "/actions/add_tags" 
  23.              type :POST 
  24.              parameters:m_Params.toString() 
  25.              connection:"zcrm" 
  26.          ]
  27.          info r_AddTags; 
  28.      } 
  29.  } 

Fix to historical records
This snippet uses COQL to find me all the deals where the tag is empty but the contact record wasn't. There is an additional/repeat action to add tags; the first attempts to copy over the color on a new tag; the second is if this fails to copy over the color (because there is an existing tag with the same name), then it only copies over the name:
copyraw
v_TotalCount = 0;
v_TotalProcessed = 0;
v_PerPage = 100;
v_CoqlQuery = "select id, Contact_Name.Tag 'Tag' from Deals where Tag is null and Contact_Name.Tag is not null order by id asc limit " + v_PerPage;
m_Params = {"select_query":v_CoqlQuery};
r_Coql = invokeurl
[
	url :"https://www.zohoapis.com/crm/v7/coql"
	type :POST
	parameters:m_Params.toString()
	connection:"zcrm"
];
if(!isNull(r_Coql.get("data")))
{
	for each  m_Data in r_Coql.get("data")
	{
		if(!isNull(m_Data.get("id")))
		{
			v_TotalCount = v_TotalCount + 1;
			//
			l_Tags = List();
			for each  m_Tag in m_Data.get("Tag")
			{
				m_Tag.remove("id");
				l_Tags.add(m_Tag);
			}
			if(l_Tags.size() > 0)
			{
				m_Params = {"tags":l_Tags};
				r_AddTags = invokeurl
				[
					url :"https://www.zohoapis.com/crm/v6/Deals/" + m_Data.get("id") + "/actions/add_tags"
					type :POST
					parameters:m_Params.toString()
					connection:"zcrm"
				];
				if(!isNull(r_AddTags.get("code")) && r_AddTags.get("code").equals("MAPPING_MISMATCH"))
				{
					info "Tags Error: MAPPING_MISMATCH: Color";
					info m_Tag.get("name") + " " + m_Tag.get("color_code");
					//
					l_Tags = List();
					for each  m_Tag in m_Data.get("Tag")
					{
						m_Tag.remove("id");
						m_Tag.remove("color_code");
						l_Tags.add(m_Tag);
					}
					m_Params = {"tags":l_Tags};
					r_AddTags = invokeurl
					[
						url :"https://www.zohoapis.com/crm/v7/Deals/" + m_Data.get("id") + "/actions/add_tags"
						type :POST
						parameters:m_Params.toString()
						connection:"zcrm"
					];
				}
				if(!isNull(r_AddTags.get("code")) && r_AddTags.get("code").equals("SUCCESS"))
				{
					info "Tag Error resolved.  Tags updated.";
					v_TotalProcessed = v_TotalProcessed + 1;
				}
			}
		}
		info "-------------------------";
	}
}
return "Updated " + v_TotalProcessed + " of " + v_TotalCount;
  1.  v_TotalCount = 0
  2.  v_TotalProcessed = 0
  3.  v_PerPage = 100
  4.  v_CoqlQuery = "select id, Contact_Name.Tag 'Tag' from Deals where Tag is null and Contact_Name.Tag is not null order by id asc limit " + v_PerPage; 
  5.  m_Params = {"select_query":v_CoqlQuery}
  6.  r_Coql = invokeUrl 
  7.  [ 
  8.      url :"https://www.zohoapis.com/crm/v7/coql" 
  9.      type :POST 
  10.      parameters:m_Params.toString() 
  11.      connection:"zcrm" 
  12.  ]
  13.  if(!isNull(r_Coql.get("data"))) 
  14.  { 
  15.      for each  m_Data in r_Coql.get("data") 
  16.      { 
  17.          if(!isNull(m_Data.get("id"))) 
  18.          { 
  19.              v_TotalCount = v_TotalCount + 1
  20.              // 
  21.              l_Tags = List()
  22.              for each  m_Tag in m_Data.get("Tag") 
  23.              { 
  24.                  m_Tag.remove("id")
  25.                  l_Tags.add(m_Tag)
  26.              } 
  27.              if(l_Tags.size() > 0) 
  28.              { 
  29.                  m_Params = {"tags":l_Tags}
  30.                  r_AddTags = invokeUrl 
  31.                  [ 
  32.                      url :"https://www.zohoapis.com/crm/v6/Deals/" + m_Data.get("id") + "/actions/add_tags" 
  33.                      type :POST 
  34.                      parameters:m_Params.toString() 
  35.                      connection:"zcrm" 
  36.                  ]
  37.                  if(!isNull(r_AddTags.get("code")) && r_AddTags.get("code").equals("MAPPING_MISMATCH")) 
  38.                  { 
  39.                      info "Tags Error: MAPPING_MISMATCH: Color"
  40.                      info m_Tag.get("name") + " " + m_Tag.get("color_code")
  41.                      // 
  42.                      l_Tags = List()
  43.                      for each  m_Tag in m_Data.get("Tag") 
  44.                      { 
  45.                          m_Tag.remove("id")
  46.                          m_Tag.remove("color_code")
  47.                          l_Tags.add(m_Tag)
  48.                      } 
  49.                      m_Params = {"tags":l_Tags}
  50.                      r_AddTags = invokeUrl 
  51.                      [ 
  52.                          url :"https://www.zohoapis.com/crm/v7/Deals/" + m_Data.get("id") + "/actions/add_tags" 
  53.                          type :POST 
  54.                          parameters:m_Params.toString() 
  55.                          connection:"zcrm" 
  56.                      ]
  57.                  } 
  58.                  if(!isNull(r_AddTags.get("code")) && r_AddTags.get("code").equals("SUCCESS")) 
  59.                  { 
  60.                      info "Tag Error resolved.  Tags updated."
  61.                      v_TotalProcessed = v_TotalProcessed + 1
  62.                  } 
  63.              } 
  64.          } 
  65.          info "-------------------------"; 
  66.      } 
  67.  } 
  68.  return "Updated " + v_TotalProcessed + " of " + v_TotalCount; 
Category: Zoho :: Article: 898

Add comment

Your rating:

Submit

Credit where Credit is Due:


Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman
www.joellipman.com

Please publish modules in offcanvas position.