Hello everyone!
Welcome back to the Kaizen series!
Discount approvals are a standard part of sales governance.
Most organizations need something like this:
Discount % | Required Action |
< 10% | Auto-approve |
10–19.99% | Sales Manager approval |
≥ 20% | VP Sales approval |
Zoho CRM already includes a powerful
Approval Process feature capable of routing records, locking them, notifying approvers, and maintaining audit history.
So the natural question is "Isn’t the native Approval Process enough?". Often, yes. But when the discount logic depends on accurate percentage calculation across line items and header adjustments, we need a small architectural enhancement.
This Kaizen combines Functions(for decisions), Workflow Rules(for triggers), Approval Process(for governance), and Reporting Hierarchy(for routing) into a clean, scalable solution.
Understanding the native Approval Process
Before adding anything custom, it’s important to recognize what the Approval Process already does extremely well.
- Evaluates criteria based on field values
- Automatically submits records
- Locks records during review
- Routes to users, roles, or hierarchy levels
- Maintains approval history
- Sends notifications
It is a powerful governance engine.
However, it evaluates existing values and does not calculate new ones. That distinction matters in discount scenarios.
The missing piece: Reliable discount percentage
In Quotes:
- Discounts may be applied at line-item level
- Discounts may be applied at header level
- Grand Total reflects cumulative adjustments
There is no guaranteed native field that consistently represents
True Discount % = (Sub_Total - Grand_Total) / Sub_Total * 100
If approval rules rely directly on partial fields(like “Discount”), they may misrepresent the effective discount.
To ensure accuracy, we introduce a Function to calculate and store a reliable Discount Percentage.
We are not replacing the Approval Process, but preparing accurate data for it.
Here is the architectural flow with each component having a distinct responsibility. This makes the system sustainable.
Quote Saved --> Workflow triggers Function --> Function calculates Discount % --> Function sets Approval_Status --> Approval Process evaluates status --> Record submitted and locked |
Let's go over this one step at a time.
Step 1: Create Custom Fields(Quotes Module)
Field | Type | Purpose |
Discount_Percentage | Percent | Stores calculated discount |
Approval_Status | Picklist | Controls approval trigger. Values:
- Auto Approved
- Pending Manager Approval
- Pending VP Approval
- Approved
- Rejected
|
| Approval_Level | Single Line | Displays routing level |
Step 2: Write the CRM Function(Decision Layer)
This function calculates the effective discount and determines the approval level. This function becomes the decision engine.
void automation.Set_Quote_Approval_Level(String id) { quoteId = id.toLong(); quoteDetails = zoho.crm.getRecordById("Quotes",quoteId); if(quoteDetails != null) { subTotal = ifnull(quoteDetails.get("Sub_Total"),0).toDecimal(); grandTotal = ifnull(quoteDetails.get("Grand_Total"),0).toDecimal(); discount = subTotal - grandTotal; discountPercentage = 0.0; if(subTotal > 0) { discountPercentage = discount / subTotal * 100; } approvalStatus = ""; approvalLevel = ""; if(discountPercentage < 10) { approvalStatus = "Auto Approved"; approvalLevel = "None - Auto Approved"; } else if(discountPercentage < 20) { approvalStatus = "Pending Manager Approval"; approvalLevel = "Sales Manager"; } else { approvalStatus = "Pending VP Approval"; approvalLevel = "VP Sales"; } updateMap = Map(); updateMap.put("Discount_Percentage",discountPercentage.round(2)); updateMap.put("Approval_Status",approvalStatus); updateMap.put("Approval_Level",approvalLevel); updateResponse = zoho.crm.updateRecord("Quotes",quoteId,updateMap); } } |
Step 3: Workflow(Trigger Layer)
Every time a quote is saved, we want the discount to be evaluated automatically.
Create the following Workflow Rule:
Module: Quotes
Trigger: On Create or Edit
Action: Execute Function
Map the Quote ID with the "id" argument in the function.
Step 4: Approval Process(Governance Layer)
Rule 1 - Manager Approval when Discount% is 10 to 19.99
Approval_Status = "Pending Manager Approval" --> Route to Sales Manager(via hierarchy)
Rule 2 - VP Sales Approval when Discount% >= 20
Approval_Status = "Pending VP Approval" --> Route to VP Sales(via hierarchy)
When this process is triggered, CRM:
- Submits the record for approval
- Locks it
- Sends notification
- Tracks approval history
The outcome
Why is this layered approach strong?
This design works well because each component in the system has a clearly defined responsibility. The CRM Function acts as the decision layer. It performs the discount calculation, determines the appropriate approval level, and updates the control fields. This ensures that the logic behind the approval requirement is accurate and intentional.
The workflow serves as the trigger layer. Its only job is to execute the function whenever a quote is created or edited. It does not contain business logic; it simply initiates the evaluation process at the right time.
The approval process becomes the governance layer. Once the function sets the appropriate status, the approval engine evaluates the criteria, submits the record, locks it, routes it to the correct approver, and maintains the approval history. This is where enforcement happens.
Finally, the reporting hierarchy determines who the approver is. Instead of hard-coding specific users, the system dynamically identifies the appropriate manager or second-level supervisor based on the role structure. This keeps the design scalable and adaptable to organizational changes.
By separating calculation, triggering, enforcement, and routing into distinct layers, the solution remains clean, maintainable, and easy to extend. The Approval Process continues to do what it does best—govern and enforce—while the Function ensures that the decision it evaluates is accurate and business-driven.
Summary
Zoho CRM’s native Approval Process is powerful and reliable.
When business logic depends on calculated values, like true discount percentage, introducing a function strengthens the design by ensuring accurate, consistent decision-making.
Used together, Functions and Approval Process create:
- Intelligent routing
- Accurate governance
- Clean audit trails
- Scalable architecture
That combination is what makes this solution robust.
We hope you liked this post. We'll see you next week with another interesting one!
Write to us at
support@zohocrm.com or let us know your feedback in the comments section of this post.
Cheers!
==========================================================================
Recent Topics
Download a writer template as .docx instead of .pdf.
I have been trying to implement a feature to download a writer template as a .docx and got it working partly but it isn't good. Earlier I checked our code and I saw openurl("https://crm.zoho.com/crm/org121314/specific/Template.do?action=print&step=pdfPreview&id="
Allow the usage of Multi-Select fields as the primary field on "Layout Rules"
We want to force our users to enter some explanation strings when a multi-select field has been utilized. I can't understand the reason for the usage restriction of Multi-Select fields as a primary field. This is a simple "Display hidden mandatory field
Extract Archived Projects using Zoho Projects API
In my organization we archive the projects when they are already completed, charged, invoiced, so that only those that are still pending process remain active. I need to access all projects (active and archived) from an external system, but the API v3
Ask the Experts: Five-hour live Q&A session with Zoho WorkDrive product experts
Have questions about WorkDrive 5.0? Let’s talk! We recently launched Zoho WorkDrive 5.0, packed with powerful updates to help your team work smarter, stay secure, and get more value from your business content. From content-centric workflows and AI-powered
File upload support for subforms
Dear All, Subforms help you add and track data related to your CRM records. We've always supported most of the commonly used field types in subforms, so as to cater to your business requirements. Now we're happy to extend support to file upload fields.
Circular record relationship in CRM
Given there is a lookup in custom module Transactions creating a related list on the chosen Contact record. I. e. a lookup field on Transactions module points to Contacts. The related list on a Contact record can thus have have many transaction records.
Is it possible to pull the Zoho desk data into Zoho analytics in real time
Hi - I am looking to add more dashboards and reports of Zoho Desk in analytics. I see there is a schedule to pull the data into analytics, but I'm wondering if there is an option to pull the data in real time instead of a specific interval?
How to set value of dropdown field to variable
For the life of me, I can't figure out why the following code won't set input.status to the previousSelection. Steps to reproduce: 1. Click input.complete 2. input.status dropdown updates from '1-Backlog' to '4-Done' 3. Click input.complete again to deselect
[Product Update] TimeSheets module is now renamed as Time Logs in Zoho Projects.
Dear Zoho Analytics customers, As part of the ongoing enhancements in Zoho Projects, the Timesheets module has been renamed to Time Logs. However, the module name will continue to be displayed as Timesheets in Zoho Analytics until the relevant APIs are
[WEBINAR][MEA] Learn how to control your inventory and multi-channel sales with the Zoho Inventory & Zoho Books integration
Hello there, We are hosting an exclusive live webinar tailored for businesses across the Middle East and African countries, where you'll learn how to take full control of your inventory and multi-channel sales while keeping your accounting perfectly in
Less clicks, more connection – the usability edge of Zoho Desk
Imagine joining a new workplace, eager to prove your skills, partner with peers, learn new tools, and build a strong foundation for your career. The standards you've set could drive pressure into your head. You now discover the organization is using Zoho
Tip #3 Automating total item weight calculation for your sales orders in Zoho Inventory
Hello, Hope the day is treating you well. Last week, we saw how we could automate the calculation of total shipping charges from numerous shipments for your sales orders and invoices. This week, we will see how you can automate the calculation of total item weight for your sales orders. How does this work? First, you are required to capture the weight of all your items using a custom field. And when you create a sales order, you can either have the system display the individual weights for you or
Why Format section gets disabled when we create Merge Template over PDF
I need some assistance I have a Client who is going to give certificates to users who passes his exam. So, I am using mail merge but in ZOHO writer after I upload the PDF and create merge Template over PDF the format Section gets disabled. My problem
How to calculate separate totals for Product Line Items filtered by category in Quotes?
Hello! I'm working with Quotes in Zoho CRM and need help calculating conditional totals for line items. Current setup: I have two tables in my Quote template (Zoho Writer), both displaying Quoted Line Items Table 1 (top): Shows all products where Product
Zoho Desk API Documentation missing a required field
We are trying to create a section using this information. Even after preparing everything based on that page, we still get an error. The error we get is this: {"errorCode":"INVALID_DATA","message":"The data is invalid due to validation restrictions","errors":[{"fieldName":"/translations","errorType":"missing","errorMessage":""}]}
Fetch Subform values through a lookup of a lookup
Hi, I'm having an issue fetching the values of a subform through a lookup field through another lookup field. The code works perfectly to show me the subform row ID, but the second I try to get any readable data, it says "Error occurred. Please contact
Turn Decision Box to a button
Dear all, I need your help on CSS to turn a Decision Box to a Button. I have a Decision Box like: Turn on/off to refresh the information. (on User Input, either True or False, will refresh the information) Now I want to simulate to treat it like a Refresh
Emails not being received from a particular domain
Cannot receive any emails sent from atco.com Domain is in the spam whitelist so should be no reason for it not to be coming through. Have filed a ticket and besides a generic response of we are looking at it - it seems there is no actual support workers
Stock Count
The stock count is a nice new feature, but we cannot figure out how to: 1. Use it without assigning to a person, we have a team or one of multiple do stock counts as do most any company. 2. Add any extra fields to what the "counter" sees. The most important
Send Whatsapp message from Whatsapp template with custom variables
Hi, I'm trying to do some basic integration for sending WhatsApp messages from Zoho CRM using Zoho Desk whatsapp templates. When creating new whatsapp template in Zoho Desk we can choose ticket related fields as variables but it's not clear how to use
Outgoing blocked: Unusual activity detected.
I just made payment for my Zohomail Today and have been debited so i will like to be Unblocked because this is what it says (Outgoing blocked: Unusual activity detected) Thank you i await your swift responses
Integrating with My Own Application and ZOHO CRM Simultaneously
I have my own WhatsApp bot that uses my WhatsApp business account. I want to use the same phone number to integrate with ZOHO as well. What is the recommended way to do that? Should I integrate my application with ZOHO, forwarding messages whenever the
Account for Cryptocurrency Holdings in Zoho Books/Custom Currencies?
Hello, I've recently started using Zoho to run my small business and I've really been enjoying all of its features. However, I've been struggling to find a way to account for cryptocurrencies in Zoho Books. My company mines a Cryptocurrency token called
Transferring CRM Attachments to Workdrive
relatedrecords = zoho.crm.getRelatedRecords("Attachments","Conditions",conId); attachid = List(); for each ele in relatedrecords { attachementId = ele.get("id"); attachid.add(attachementId); } for each ele in attachid { counter = 1; downloadFile = invokeurl [ url: "https://www.zohoapis.com/crm/v2/Conditions/" + conId + "/Attachments/" + ele type: GET connection : "work_drive" ]; resp2 = zoho.crm.attachFile("Deals",dealId,downloadFile); resp3 = zoho.workdrive.uploadFile(downloadFile, dealWD, "PlaceHolder"+counter+"",
New Customization options in the module builder: Quick Create and Detail view
Hello everyone, We have introduced two new components to the module builder: Quick create and Detail view. The Quick Create Component It is a mini form used to create a record and associate it to the parent record from a lookup field. For example, if you have a Deals lookup in the Contacts module, then you can associate existing deals or create a deal and associate it with the contact. You can customize this Quick Create form by adding standard as well as custom fields. There is no limit to the number
unblock my zoho mail account. outlines@zoho.com
please unblock my zoho mail account, outlines@zoho.com
SMTP email sending problem
Hello, I've sent emails before, but you haven't responded. Please respond. My work is being disrupted. I can't send emails via SMTP. Initially, there were no problems, but now I'm constantly receiving 550 bounce errors. I can't use the service I paid
Mailk got blocked / Inquiry About Email Sending Limits and Upgrade Options
Dear Zoho Support Team, My name is Kamr Elsayed I created this account to use for applying for vocational training in Germany. As part of this process, I send multiple emails to different companies. However, after sending only 8 emails today, I received
Forwarder
Hi, I tried to add a forwarder from which emails are sent to my main zoho account email . However, it asks me for a code that should be received at the forwarder email, which is still not activated to send to my zoho emial account. So how can I get the
No chat option
Chat option is not supported.
Direct “Add to Google Calendar” Option in Zoho Meeting
Hello Zoho Meeting Team, Hope you are doing well. We would like to request an enhancement related to the “Add to Calendar” functionality in Zoho Meeting. Currently, when we open Zoho Meeting and view our meetings under My Calendar, there is an Add to
DKIM cannot be enabled for the domain as no verified default selector present
Hi Support Team, For Domain DKIM record trying to enable status. but showing error "DKIM cannot be enabled for the domain as no verified default selector present" So, please resolve the issue. Thank you.
unable to send message reason 554 5.1.8 Email outgoing blocked
unable to send message reason 554 5.1.8 Email outgoing blocked
I can't log in to my account on Thunderbird
I've just had to rebuild my PC (calamitous mess from Microsoft with Win10/Win 11 'upgrade' - they confirmed I had to start with a new build). I have used Zoho mail for years via Mozilla Thunderbird, but now I've had to download the latest version of TBird,
Should I Use DMARC?
When I configure Zoho Mail's DMARC settings, it's mandatory to fill in the RUA and RUF (Aggregate notification email address*, Forensic notification email address*) addresses. When we enter an email address in these fields, we receive reports from the
Introducing Profile Summary: Faster Candidate Insights with Zia
We’re excited to launch Profile Summary, a powerful new feature in Zoho Recruit that transforms how you review candidate profiles. What used to take minutes of resume scanning can now be assessed in seconds—thanks to Zia. A Quick Example Say you’re hiring
Books API Receiving an Error that Doesn't Make Sense when Creating Credit Note - trying to use 'ignore_auto_number_generation' argument
Hello, I'm working on a newly created routine and I'm getting an error that doesn't make sense when trying to create a new Credit Note. Here is my POST request. Endpoint: https://www.zohoapis.com/books/v3/creditnotes?organization_id=########## Body: {
How to move emails to Shared Mailbox?
Hello, I created a Shred Mailbox instead of using a distribution group. But I cannot move previous emails to certain shared mailbox. Is it possible move some emails from inbox to shared mailbox?
Collaboration with free plan user.
Hello. Do both users need to be on Pro plan to collaborate? Or can a Pro user share a note with a free plan user with the ability to edit?
Analytics Portal
I have the "standard plan" and want to explore the portal option; I activated the 15-day trial but do not see the pricing for the add-on. How can I get the price under "Upgrade add-ons." Thanks Rudy
Next Page