User Tips: Adding Multiple Products (Package) to a Quote v2.0 (with Client Script)

User Tips: Adding Multiple Products (Package) to a Quote v2.0 (with Client Script)

This solution is an improvement on the original idea which used deluge. My solution was posted in the comments are: https://help.zoho.com/portal/en/community/topic/adding-multiple-products-package-to-a-quote

The updated version uses client script instead of deluge.

Hopefully this might help a few people. It helps our reps speed up the process of creating quotes and quoting accurately.

Details below:


Problem:

We run numerous manufacturer promotions with various bundled items and discounts. Reps struggle to remember all details, leading to incorrect discounts on quotes.


Solution

I created a custom module for Product Packages. For each promotion, we create a "Package" including all products, discounts, and start/end dates. A quote lookup field allows users to select a package, automatically adding the related products with accurate pricing and information.

When a user selects a package, a client script retrieves all related products and discounts, adding them to the quote. The lookup field is then reset for additional product entries.

Some fields on the package layout include:

  1. Promotion type
  2. Status
  3. Start / End dates for the promotion. 
  4. Pop-up message field if we want to show the rep a message when quoting the package

I also have a workflow that sets the package to “Expired” when the record expiration date hits. The lookup is filtered in the quotes module to only show “Active” packages.

In Action (with lookup field to the package module):



The Setup:
Create a custom module “Package Items”. Add the fields as below. 



Additional Info
1. I also use client script to hide the “Auto-Quote” field when in a standard view page
2. When I name a package, a deluge script runs to append the Package ID number which is an auto-number field.


