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 CRM: Update Opportunity Type as New or Existing Business

Zoho CRM: Update Opportunity Type as New or Existing Business

What?
A quick article on how to get Zoho CRM to update the deal or opportunity type field with "New Business" or "Existing Business" depending on whether this won opportunity is the second time for this account.

Why?
Mainly for reporting purposes. We want ZohoCRM to report on what is repeat business and what is new business. As part of a process, you could get your staff to update the opportunity "Type" to "Existing Business" or "New Business" at the time they update the stage to "Closed Won". If you'd rather that staff don't have to remember to do this, then this snippet of code is for you.

How?
Note that here, the term "opportunity" is synonymous with the "deal". Also note that I have 2 versions of this, the first is if you have Enterprise or Ultimate edition (or Zoho One) which supports functions; the second is further down on the page applicable to Zoho CRM Professional (which doesn't support custom functions).

To be specific, we only want the opportunity type to be updated to "Existing Business" if the opportunity is the second "Won" opportunity against this account.



Zoho One, Zoho CRM Enterprise, or Zoho CRM Ultimate


To do this, we will need a specific workflow that picks up the change in status at the sales order level and where the sales order has been completed (fulfilled or invoiced). This will then see if any other opportunities were won against this account and then update the opportunity related to this sales order.

the Workflow
  1. Login to Zoho CRM as an administrator
  2. Go to Setup > Automation > Workflow Rules > Create Rule
  3. Set "Record Type" to "Sales Orders" and "Rule Name" to something like "Sales Orders - On Complete"
  4. Execute this workflow based on "Record Action" > "Edit" > "Specific Field(s) Get Modified" > tick the "Repeat every time" > Criteria is "When Status is modified to the value ..." then list all complete statuses of a sales order.
  5. Condition 1 is that the status must match one of the complete statuses of the sales order.
  6. Under "Instant action", select "Function" > "Configure Function" > "Write your own"
  7. Give it a displayed name such as "Fn - Sales Orders - On Complete"
  8. Give it a function name, I'm calling mine: fn_SalesOrders_OnComplete
  9. Paste in the function below
  10. In the rightmost bar, you will see a pair of tabs one which has (x) and the tooltip "Arguments" click on this
    1. Type p_SoID in the first field
    2. In the second field type the hash/pound sign # and select "Sales Orders" then "Sales Order Id"

the Code
copyraw
void automation.fn_SalesOrders_OnComplete(Int p_SoID)
{
/* *******************************************************************************
	Function:       void automation.fn_SalesOrders_OnComplete(int p_SoID)
	Label:          Fn - Sales Orders - On Complete
	Trigger:        Workflow when a sales order is completed
	Purpose:		To update the opportunity type to existing or new business
	Inputs:         int p_SoID (the sales order zoho id)
	Outputs:        -

	Date Created:   2026-02-17 (Joel Lipman)
					- Initial release
					- Counts opps against this account and updates the field for this opp
	Date Modified:	???
					- ???

	More Information:
					Any information that may help

	******************************************************************************* */
	//
	// initialize
	v_ThisDealID = "0";
	v_ThisAccountID = "0";
	v_ThisContactID = "0";
	v_CountWonOpps = 0;
	//
	// add in what sales orders you consider "closed won"
	l_CompletedSOStatuses = List();
	l_CompletedSOStatuses.add("Partially Fulfilled");
	l_CompletedSOStatuses.add("Fulfilled");
	l_CompletedSOStatuses.add("Partially Invoiced");
	l_CompletedSOStatuses.add("Invoiced");
	//
	// get sales order record
	r_SoDetails = zoho.crm.getRecordById("Sales_Orders",p_SoID);
	//
	// check status of sales order is a completed one (can be done in workflow but this is a double-check)
	if(l_CompletedSOStatuses.containsIgnoreCase(r_SoDetails.get("Status")))
	{
		if(!isNull(r_SoDetails.get("Deal_Name")))
		{
			v_ThisDealID = r_SoDetails.get("Deal_Name").get("id");
		}
		if(!isNull(r_SoDetails.get("Account_Name")))
		{
			v_ThisAccountID = r_SoDetails.get("Account_Name").get("id");
		}
		if(!isNull(r_SoDetails.get("Contact_Name")))
		{
			v_ThisContactID = r_SoDetails.get("Contact_Name").get("id");
		}
		info v_ThisContactID;
		//
		// set ordered criteria
		m_SortCriteria = Map();
		m_SortCriteria.put("sort_by","id");
		m_SortCriteria.put("sort_order","desc");
		m_SortCriteria.put("fields","id,Status,Deal_Name");
		//
		// count opportunities against this account (B2B)
		r_SearchAccountDeals = zoho.crm.getRelatedRecords("Deals","Accounts",v_ThisAccountID,1,200,m_SortCriteria);
		l_SearchAccountDeals = ifnull(r_SearchAccountDeals,List());
		if(l_SearchAccountDeals.size() > 0)
		{
			for each  m_RelatedDeal in l_SearchAccountDeals
			{
				v_RelatedDealStage = ifnull(m_RelatedDeal.get("Stage"),"");
				v_RelatedDealId = ifnull(m_RelatedDeal.get("id"),"");
				//
				if(v_RelatedDealStage.containsIgnoreCase("Closed Won") && v_RelatedDealId != v_ThisDealID)
				{
					v_CountWonOpps = v_CountWonOpps + 1;
				}
			}
		}
		//
		// account field was blank?
		// count opportunities against this contact (B2C)
		if(v_CountWonOpps == 0 && v_ThisAccountID == "0")
		{
			r_SearchContactDeals = zoho.crm.getRelatedRecords("Deals","Contacts",v_ThisContactID,1,200,m_SortCriteria);
			l_SearchContactDeals = ifnull(r_SearchContactDeals,List());
			if(l_SearchContactDeals.size() > 0)
			{
				for each  m_RelatedDeal2 in l_SearchContactDeals
				{
					v_RelatedDealStage2 = ifnull(m_RelatedDeal2.get("Stage"),"");
					v_RelatedDealId2 = ifnull(m_RelatedDeal2.get("id"),"");
					//
					if(v_RelatedDealStage2.containsIgnoreCase("Closed Won") && v_RelatedDealId2 != v_ThisDealID)
					{
						v_CountWonOpps = v_CountWonOpps + 1;
					}
				}
			}
		}
		//
		// update the opp
		if(v_CountWonOpps > 0)
		{
			m_UpateOpp = Map();
			m_UpateOpp.put("Type","Existing Business");
			r_UpdateOpp = zoho.crm.updateRecord("Deals",v_ThisDealID,m_UpateOpp);
			info r_UpdateOpp;
		}
		else 
		{
			info "This is the first complete sales order so the opportunity type here is still 'New Business'.";
		}
	}
	else
	{
		info "This Sales Order is not considered complete so it will not update the opportunity.";
	}
}
  1.  void automation.fn_SalesOrders_OnComplete(Int p_SoID) 
  2.  { 
  3.  /* ******************************************************************************* 
  4.      Function:       void automation.fn_SalesOrders_OnComplete(int p_SoID) 
  5.      Label:          Fn - Sales Orders - On Complete 
  6.      Trigger:        Workflow when a sales order is completed 
  7.      Purpose:        To update the opportunity type to existing or new business 
  8.      Inputs:         int p_SoID (the sales order zoho id) 
  9.      Outputs:        - 
  10.   
  11.      Date Created:   2026-02-17 (Joel Lipman) 
  12.                      - Initial release 
  13.                      - Counts opps against this account and updates the field for this opp 
  14.      Date Modified:    ??? 
  15.                      - ??? 
  16.   
  17.      More Information: 
  18.                      Any information that may help 
  19.   
  20.      ******************************************************************************* */ 
  21.      // 
  22.      // initialize 
  23.      v_ThisDealID = "0"
  24.      v_ThisAccountID = "0"
  25.      v_ThisContactID = "0"
  26.      v_CountWonOpps = 0
  27.      // 
  28.      // add in what sales orders you consider "closed won" 
  29.      l_CompletedSOStatuses = List()
  30.      l_CompletedSOStatuses.add("Partially Fulfilled")
  31.      l_CompletedSOStatuses.add("Fulfilled")
  32.      l_CompletedSOStatuses.add("Partially Invoiced")
  33.      l_CompletedSOStatuses.add("Invoiced")
  34.      // 
  35.      // get sales order record 
  36.      r_SoDetails = zoho.crm.getRecordById("Sales_Orders",p_SoID)
  37.      // 
  38.      // check status of sales order is a completed one (can be done in workflow but this is a double-check) 
  39.      if(l_CompletedSOStatuses.containsIgnoreCase(r_SoDetails.get("Status"))) 
  40.      { 
  41.          if(!isNull(r_SoDetails.get("Deal_Name"))) 
  42.          { 
  43.              v_ThisDealID = r_SoDetails.get("Deal_Name").get("id")
  44.          } 
  45.          if(!isNull(r_SoDetails.get("Account_Name"))) 
  46.          { 
  47.              v_ThisAccountID = r_SoDetails.get("Account_Name").get("id")
  48.          } 
  49.          if(!isNull(r_SoDetails.get("Contact_Name"))) 
  50.          { 
  51.              v_ThisContactID = r_SoDetails.get("Contact_Name").get("id")
  52.          } 
  53.          info v_ThisContactID; 
  54.          // 
  55.          // set ordered criteria 
  56.          m_SortCriteria = Map()
  57.          m_SortCriteria.put("sort_by","id")
  58.          m_SortCriteria.put("sort_order","desc")
  59.          m_SortCriteria.put("fields","id,Status,Deal_Name")
  60.          // 
  61.          // count opportunities against this account (B2B) 
  62.          r_SearchAccountDeals = zoho.crm.getRelatedRecords("Deals","Accounts",v_ThisAccountID,1,200,m_SortCriteria)
  63.          l_SearchAccountDeals = ifnull(r_SearchAccountDeals,List())
  64.          if(l_SearchAccountDeals.size() > 0) 
  65.          { 
  66.              for each  m_RelatedDeal in l_SearchAccountDeals 
  67.              { 
  68.                  v_RelatedDealStage = ifnull(m_RelatedDeal.get("Stage"),"")
  69.                  v_RelatedDealId = ifnull(m_RelatedDeal.get("id"),"")
  70.                  // 
  71.                  if(v_RelatedDealStage.containsIgnoreCase("Closed Won") && v_RelatedDealId != v_ThisDealID) 
  72.                  { 
  73.                      v_CountWonOpps = v_CountWonOpps + 1
  74.                  } 
  75.              } 
  76.          } 
  77.          // 
  78.          // account field was blank? 
  79.          // count opportunities against this contact (B2C) 
  80.          if(v_CountWonOpps == 0 && v_ThisAccountID == "0") 
  81.          { 
  82.              r_SearchContactDeals = zoho.crm.getRelatedRecords("Deals","Contacts",v_ThisContactID,1,200,m_SortCriteria)
  83.              l_SearchContactDeals = ifnull(r_SearchContactDeals,List())
  84.              if(l_SearchContactDeals.size() > 0) 
  85.              { 
  86.                  for each  m_RelatedDeal2 in l_SearchContactDeals 
  87.                  { 
  88.                      v_RelatedDealStage2 = ifnull(m_RelatedDeal2.get("Stage"),"")
  89.                      v_RelatedDealId2 = ifnull(m_RelatedDeal2.get("id"),"")
  90.                      // 
  91.                      if(v_RelatedDealStage2.containsIgnoreCase("Closed Won") && v_RelatedDealId2 != v_ThisDealID) 
  92.                      { 
  93.                          v_CountWonOpps = v_CountWonOpps + 1
  94.                      } 
  95.                  } 
  96.              } 
  97.          } 
  98.          // 
  99.          // update the opp 
  100.          if(v_CountWonOpps > 0) 
  101.          { 
  102.              m_UpateOpp = Map()
  103.              m_UpateOpp.put("Type","Existing Business")
  104.              r_UpdateOpp = zoho.crm.updateRecord("Deals",v_ThisDealID,m_UpateOpp)
  105.              info r_UpdateOpp; 
  106.          } 
  107.          else 
  108.          { 
  109.              info "This is the first complete sales order so the opportunity type here is still 'New Business'."
  110.          } 
  111.      } 
  112.      else 
  113.      { 
  114.          info "This Sales Order is not considered complete so it will not update the opportunity."
  115.      } 
  116.  } 

Additional Notes:
  • This is for completed sales orders. If you need to trigger this at the invoice level, then you will need to change the workflow to trigger when the invoice reaches a certain status and modify the code above to reflect this.





Zoho Standard, Zoho Professional

To do this, we will need to use the "Action by Zoho Flow" feature available in a CRM workflow. Again, we are using the example here that a completed/fulfilled sales order updates the deal/opportunity type. If you wanted this only when the deal is closed won, then you could simply amend the below omitting some of the steps.

Step 1: Add Marker Fields
  1. Login to ZohoCRM as an Administrator
  2. Go to Setup > Customization > Modules and Fields > Accounts > Layout (Standard)
  3. Add a checkbox field called "Has Won a Deal" (unticked by default)
  4. Go to Setup > Customization > Modules and Fields > Sales Orders > Layout (Standard)
  5. Add a checkbox field called "Account Won Before" (unticked by default)
Step 2: Automation - Set "Has Won a Deal" when a deal is won
  1. Go to Setup > Automation > Workflow Rules > Create Rule
  2. Record Type (Module) is Deals (aka Opportunities)
  3. Rule Name, I'm calling mine "Deals - Update Account Won a Deal" > Next
    1. Execute this workflow rule on Record Action > Create or Edit > Tick "Repeat this workflow whenever a deal is edited" > Done
    2. Condition 1 has criteria: Deals matching certain conditions
      1. Click in the dropdown and select "Stage" "is WON" > Done
    3. Instant Action is a Field Update > Create Field Update
      1. Give it a name, I'm calling mine "Deal - Update Account Won"
      2. Module should be "Accounts"
      3. Field is "Has Won a Deal"
      4. Value to be updated is ticked
    4. Click "Save and Associate"
  4. Click on "Save" to save the workflow.
Step 3: Automation - Map marker from Account to new Sales Order
  1. Go to Setup > Automation > Workflow Rules > Create Rule
  2. Record Type (Module) is Sales Orders
  3. Rule Name, I'm calling mine "Sales Order - Get Previous Won" > Next
    1. Execute this workflow rule on Record Action > Create > Next
    2. Condition 1 includes "All Sales Orders > Done
    3. Under "Instant Actions" click on this and select "Actions by Zoho Flow"
      1. Click on "New Action"
      2. Search Apps for Zoho CRM
      3. Select "Zoho CRM" > "Next"
      4. Scroll down to "Update Module Entry" > Next
      5. Choose Connection
        • If "New Connection" then give it a name (eg. My Zoho CRM Connection)
        • Scroll down under "Action" and ensure that "Update module entry" is ticked
        • Click "Authorize"
        • You will be advised of what this connection has permission to do > Authorize (If exists, then click on "Re-Use")
      6. You will return to the connection panel > Next
      7. Give it an action name, I'm calling mine: "Sales Order - Pull Previous Won From Account"
      8. Give it a description, I gave it: "On sales order creation, maps value from the account 'Has Won a Deal' to the sales order 'Account Won Before'."
      9. For Module, specify "Sales Orders" (should be already selected and read-only) > Create
      10. A popup for "Update Module Entry" will appear:
        • Module is "Sales Orders"
        • Layout is "Standard"
        • Click into the field "Entry Id" and on the right sidebar expand "CRM Sales Orders" by clicking on it
        • Scroll down and select "Sales Order Id" (this should insert "${Sales_Orders.id}" into the field)
        • Staying within this popup, scroll down on the left (main panel of fields) and find "Account Won Before"
        • Click into the field "Account Won Before" and on the right sidebar expand "CRM Accounts" by clicking on it
        • Click on "Has Won a Deal" (this should insert "${Sales_Orders.lookup.Account_Name.Has_Won_a_Deal}" into the field)
      11. Click on "Done"
    4. Associate the action
  4. Save the workflow
You should have something like the following:

Step 4: Automation - Set Deal / Opportunity won to Existing Business
  1. Go to Setup > Automation > Workflow Rules > Create Rule
  2. Record Type (Module) is "Sales Orders"
  3. Rule Name, I'm calling mine "Sales Order - Update Opportunity Type" > Next
    1. Execute this workflow rule on Record Action > Edit > Specific field(s) get modified > Tick "Repeat this workflow whenever a deal is edited"
      1. When Status is modified to the value "Delivered" (or whichever status is considered complete/fulfilled) > Done
    2. Condition 1 has criteria: Sales Orders matching certain conditions
      1. Click in the dropdown and select "Account Won Before" is "Selected" > Done
    3. Instant Action is a Field Update > Create Field Update
      1. Give it a name, I'm calling mine "Sales Order - Update Deal Type"
      2. Module should be "Deals"
      3. Field is "Type"
      4. Value to be updated is "Existing Business"
      5. Click "Save and Associate"
    4. Click on the "+ Action" and select another "Field Update"
    5. Click on "Create Field Update"
      1. Give it a name, I'm calling mine "Sales Order - Update Deal Won"
      2. Module should be "Deals"
      3. Field is "Stage"
      4. Value to be updated is "Closed Won"
      5. Click "Save and Associate"
    6. Click on "+ Add another condition" (under Condition1)
      1. Select "Sales Orders that do not meet any of the above conditions" > Next
      2. Click on "Instant Actions" and select "Field Update"
      3. Change the Module dropdown to "Deals" (Opportunities)
      4. Select the "Sales Order - Update Deal Won"
      5. Click on "Associate"
  4. Click on "Save" to save the workflow.
You should have something like the following:

Caveat
There is a limit to the number of Zoho Flows per month that CRM professional lets you have. If you need a higher volume, ensure that you are the recipient for the Zoho Flow limit warnings (eg. when reaching 90% you will be emailed by Zoho for some more money).



Category: Zoho CRM :: Article: 1723

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