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

    • Samsung Keyboard Issues with Notebook

      Dear Users, We're sorry to inform you that some of our users are experiencing certain issues like scrolling, delay/lag, cursor placement especially within the text notes. This occurs mainly due to Samsung Keyboard compatibility with Android 13 and some
    • Zoho Books | Product updates | October 2025

      Hello users, We’ve rolled out new features and enhancements in Zoho Books. From iOS 26 updates to viewing reports as charts, explore the updates designed to enhance your bookkeeping experience. Zoho Books Updates for Apple Devices At WWDC 2025, Apple
    • Zoho Developer Community Hackathon 2025 is LIVE!

      Hey developers! It’s that time of the year again — the Zoho Developer Community Hackathon 2025 is officially open for registrations! If you’ve been waiting for a chance to stretch your skills, try something new, or finally bring that idea to life, this
    • Zoho Books | Product updates | September 2025

      Hello users, We’ve rolled out new features and enhancements in Zoho Books. From PayNow payment method to applying journal credits to invoices and bills in other locations, explore the updates designed to enhance your bookkeeping experience. Integrate
    • Zoho Workdrive for Office, "vsto runtime not found"

      Hi all, I have been trying to get ZohoWorkdrive_MS-addin_1.4.exe installed, but I keep getting the error "VSTO Runtime Not Found!" - even though I have installed it ... Anyone else hear had problems with the MS addin?  FYI, I am using O365 on A Dell laptop running Win 10 Home - fully patched and up-to-date.  I have tried compatibility modes and running explicitly as Administrator - the usual steps. Any advice would be appreciated.
    • Add "Fetch Composite Item" Action for Inventory

      I want to make a Flow that uses information returned in the GET call for Composite Items, and it's not currently available in Zoho Flow. Please consider adding this functionality.
    • Inactive Items - Make Less Prominent by Default

      Currently, when one marks an Item as "Inactive", it really doesn't do much of anything to hide it or get it out of the way. Search and reporting within Finance should, by default, hide inactive Items from standard reports, searches, etc. If one specifically
    • Can no longer export as pdf

      In NOTEBOOK I am no longer able to export notes to pdfs as I used to be able to. When I hit that command it asks where I want to send it, but no matter what I chose there is no pdf attachment that shows up in order to send. Nothing happens.
    • Emails are going to notification folder and not in inbox

      emails are going to notification folder and not into inbox
    • How can I prevent the Zoho Vault extension from automatically logging me out?

      Hi, I want the Zoho Vault Chrome extension to never log out. How can I do this? It only allows me to log out for 1 week, and the same applies to the Android app.
    • Zoho CRM App - Links

      Hi  Is there are plan for making Custom Links available in the Zoho CRM Android App? I can't see them being added? Thanks Gene
    • Templates

      Trying to sort out / get rid of unwanted invoice templates, the error msgs are not at all helpful. Surely it's easy to amend the error msg by including a list of the names of the customers / vendors that use it, denying deletion or making it inactive
    • Contacts limit in basic vs standard - what counts? Are customers contacts?

      I’ve been using books for a number years for my small business. I only ever work with 20 clients at any given time. I do purchase services from a number of vendors to run my business, so there are some comtacts there too. I used to use the basic package,
    • Finding missing records

      I have a challenge and I am not really sure where to start with it. I can't find any similar threads on here, can anyone help: I have two forms, FormA and FormB. Both forms have records that contain a field called Job_Number. What I am trying to achieve
    • Prevent Unapproved Quotes from Exporting to Zoho CRM Finance Module

      Is it possible to prevent unapproved quotes in Zoho Books from being exported from Zoho Finance module inside Zoho CRM?
    • ZOHO BOOKS - RECEIVING MORE ITEMS THAN ORDERED

      Hello, When trying to enter a vendor's bill that contains items with bigger quantity than ordered in the PO (it happens quite often) - The system would not let us save the bill and show this error: "Quantity recorded cannot be more than quantity ordered." 
    • Updates for Zoho Campaigns: Merge tag, footer, and autoresponder migration

      Hello everyone, We'd like to inform you of some upcoming changes with regard to Zoho Campaigns. We understand that change can be difficult, but we're dedicated to ensuring a smooth transition while keeping you all informed and engaged throughout the process.
    • Process between CRM and Campaigns to ensure double opt-in contacts?

      I would like to ask for a few clarifications to ensure we fully comply with best practices and legal requirements: According to the documentation (Zoho Campaigns CRM sync – Default option), the best and recommended way to sync contacts is by using the
    • What's New in Zoho Inventory | August – October 2025

      Hello customers, The last quarter has been incredibly productive! We've released a powerful slate of new features and enhancements in Zoho Inventory designed to give you better control, greater efficiency, and expanded functionality across your inventory
    • Search not working!

      I have items in my notebook tagged but when I search for a tag nothing comes up! Any fix for this?
    • Let's Talk Recruit: Meet Zia, your all-in-one AI assistant (Part-2)

      Welcome back to Let’s Talk Recruit series. In Part 1, we introduced Zia and how AI is reshaping the way recruiters work. This time, we’re taking a closer look at how far Zia has come and how each update continues to simplify your everyday tasks. When
    • Zoho Developer - Feature Request Platform

      Zoho Developer is one of the most underatted platform in zoho ecosystem, however, it may just be what zoho needs to welcome more people to use Zoho Services. The more developers you have creating zoho creator applications and zoho extensions the more
    • Last/Previous month in relative date filter

      In the relative date filter, what is the difference between "Last 2 months" and "Previous 2 months"? So, if we are on 25-July, then is my understanding correct of the following: Last 2 months :=:      25-May~24 July Previous 2 months :=:     01-May~30-June Thanks.
    • Tags get removed from notes on mobile

      I don't know why this keeps happening even after all these app updates but if you log out and log back into the app or you reinstall it, all the tags you assigned to your notes get taken off, but if you go on the desktop version the tags are still there.
    • Show Zoom Link in Recipient's Calendar

      We set up meetings within a record, selecting the "Make this an online meeting".  We use Zoom. Most of the recipients go to their calendar (usually Gmail or Outlook, corporate) to join the Zoom meeting, but there is no Zoom link in the calendar. Can this
    • How to fetch custom fields for time entries in Zoho Project API v3

      In the previous Zoho Projects REST API, we were able to retrieve custom field details for time entries, including picklist options, using the endpoint: GET /restapi/portal/[PORTAL_ID]/timesheetcustomfields In the new Zoho Projects API v3, we tried using
    • VAT rates - exempt and out of scope

      Good Evening, UK based company here. I am a bit confused in respect of setting up VAT rates for exempt goods and services; at present I am simply leaving the VAT rate blank in the transactions in order to prevent any VAT appearing in the VAT return. When
    • Zoho is blocking emails I subscribe to from one sender

      About 4 months ago I stopped receiving newsletters that I subscribe to from @thedispatch.com. They tell me that zoho's server is blocking them. I've added them to my contacts list, but they're not even reaching my inbox. I don't know how to troubleshoot
    • Introducing Lead Capture: Empower exhibitors to capture leads effortlessly

      Events provide a great opportunity for exhibitors to generate awareness and engage with potential customers. Efficiently distributing attendee information to exhibitors through a seamless and secure way is of paramount importance. Introducing Lead Capture
    • Work Order Creation Issue

      Dear Team, I would like to inquire about the daily limit for Work Order creation in Zoho FSM. Yesterday (02/05/2025) at around 6:30 PM GST, I attempted to create a Work Order, but I have been unable to do so since then. Please find the attached image
    • Accessing shared mailboxes through Trident (Windows)

      Hi, I have a created a couple of shared mailboxes. The mailboxes are showing up on the browser based Zoho workplace, but I cannot seem to figure out how to access my shared inboxes through Trident (Windows). Am I missing something or is this feature not
    • URGENT: ChatGPT Extension Failing With “gpt-3 Access Error” (Priority Support)

      Appreciate support reviewing this urgently. I am a Priority Support member and need immediate clarification on a recurring issue involving the ChatGPT extensions inside Zoho Desk. Both extensions — including the version created and published by Zoho —
    • Zoho Desk iOS update: Custom buttons, follow/ unfollow option on tickets

      Hello everyone! In the most recent Zoho Desk iOS app update, we have brought in support to access the custom buttons configured on web app(desk.zoho.com). Using custom buttons you can seamlessly execute predefined actions directly from their mobile devices,
    • Zoho pdf suit

      Pl. design products with following feature: 1. Please add all features given in Ilovepdf website to work on pdf files. It is mandatory to use pdf in court work. 2. Courts have prescribed New Times Roman, pl. add this font as well 3. Indexing, signature
    • Zoho Not Working

      Today Zoho not wokring
    • Dynamically autofill fields with URL parameters

      I have a zoho form embedded in my organization's WP website. Our users find their account with a search tool, and then can select to open this page with the embedded form. The URL of the page holds the parameter that I need, but I cannot figure out how
    • User Automation: User based workflow rules & webhooks

      User management is an undeniable part of project management and requires adequate monitoring. As teams grow and projects multiply, manual coordination for updating users & permissions becomes difficult and can give way to errors. User automation in Zoho
    • Integrate Projects for Desk KB article release tasks

      Could you please look into the possibility of integrating project tasks for Zoho Desk article release processes? We are looking for an internal integration between Zoho Projects and Zoho Desk's KB article drafting, reviewing and releasing tasks. We could
    • Issue in Annual Leave

      We created a policy to credit 21 days at the Start of the Year An employee has taken 16 days of leaves thought the year, so we expect to see 5 Leaves remaining right? But Zoho People is Showing 12 Days of Leave Balance Available If we check the Leave
    • Use the searchBy parameter to find user by email address

      I'm trying to find a user is Zoho Desk via the Api. In the documentation I see that there is the possibility to add a searchBy parameter in the request. But I can't find how the search values should be formatted. I've tried multiple things and get either
    • Next Page