2

I have an scenario where I want an custom calculation for field "Totalprice" on OpportunityLineItem. I have written a trigger on OpportunityLineItem where first I am setting the UnitPrice value on Before Insert trigger. Then updating the TotalPrice. My Totalprice formula is

TotalPrice = (ListPrice * Quantity * (100 - Discount_override__c)) / 100

Below is my code which I have tried.

trigger OpportunityLineItemTrigger on OpportunityLineItem (before insert, after insert, after update) {

  if(Trigger.isBefore && Trigger.isInsert){
    list<OpportunityLineItem> oppLineitmLst = new list<OpportunityLineItem>();
    for (OpportunityLineItem oppLineitem : Trigger.new) {

        if(oppLineitem.Product_Family__c  == 'Incp'){
            oppLineitmLst.add(oppLineitem);
        }
    }
    OpportunityLineItem_Handler.UpdateFieldsForNotFixedPriceProducts(oppLineitmLst);

   }
   if(Trigger.isAfter && Trigger.isInsert){
    if(OpportunityLineItem_Handler.isFirstUpdate) {
         System.debug('TriggerAfterInsert ' +Trigger.New);
        list<OpportunityLineItem> oppLineitmLst = new list<OpportunityLineItem>();
        for (OpportunityLineItem oppLineitem : Trigger.new) {

            if(oppLineitem.Product_Family__c  == 'Incp'){
                oppLineitmLst.add(oppLineitem);
            }
        }
        OpportunityLineItem_Handler.UpdateTotalPriceForNotFixedPriceProductsAfterInsertUpdate(oppLineitmLst, trigger.oldMap);
    }

  }
}

And the handler class for Trigger

public with sharing class OpportunityLineItem_Handler {
    public static Boolean isFirstUpdate = true;
    public static void UpdateFieldsForNotFixedPriceProducts(list<OpportunityLineItem> triggerNew){


        for (OpportunityLineItem oli :triggerNew){
             Opportunity oliOpp = triggerNewOpps.get(oli.OpportunityId);

             if(oliOpp.ResellerName__c != null 
           && oliOpp.Reseller__r.incp_Partner_Default_Discount__c != null 
           && oliOpp.Reseller__r.incp_Partner_Default_Discount__c != 0
          && !oli.INCP_Fixed_Price__c)
             {
                 System.debug(' inside discount override');
                 oli.Discount_Override__c = oliOpp.Reseller__r.incp_Partner_Default_Discount__c;
                 System.debug('discout override ' + oli.Discount_Override__c  );
                 if(oli.Product2.Incp_Annual__c){
                     oli.UnitPrice = oli.ListPrice;
                 }else{
                     oli.UnitPrice = oli.ListPrice * oli.incp_Months__c;
                 }
                 System.debug('oli.UnitPrice ' + oli.UnitPrice + 'TotalPrice ' + oli.TotalPrice );
           } 
       }

    }
    public static void UpdateTotalPriceForNotFixedPriceProductsAfterInsertUpdate(list<OpportunityLineItem> triggerNew, map<Id,OpportunityLineItem> triggerOldMap){
    OpportunityLineItem_Handler.isFirstUpdate = false;

        for (OpportunityLineItem oli :filteredList){
            OpportunityLineItem oldOli = trigger.isUpdate ? triggerOldMap.get(oli.Id): null;

            if(trigger.isAfter){
                  OpportunityLineItem o = oli.clone(true, true, true, true);
                  o.TotalPrice = (oli.ListPrice * oli.Quantity * (100 - oli.Discount_override__c)) / 100;                           
                  OppLIsForUpdate.add(o);                   
            }
       }
       if(OppLIsForUpdate != null && !OppLIsForUpdate.isEmpty()) {
           update OppLIsForUpdate;
       }
    }
}

Suppose my ListPrice is $100, Quantity is 10 and discount is 25%. In the above scenario, UnitPrice should be $1000 and Total price should $750. But in My scenario Unitprice is getting update from $1000 to $750 after the trigger is executed.

I have checked all the workflow rules, process builder, trigger etc. But still didn't understood why UnitPrice is getting updated. If anyone can help me then It would be great. Please let me know if anything is required from my side and please ignore the typo mistakes.

Edited - Adding an screen shot from old sandbox where Unitprice is (Listprice * Months) and TotalPrice = (UnitPrice * Quantity * (100 - discount_override__c)) / 100

enter image description here

2

The way OLIs work, TotalPrice and UnitPrice are joined at the hip.

When you update UnitPrice, the TotalPrice is calculated by doing Unit * Qty. When you update TotalPrice, the UnitPrice is calculated by doing Total / Qty.

In fact, that is why you can't update both UnitPrice and TotalPrice at the same time. You get an error (try it!)

So, on your second update, you're basically reverting your Unit to have the discount applied.

I would let Unit and Total stay in sync and create custom fields that have the undiscounted amount.

You can find documentation of this behavior by going to the corresponding fields here

  • Yes but we have an old sandbox where total price is calculated based on the given formula and Unit Price remains same(undiscounted). I have copied the same code from old sandbox and pasted in new one but it did not worked on new but it is working in Old one. – Nupur Bhagat Oct 3 '18 at 21:10
  • I have added the screenshot in main post from the old sandbox. – Nupur Bhagat Oct 3 '18 at 21:16
  • I can't comment on your sandbox. It's entirely possible it is using custom fields. The standard fields operate as I described. But please also remember that there is a Discount standard field, and it behaves as you expect your custom solution to work. I urge you to read the document I linked. – Sebastian Kessel Oct 4 '18 at 0:22
  • Yes even searching for more than 5-6 hours I am still not able to find it. I am sure that it is an Standard UnitPrice field and Standard TotalPrice field used. and the discount which you are seeing is the custom field. I know there is a Standard field Discount by which I can get the expected behavior. I will try to dig little bit more on this why it is different. Thanks for your help.. – Nupur Bhagat Oct 4 '18 at 5:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.