--- title: "Custom Quote Action" slug: "custom-quote-action" description: "Learn how to add a business-specific button to the quote detail screen. When users select this button, your script runs automatically to perform a defined task or workflow." updated: 2026-06-02T12:00:33Z published: 2026-06-02T12:00:33Z canonical: "docs.zilliant.com/custom-quote-action" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.zilliant.com/llms.txt > Use this file to discover all available pages before exploring further. # Custom Quote Action ## Purpose Allows you to add a business-specific button to the quote detail screen. When users select this button, your script runs automatically to perform a defined task or workflow. This functionality allows you to execute specialized processes directly from a quote, such as exporting quote data to an external system, sending a quote for custom approval, or triggering a company-specific integration. ## Setup Follow these steps: 1. [Upload a script.](/main/docs/custom-quote-action#upload-a-script) 2. [Enable the script and custom button.](/main/docs/custom-quote-action#enable-the-script-and-custom-button) ### Upload a script Upload a script for **Custom Quote Action**. For details about uploading and configuring Groovy scripts, read [Upload a Groovy script](/main/docs/upload-a-groovy-script). ### Enable the script and custom button 1. From the application left navigation area, select **Administration**. 2. From the top navigation bar, select **Master Data Management**. 3. Move through or search to locate **Setting Boolean** and select it from the list. 4. Select **Enable Custom Quote Action**. 5. Set the **Setting Value Boolean** switch to **YES**. 6. Select **Save**. The **Custom Quote Action** button appears in the **Actions** dropdown in [quotes](/main/docs/manage-quotes#open-quotes). By default, the button is hidden. To configure it: - In the Classic view—Manage both the button label and any UI profile–based restrictions through the **UI Customization** screen. - In the New UI—Read [Customize actions](/main/docs/customize-actions) for instructions on configuring and managing the button. ## Binding variables In addition to the [common binding variables](/main/docs/binding-variables), the following binding variables are available for this extension point. | Variable name | Class | Description | | --- | --- | --- | | salesItemsTree | SalesItemsTree | Represents the quote. It contains the functions you can use to query and modify the quote and its line item data. | | accountInfo | AccountInfo | Basic data about the account, including its address. | | userInfoList | Set | List of all users in the system. | | sourceQuotePFRecords | Set | List of partner function records in the quote. If the script is triggered due to the quote copy action, the system populates this variable with information about the source quote’s partner functions. | | accountPFRecords | List | List of partner function records for the account of the quote. | For details about the classes listed in this table, including available methods, fields, and method signatures, read the [Zilliant Groovy API reference](/main/docs/groovy-api-reference). ## Expected output The script should return one of the following Boolean values: - **True**—Script ran successfully. - **False**—Error occurred while executing the script. ## Script execution A script that you upload for this extension point runs automatically when users select the **Custom Quote Action** button from the **Actions** dropdown button in [quotes](/main/docs/manage-quotes#open-quotes). ## Sample script ```groovy // Import necessary classes for the script import com.imc.vocabulary.Schema import com.imc.iss.groovy.salesitem.SalesItemsTree import com.imc.iss.groovy.salesitem.SalesItemNode System.out.println('Script Execution: SalesItemsTree Started'); def quoteTitle = salesItemsTree.getQuoteDataAttributeValue(Schema.objectName.getUriAsString()); System.out.println('Quote URI:- ' + salesItemsTree.getQuoteURI()); System.out.println('Quote Title: ' + quoteTitle); for (SalesItemNode salesItemNode: salesItemsTree.getChildren()) { accessSalesItem(salesItemNode); } void accessSalesItem(SalesItemNode salesItemNode) { def position = salesItemNode.getSalesItemDataAttributeValue(Schema.salesItemPosition.getUriAsString()); def ihQuantity = salesItemNode.getSalesItemDataAttributeValue(Schema.itemHeaderQuantity.getUriAsString()); System.out.println('itemHeaderQuantity at ' + position + ' : ' + ihQuantity);    List salesItemNodes = salesItemNode.getChildren();    for (SalesItemNode child: salesItemNodes) {        accessSalesItem(child);    } } return true; ```