function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SarikaPSarikaP 

Based on one field value in lineitem update values in the same field of other lineitem using onchange event

Hello Everyone,
I am having a field called Discount Percent at quotelineitem. 
If a quotelineitem is of a specific Product Category and there are many quotelineitems of the same product category, when discount % is applied to one lineitem of that product category in an onchange event automatically the discount percent should be applied to all lineitems of the same product category. 
Could anyone suggest how to do that? 
Thanks
 
Best Answer chosen by SarikaP
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
I also introduced a wrapper into my version.  Instead of passing the QLI ID as a parameter, the page now passes the index of the wrapper.  Let me know how it works for you.
<apex:page standardController="Quote" extensions="QuotePageController" docType="html-5.0">
<apex:form>
    <apex:sectionHeader title="Quote" subtitle="{!Quote.Name}"/>
    <apex:pageBlock title="Quote Detail" mode="detail" >
        <apex:pageBlockSection title="Quote Line Items" columns="1" >
            <apex:pageBlockTable value="{!quoteLineItems}" var="wrapper" id="qliTable">
                <apex:column
                    headerValue="{!$ObjectType.QuoteLineItem.Fields.LineNumber.Label}"
                    value="{!wrapper.qli.LineNumber}"
                />
                <apex:column
                    headerValue="{!$ObjectType.Product2.Fields.Name.Label}"
                    value="{!wrapper.qli.Product2.Name}"
                />
                <apex:column
                    headerValue="{!$ObjectType.Product2.Fields.Family.Label}"
                    value="{!wrapper.qli.Product2.Family}"
                />
                <apex:column headerValue="{!$ObjectType.QuoteLineItem.Fields.Discount.Label + ' (%)'}" >
                    <apex:inputField value="{!wrapper.qli.Discount}" >
                        <apex:actionSupport event="onchange" action="{!changeDiscount}" reRender="qliTable" >
                            <apex:param name="qliIndex" value="{!wrapper.index}" assignTo="{!qliIndex}"/>
                        </apex:actionSupport>
                    </apex:inputField>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:form>
</apex:page>
 
public class QuotePageController
{
    private Quote quote;

    public QuotePageController( ApexPages.StandardController standardController )
    {
        quote = (Quote) standardController.getRecord();
    }

    public List<QLIWrapper> quoteLineItems
    {
        get
        {
            if ( quoteLineItems == null )
            {
                quoteLineItems = new List<QLIWrapper>();
                for ( QuoteLineItem qli :
                    [   SELECT  Id, LineNumber, Discount, Product2.Name, Product2.Family
                        FROM    QuoteLineItem
                        WHERE   QuoteId = :quote.Id
                    ]
                    )
                {
                    quoteLineItems.add( new QLIWrapper( qli ) );
                }
            }
            return quoteLineItems;
        }
        private set;
    }

    public Integer qliIndex     { get; set; }

    public void changeDiscount()
    {
        QuoteLineItem changedQLI = quoteLineItems[ qliIndex ].qli;
        String family = changedQLI.Product2.Family;
        Decimal discount = changedQLI.Discount;
        List<QuoteLineItem> qlisToUpdate = new List<QuoteLineItem>();
        for ( QLIWrapper wrapper : quoteLineItems )
        {
            if ( wrapper.qli.Product2.Family != family ) continue;
            wrapper.qli.Discount = discount;
            if ( wrapper.qli.Id != null ) qlisToUpdate.add( wrapper.qli );
        }
        update qlisToUpdate;
    }

    public class QLIWrapper
    {
        public Integer index        { get { quoteLineItems.indexOf( this ); } }
        public QuoteLineItem qli    { get; set; }
        QLIWrapper( QuoteLineItem qli ) { this.qli = qli; }
    }
}

 

All Answers

Glyn Anderson (Slalom)Glyn Anderson (Slalom)
Is this in a Visualforce page?  Or a Lightning Component?  Are the QLI's in memory/viewstate?  Or are they in the database?