The Code: 

  1. try {
    // List of funny loading messages
    var loadingMessages = [
    "Cranking up the quote machine...",
    "One sec... just stepped out for coffee.",
    "Hold tight! The hamsters are running the wheels.",
    "Almost there... giving it a little extra attention.",
    "Loading... probably faster than your internet speed.",
    "Please hold while we make magic happen.",
    "Just a moment... our servers are stretching their legs.",
    "Your patience is appreciated... and rewarded!",
    "Brewing up your quote right now...",
    "Give us a second... we're flexing our technical muscles.",
    "Our system is doing some yoga... stay calm!",
    "Loading... don't worry, it's not stuck!",
    "Fetching your data... hopefully with no detours!",
    "Keep calm and let us handle the rest.",
    "Processing... taking a coffee break, be right back!",
    "Stay tuned... greatness is loading.",
    "Our system is running... faster than a cheetah!",
    "Looks like you're going all in on this quote!",
    "Getting things ready... just need a moment.",
    "Hold on... we're aligning some stars for you.",
    "Please wait... we're feeding the server squirrels.",
    "One moment... your quote is coming fresh out of the oven.",
    "Loading... just making sure everything is perfect!",
    "Generating your quote... thanks for your patience!",
    "Almost there... your quote is worth the wait!"
    ];

    // Select a random message from the list
    var randomMessage = loadingMessages[Math.floor(Math.random() * loadingMessages.length)];

    // Log the entire value object to see its structure
    log("Full value object: " + JSON.stringify(value));

    // Ensure value.id is defined before proceeding
    if (!value || !value.id) {
    log("No product selected or value.id is undefined");
    return; // Exit the script quietly since no valid product was selected
    }

    // Show loader
    ZDK.Client.showLoader({ type: 'page', template: 'vertical-bar', message: randomMessage });

    // Extract the product ID and name from the value passed in
    var packageId = value.id;
    var packageName = value.name;
    log("Product ID: " + packageId);
    log("Package Name: " + packageName);

    // Get the subform field from Quotes module
    var quotedItemsSubform = ZDK.Page.getField("Quoted_Items");

    // Fetch product information for the package ID
    var packageDetails = ZDK.Apps.CRM.Auto_Quote_Packages.fetchById(packageId);


    var packageStatus = packageDetails.Status; // Active or Expired.
    var popUpMessage = packageDetails.Pop_Up_Message; // Check the package for any Pop-up message we want to show
    log("Package Details: " + JSON.stringify(packageDetails));
    log("Package Status: " + packageStatus);
    log("Pop-Up Message: " + popUpMessage);

    // Initialize array for existing line items.
    var existingLineItems = quotedItemsSubform.getValue() || [];
    log("Existing line items: " + JSON.stringify(existingLineItems));
    //
    // Only include rows with products. Excude any blank rows from the quote
    var filteredExistingLineItems = existingLineItems.filter(function(item) {
    return item.Product_Name && item.Product_Name.id;
    }).map(function(item) {
    return {
    id: item.Product_Name.id // Include only the item ID
    };
    });
    log("Filtered existing line items: " + JSON.stringify(filteredExistingLineItems));

    // Array to hold new line items we are adding
    var newLineItemArray = [];

    // Check if package is active and populate new line items
    if (packageStatus === "Active") {
    var packageItems = packageDetails.Package_Details;
    packageItems.forEach(function(item) {
    var productLineItem = {
    Product_Name: {
    id: item.Item_Code.id,
    name: `${item.Item_Code.name} (${item.Item_Name})`
    },
    Product_List_Price: item.Item_Price,
    Description: item.Item_Description,
    List_Price: item.Item_Price,
    Quantity: item.Item_Quantity ?? 1, // Default to 1 if Qty is null or undefined
    Discount: Math.abs(item.Item_Discount ?? 0) // Get the discount or default to 0 if null
    };
    log("New product line item: " + JSON.stringify(productLineItem));
    newLineItemArray.push(productLineItem);
    });
    } else {
    // Show error message if the package is not active
    // My layout to only show Active items but if you don't do that this solves it.
    ZDK.Client.showMessage('This package / promo is no longer active. Please contact the admin for details.', { type: 'error' });
    ZDK.Client.hideLoader();
    return; // Exit the script since the package is not active
    }

    // Combine existing line items with new line items
    var updatedLineItemArray = filteredExistingLineItems.concat(newLineItemArray);
    log("Updated line items array: " + JSON.stringify(updatedLineItemArray));

    // Add all updated items to the Quotes page
    quotedItemsSubform.setValue(updatedLineItemArray);

    // Reset the pick list field so user can re-use
    ZDK.Page.getField("Auto_Quote").setValue(null);

    // Hide loader
    ZDK.Client.hideLoader();

    log("Final updated line items: " + JSON.stringify(updatedLineItemArray));

    // Function to show confirmation and number of items added back to the user
    var showSuccessMessage = function() {
    ZDK.Client.showMessage(`${value.name} selected. ${newLineItemArray.length} items added successfully.`, { type: 'success' });
    };

    // Function to show popup message and then success message
    var showAlertAndSuccess = function(message, heading, buttonText) {
    ZDK.Client.showAlert(message, heading, buttonText);
    showSuccessMessage();
    };

    // Check for pop-up message and show alert if it exists
    if (popUpMessage) {
    showAlertAndSuccess(popUpMessage, "Important Information", "Got It!");
    } else {
    // No pop-up message, show the success message
    showSuccessMessage();
    }
    } catch (error) {
    // Log the error
    log('Error: ' + error.message);

    // Show error message
    ZDK.Client.showMessage('An error occurred while adding items. Please try again.', { type: 'error' });

    // Hide loader
    ZDK.Client.hideLoader();
    }

    • Recent Topics

    • Zia expands to China with native features and DeepSeek-powered generative AI features

      Hello everyone, We are glad to support Zia native features and Zia generative AI features for our customers in China. From hereon, all AI-features in Desk will be accessible in China data center with the integration of DeepSeek generative AI model. DeepSeek
    • Email in each module

      We have a contact ,module which then has a link to customer assets which in turn the asset has a multiple link to service visits. When we link assets to customers we choose by name and it brings over the associate email via the lookup. Great feature.
    • Global Search placement in the new UI

      Having a hard time with the global search placement in the UI redesign. Surely I can't be the only one. Previously global search placement was perfect. A bar at the top/center of the page. Exactly where you would expect it to be. Since the new UI has
    • Introducing Skill-Based Ticket Assignment

      The goal of every support team is to provide great support, and to do so as fast as they can. To make this possible, it is important that agents spend their time judiciously, especially when they're dealing with a large number of tickets of varying urgency
    • Kaizen #213 - Workflow APIs - Part 1

      Welcome to another week of Kaizen! If you have ever managed complex business processes, you know that Workflows are the quiet backbone of any well-run business process. They keep things moving; assigning owners, sending alerts, keeping deals on track,
    • Browser and address bar hide

      Hi, How i can do hide the address bar with browser headline when i am working on the sheet, because i am using (freeze panes) which i want visible for full work. For your reference here i am attached the screen shot and marked yellow lines which really
    • Cells Border

      Hi I am using Zoho Sheet on S Tab , is there any option to make all border of any cell at once. I think this is very basic which we are missing. This is available in mobile but not in tab or suggest if i am missing this function. And for Tab can you give
    • Credit Management: #2 Configuring Right Payment Terms for Credit Control

      Think about the last time you ordered something online and saw that little note at the checkout, "Pay on Delivery" or "Pay later". It's simple, but it actually sets the tone. As a business owner, you know exactly when payment is expected. Now, imagine
    • Zobot and Sales IQ

      What will happen to the Zoho Sales IQ being integrated to the website after creating the Zobot on the website too
    • Workflow workdrive rollout

      Hi! When will workflow be rolled out to all users? Thanks.
    • Help Center and SEO: Any Benefit to My Domain-Mapped Website Ranking?

      First of, I love the Help Center which I've just decided to integrate into my website to replace its old-fashioned FAQs. So much more to achieve there now! Lots of new benefits to the site visitors and to me in terms of organizing and delivering all the
    • Blueprint status change

      I want to change the Blueprint status of a workflow. The status is completed automatically when I added the record through API call. But I want to make it active, I don't see any options for this. Even if I draw transition from any stage , it is not visible
    • Support french language options

      Greetings, I want to use Zoho with the french language portal, however the supplied translation is not very good (google translate). There are many basic mistakes on the main most important sections (my requests, submit a request). Is there a way for
    • Automation #7 - Auto-update Email Content to a Ticket

      This is a monthly series where we pick some common use cases that have been either discussed or most asked about in our community and explain how they can be achieved using one of the automation capabilities in Zoho Desk. Email is one of the most commonly
    • filter broke my data

      I uploaded a file recently from Sheets and it has top 2 rows frozen, with table headers in second row and each one is filterable. somehow my first 2 columns became unfiltered and no matter what I do I cannot reapply the filter?? also didn't realize they
    • Introducing the Workflow and Actions APIs for Zoho CRM

      We are absolutely thrilled to announce the release of Workflow APIs and Actions APIs in Zoho CRM’s v8 API suite! This powerful new set of endpoints gives developers unprecedented programmatic control over business automation. For years, Workflow Rules
    • Zoho CRM Analytics - Allow To Reorder Dashboards

      I would like to suggest that you add the ability to reorder dashboards in the Analytics Module. I can see that this has been requested some time ago, the latest 9 years ago. I am not sure if this is a big or small endeavor, but such a small fix can go
    • Zoho Form URL displays incorrect name

      Hi, I have a form I created called "Design Request form". It displays this way everywhere I look. However, in the URL, it shows up as "DesignJobRequestFormFINAL011325PROOFV1B" and I'm not sure why. I can't find where to fix this. Does anyone have any
    • Consumers are talking about your business. Are you listening?👂

      A loyal customer might be praising your product in a forum. A frustrated user could be posting a harsh review on a public site. An excited partner may have left a comment on your campaign. A domain expert might be deconstructing your product. A prospect
    • What counts as a Temp for Billing Purposes in Workerly

      I'm considering trying this product but am not sure how the temp count is used for billing purposes. For example, if we keep a large data base of 500 potential workers.....are we billed for that or only if they are assigned to a client at a given point
    • Form name incorrectly displayed in URL

      Hi, I have a form I created called "Design Request form". It displays this way everywhere I look. However, in the URL, it shows up as "DesignJobRequestFormFINAL011325PROOFV1B" and I'm not sure why. I can't find where to fix this. Does anyone have any
    • I can't receive mail

      Hello, I can't receive e-mail. I no longer receive e-mails to the e-mail I received for ​my site. I also edited the DNS settings, but it doesn't work at all.
    • 1‑to‑1 invite missing post-setup (needs re-invite) vs channel invite auto-joins without business prompt

      1. Zoho Cliq 1‑to‑1 external invite The inviter sent a 1‑to‑1 invite to an invitee who didn’t have a Cliq account. After the invitee completed account setup and created a business/organization, the website redirected them to Cliq, where they opened Cliq
    • 【開催報告】東京 ユーザー交流会 Vol.3 2025/10/17 Zoho サービスの活用促進を外部ツールとの連携で実現!

      ユーザーの皆さま、こんにちは。コミュニティチームの藤澤です。 10月17日(金)に新橋で「東京 ユーザー交流会 Vol.3」を開催しました。ご参加くださったユーザーの皆さま、ありがとうございました! この投稿では、当日のセッションの様子や使用した資料を紹介しています。残念ながら当日お越しいただけなかった方も、ぜひチェックしてみてください😊 ユーザー活用事例セッション:Zoho Flowと決済システムの連携 あみろくの岡島さんに、Zoho サービスの活用事例として、Zoho Flow を活用した外部サービスとの連携事例をご共有いただきました。
    • received email opens in a new tab every time I log in

      as per the title: since about when I first made my email account, every single time Ive logged in to view my inbox, a new tab opens for an email I viewed once as if restoring a closed session. I thought I just didnt understand the "starting up" settings
    • Engage with your customers at scale using WhatsApp Marketing Template messages

      Hi everyone, To make it easier for organizations to communicate with customers, Desk now allows you to send individual, mass, and bulk WhatsApp template messages from both the Ticket and Contact modules. How is this going to benefit your business? WhatsApp
    • Importation Tickets error

      Hi, I'm newbie here 🤓 So, i'm importing data from csv, but when I try advance to mapping fields the importer tool show this message: Previously I try import, other data, and not show errors in this step. Some ideas? Best Regards,
    • Showing description in timesheet and timelogs.

      I am wondering if it’s possible in version 5 of Zoho People to have the description show by default or with a manipulation on the user’s part. Let me show you what I mean. As you can see this is the view for the users. Now if they want to see the full
    • 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
    • Add Flexible Recurrence Options for Meeting Scheduling in Zoho Cliq (e.g., Every 2 Weeks)

      Hello Zoho Cliq Team, We hope you are doing well. Currently, when scheduling a meeting inside Zoho Cliq, the recurrence options are limited to Daily, Weekly, Monthly, and Yearly. There is no ability to set a meeting to occur every X weeks — for example,
    • Workaround: openURL in Blueprints - An alternate approach

      There is a roundabout way to open a URL in blueprints after a save event. By using the 'onBeforeMandatoryFormSave' in Client Script, you can open an external URL. Now, the problem is, this is designed to be run BEFORE the blueprint is saved, not after,
    • MTD SA in the UK

      Hello ID 20106048857 The Inland Revenue have confirmed that this tax account is registered as Cash Basis In Settings>Profile I have set ‘Report Basis’ as “Cash" However, I see on Zoho on Settings>Taxes>Income Tax that the ‘Tax Basis’ is marked ‘Accrual'
    • Migrate file from Single File Upload to Multi File Upload

      Dears, I have created a new field Multi File Upload to replace the old Single File Upload field. I'd like to ask you guys what is the best way to migrate the files to the new field?
    • Open "Live Chat" from a hyperlink?

      Hi, I often write paragraphs and text on our company website, and usually say you can get in touch with us via live chat. Can the chat window be triggered to pop open without clicking the chat graphic in the bottom window, and use it in a hyperlink? ie:
    • Zoho Sites search box

      Is there a Search box that can be added to a Zoho site? It would be for searching within the site only.
    • What stops me from packaging and shipping an order when the inventory is negative?

      It seems if the inventory value is negative, that Zoho Inventory should not allow me to create a Package and Ship it.   But, there seems to be nothing to stop me from doing that other than when I go to physically package the item and realize that there is no stock. There also seems to be nothing on the screen that even indicates to me that I should not package and ship.  To me this is the fundamental point of an inventory system.  Am I doing something wrong?   
    • Conditional formatting based on another field

      Hi I have two fields on my form stage 1 complete and stage 1 deadline.  I am trying to setup conditional formatting so that if stage 1 complete is after stage 1 deadline the record is highlighted in red. I need both stage 1 complete and stage 1 deadline
    • Is there API Doc for Zoho Survey?

      Hi everyone, Is there API doc for Zoho Survey? Currently evaluating a solution - use case to automate survey administration especially for internal use. But after a brief search, I couldn't find API doc for this. So I thought I should ask here. Than
    • Using IMAP configuration for shared email inboxes

      Our customer service team utilizes shared email boxes to allow multiple people to view and handle incoming customer requests. For example, the customer sends an email to info@xxxx.com and multiple people can view it and handle the request. How can I configure
    • The sending IP (136.143.188.15) is listed on spamrl.com as a source of spam.

      Hi, it just two day when i am using zoho mail for my business domain, today i was sending email and found that message "The sending IP (136.143.188.15) is listed on https://spamrl.com as a source of spam" I hope to know how this will affect the delivery
    • Next Page