For Zoho services only


I'm currently part of a wider delivery team at Ascent Business Solutions, recognised as a leading Zoho Premium Solutions Partner in the United Kingdom.

Ascent Business Solutions support organisations with everything from targeted technical fixes through to full Zoho CRM implementations and long-term platform adoption. Working as a team rather than a one-person consultancy allows projects to move forward consistently, with access to the right skills at each stage.

The team I manage specialises in API integrations between Zoho and third-party finance and commerce platforms such as Xero, Shopify, WooCommerce, and eBay. Much of our work involves solving integration challenges that fall outside standard documentation, supporting new ideas, new sectors, and evolving business models.

Success is measured through practical outcomes and return on investment, ranging from scaling small operations into high-turnover businesses to delivering rapid gains through online payments, automation, and streamlined digital workflows.

If you are looking for structured Zoho expertise backed by an established consultancy, you can contact Ascent Business Solutions on 0121 392 8140 (UK), email info@ascentbusiness.co.uk, or visit https://www.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 Deluge :: Article: 423

Joes Word Cloud

Accreditation

Badge - Zoho Creator Certified Developer Associate
Badge - Zoho Deluge Certified Developer
Badge - Certified Zoho CRM Developer

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Paypal:
Donate to Joel Lipman via PayPal

Bitcoin:
Donate to Joel Lipman with Bitcoin bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Ethereum:
Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF

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