The basic idea would be to iterate through your collection of QLI's and change the Discount Percent of any that have the same Product Category as the changed QLI.  I can't show example code until you answer the questions above.  Also, if you can post relevant parts of your existing code, that would help.
SarikaPSarikaP
Hello Glyn, yes its a visualforce page. The Qli's can be in viewstate or in database but when updated in an onchange event the field values should be updated. The issue is if i update its taking the value but only the first time, later if i try to update another value it takes again the previous value even though the previous value has not been saved in database its runtime. 
SarikaPSarikaP
Infact how to know which lineitem's discount has been changed
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
I'm working on an example.  It might take a while.  Stay tuned.
SarikaPSarikaP
Thanks a lot! Also one more thing I think I am close, its mainly I need to get the quotelineitem whose discount percent is updated. But its giving me null. Trying to figure that out. Hopefully I am in right direction :)
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
OK.  Got it.  This VF page will display the QLIs of a Quote, with an editable Discount field.  Whenever a Discount is changed, it invokes the controller extension, which updates the Discount on all QLIs whose Products are in the same Product Family of the QLI that changed.  It persists these changes in the database.

This is just an example.  I hope you can incorporate the techniques into your actual page.  Let me know if you have questions.

The Visualforce page:
<apex:page standardController="Quote" extensions="QuotePageController" docType="html-5.0">
<apex:form>
    <apex:sectionHeader title="Quote" subtitle="{!Quote.Name}"/>
    <apex:pageBlock title="Quote Detail" mode="detail" >
        <apex:pageBlockSection title="Quote Line Items" columns="1" >
            <apex:pageBlockTable value="{!quoteLineItems}" var="qli" id="qliTable">
                <apex:column
                	headerValue="{!$ObjectType.QuoteLineItem.Fields.LineNumber.Label}"
                    value="{!qli.LineNumber}"
                />
                <apex:column
                	headerValue="{!$ObjectType.Product2.Fields.Name.Label}"
                    value="{!qli.Product2.Name}"
                />
                <apex:column
                	headerValue="{!$ObjectType.Product2.Fields.Family.Label}"
                    value="{!qli.Product2.Family}"
                />
                <apex:column headerValue="{!$ObjectType.QuoteLineItem.Fields.Discount.Label + ' (%)'}" >
                    <apex:inputField value="{!qli.Discount}" >
                        <apex:actionSupport event="onchange" action="{!changeDiscount}" reRender="qliTable" >
                            <apex:param name="qliId" value="{!qli.Id}" assignTo="{!qliId}"/>
                        </apex:actionSupport>
                    </apex:inputField>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:form>
</apex:page>
The controller extension class:
public class QuotePageController
{
	private Quote quote;

	public QuotePageController( ApexPages.StandardController standardController )
    {
        quote = (Quote) standardController.getRecord();
    }

	public List<QuoteLineItem> quoteLineItems
    {
        get
        {
            if ( quoteLineItems == null )
            {
                quoteLineItems =
                (	[	SELECT	Id, LineNumber, Discount, Product2.Name, Product2.Family
                    	FROM	QuoteLineItem
                     	WHERE	QuoteId = :quote.Id
	                ]
                );
            }
            return quoteLineItems;
        }
        private set;
    }

    public Id qliId		{ get; set; }

