[SalesForce] How to calculate Custom TotalPrice in OpportunityLineItem

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

Best Answer

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

Related Topic