	public void changeDiscount()
    {
        Map<Id,QuoteLineItem> qlis = new Map<Id,QuoteLineItem>( quoteLineItems );
        QuoteLineItem changedQLI = qlis.get( qliId );
        String family = changedQLI.Product2.Family;
        Decimal discount = changedQLI.Discount;
        List<QuoteLineItem> qlisToUpdate = new List<QuoteLineItem>();
        for ( QuoteLineItem qli : quoteLineItems )
        {
            if ( qli.Product2.Family != family ) continue;
            qli.Discount = discount;
            qlisToUpdate.add( qli );
        }
        update qlisToUpdate;
    }
}
SarikaPSarikaP
Thanks Glyn for your prompt response. I was able to do it successfully. Its just that I was passing parmater for quotelineitem id after actionsupport.But now all good. 
SarikaPSarikaP
Hello Glyn, not sure why not able to get quotelineitem id when I am trying to add the lineitems. But if they are already saved I am able to get the qliId. Any suggestion how to get qliId  when lineitems are not  yet saved
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
If you are creating new QLI's, they won't have IDs until they are actually inserted into the database.  The code I provided assumes that all the QLIs have IDs (i.e. they came from the database).  If you need to have QLIs without IDs, then we'll have to rewrite the page and the controller to identify QLIs by something other than their ID.  I have an idea, but it might take me awhile to change the code.
SarikaPSarikaP
Yes Glyn agreed. That's why I am getting null values for the new quotelineitems that are not yet saved in database. Also I have a wrapper class for quotelineitem. You can also let me know your thought in the meanwhile if you can until you finish your code. I can try till then, if that's fine.
Thanks in advance for helping me out!
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
I also introduced a wrapper into my version.  Instead of passing the QLI ID as a parameter, the page now passes the index of the wrapper.  Let me know how it works for you.
<apex:page standardController="Quote" extensions="QuotePageController" docType="html-5.0">
<apex:form>
    <apex:sectionHeader title="Quote" subtitle="{!Quote.Name}"/>
    <apex:pageBlock title="Quote Detail" mode="detail" >
        <apex:pageBlockSection title="Quote Line Items" columns="1" >
            <apex:pageBlockTable value="{!quoteLineItems}" var="wrapper" id="qliTable">
                <apex:column
                    headerValue="{!$ObjectType.QuoteLineItem.Fields.LineNumber.Label}"
                    value="{!wrapper.qli.LineNumber}"
                />
                <apex:column
                    headerValue="{!$ObjectType.Product2.Fields.Name.Label}"
                    value="{!wrapper.qli.Product2.Name}"
                />
                <apex:column
                    headerValue="{!$ObjectType.Product2.Fields.Family.Label}"
                    value="{!wrapper.qli.Product2.Family}"
                />
                <apex:column headerValue="{!$ObjectType.QuoteLineItem.Fields.Discount.Label + ' (%)'}" >
                    <apex:inputField value="{!wrapper.qli.Discount}" >
                        <apex:actionSupport event="onchange" action="{!changeDiscount}" reRender="qliTable" >
                            <apex:param name="qliIndex" value="{!wrapper.index}" assignTo="{!qliIndex}"/>
                        </apex:actionSupport>
                    </apex:inputField>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:form>
</apex:page>
 
public class QuotePageController
{
    private Quote quote;

    public QuotePageController( ApexPages.StandardController standardController )
    {
        quote = (Quote) standardController.getRecord();
    }

    public List<QLIWrapper> quoteLineItems
    {
        get
        {
            if ( quoteLineItems == null )
            {
                quoteLineItems = new List<QLIWrapper>();
                for ( QuoteLineItem qli :
                    [   SELECT  Id, LineNumber, Discount, Product2.Name, Product2.Family
                        FROM    QuoteLineItem
                        WHERE   QuoteId = :quote.Id
                    ]
                    )
                {
                    quoteLineItems.add( new QLIWrapper( qli ) );
                }
            }
            return quoteLineItems;
        }
        private set;
    }

    public Integer qliIndex     { get; set; }

    public void changeDiscount()
    {
        QuoteLineItem changedQLI = quoteLineItems[ qliIndex ].qli;
        String family = changedQLI.Product2.Family;
        Decimal discount = changedQLI.Discount;
        List<QuoteLineItem> qlisToUpdate = new List<QuoteLineItem>();
        for ( QLIWrapper wrapper : quoteLineItems )
        {
            if ( wrapper.qli.Product2.Family != family ) continue;
            wrapper.qli.Discount = discount;
            if ( wrapper.qli.Id != null ) qlisToUpdate.add( wrapper.qli );
        }
        update qlisToUpdate;
    }

    public class QLIWrapper
    {
        public Integer index        { get { quoteLineItems.indexOf( this ); } }
        public QuoteLineItem qli    { get; set; }
        QLIWrapper( QuoteLineItem qli ) { this.qli = qli; }
    }
}

 
This was selected as the best answer
SarikaPSarikaP
Thanks Glyn for your prompt response. The thought of adding index really helped.