0

I have a VFP using which I upload a CSV file with several columns that consists of both OpportunityLineItem and its schedule related info. However, when I'm trying to upload the sheet, it is hitting the CPU limit & causing an error. Reason being upsert on an OppLineItem or OppLineItemSchedule triggers the parent Opportunity. However, I tried to upload the sheet by pausing the Opportunity Trigger just to observe the timeframe on the logs - but still see the same CPU exception. Wanted to share this here to get the expert inputs & eyeball the cause that might have slipped from my radar.

VFP:

<apex:page standardController="Opportunity" extensions="OpportunityLineItemCSVdmlController_AC">
<apex:form id="myForm">
    <apex:pagemessages escape="false"/>
    <apex:pageBlock >
        <apex:pageBlockSection columns="3"> 
            <apex:inputFile value="{!csvFileBody}"  filename="{!csvFileName}"/>
            <apex:pageblockSectionItem >
                <apex:outputLabel value="Plan Version"/>
                <apex:selectList id="PlanVersion" value="{!planVersionSetValue}" size="1" required="true">
                    <apex:selectOptions value="{!PlanVersion}"/>
                </apex:selectList>
            </apex:pageblockSectionItem>
            <apex:pageblockSectionItem >
                <apex:commandButton value="Import Opportunity Product" action="{!OliCSVFileImport}" onclick="alertBox()"/>
                <apex:actionRegion >
                    <apex:commandButton value="Delete" action="{!OliDelete}" rendered="{!IF($Profile.Name == 'SM SysAdmin',true,false)}" status="status" reRender="myForm"/>
                </apex:actionRegion>
            </apex:pageblockSectionItem>
        </apex:pageBlockSection>
    </apex:pageBlock>
    <apex:actionStatus id="status">
            <apex:facet name="start">
                <div style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; opacity: 0.25; z-index: 1000; background-color: black;">
                    &nbsp;
                </div>
                <div style="position: fixed; left: 0; top: 0; bottom: 0; right: 0; z-index: 1001; margin: 1% 50%">
                    <div style="display: inline-block; padding: 2px; background-color: #fff; width: 125px;">
                        <img src="/img/loading32.gif" style="float: left; margin: 8px;" />
                        <span style="display: inline-block; padding: 10px 0px;">Please Wait...</span>
                    </div>
                </div>
            </apex:facet>
    </apex:actionStatus>
</apex:form>
<script>
function alertBox() {
    alert("Confirm the Plan Version!");
}
</script></apex:page>

Controller

public class OpportunityLineItemCSVdmlController_AC {
public Static Map<String,Activate_Debug_Statements__c> debugStatementsActivationMap;
public Static Boolean DebugOn = false;
public Id oppId {get;set;}
public transient Blob csvFileBody {get;set;}
public transient string csvFileName {get;set;}
public transient string csvAsString {get;set;}
public transient String[] csvFileLines {get;set;}
public List<OpportunityLineItem> oliList {get;set;}
public List<OpportunityLineItem> oliDelList {get;set;}
public Map<Id,OpportunityLineItem> oliDelMap {get;set;}
public Map<Id,List<OliScheduleWrapper>> pbeIdToOliSchWrapMap {get;set;}
public Map<Id,Decimal> calculatedPbeGrossSpend;
public Map<Id,Decimal> calculatedDemoImpsBooked;
public Set<String> pbeIdSet;
public List<Id> oliIdsList;
public List<OpportunityLineItemSchedule> oliScheduleList;
public String planVersionSetValue {get;set;}
public Attachment attachment {get;set;}

Static{
    debugStatementsActivationMap = Activate_Debug_Statements__c.getAll();
    for(Activate_Debug_Statements__c custSet : debugStatementsActivationMap.values()){
        if(custSet.Name == 'OpportunityLineItem'){
            DebugOn = custSet.DebugOn__c;
            break;
        }
    }
}

public OpportunityLineItemCSVdmlController_AC(ApexPages.StandardController controller) {
    oppId = controller.getId();
    csvFileLines = new String[]{};
    oliList = new List<OpportunityLineItem>(); 
    oliDelList = new List<OpportunityLineItem>();
    oliDelMap = new Map<Id,OpportunityLineItem>();
    pbeIdToOliSchWrapMap = new Map<Id,List<OliScheduleWrapper>>();
    pbeIdSet = new Set<String>();
    oliIdsList = new List<Id>();
    oliScheduleList = new List<OpportunityLineItemSchedule>();
    calculatedPbeGrossSpend = new Map<Id,Decimal>();
    calculatedDemoImpsBooked = new Map<Id,Decimal>();
}

public PageReference OliCSVFileImport(){
    if(DebugOn)
        system.debug('planVersionSetValue---'+planVersionSetValue);
    try{
        if(String.isNotBlank(planVersionSetValue)){
            //DELETE NON-REV, NON-NET REV PRODS 
            if(planVersionSetValue == 'Proposed' || planVersionSetValue == 'Sold')
                oliDelMap = new Map<Id,OpportunityLineItem>([SELECT Id from OpportunityLineItem where Product2.Name NOT IN ('Revenue','Net Revenue','Commissioned Revenue','Fee') AND OpportunityId =:oppId]);
            //DELETE NON-REV, NON-NET REV, NON-SOLD_IMPS PRODS
            else    
                oliDelMap = new Map<Id,OpportunityLineItem>([SELECT Id from OpportunityLineItem where Product2.Name NOT IN ('Revenue','Net Revenue','Commissioned Revenue','Fee','Sold Impressions') AND OpportunityId =:oppId]);
            
            if(DebugOn){
                system.debug('💣 Size Check---- 💣'+oliDelList.size());
                //Products .csv Upload Process - START    
                system.debug('----csvFileBody-----'+csvFileBody);
            }
            csvAsString = csvFileBody.toString();
            if(DebugOn)
                system.debug('----csvAsString-----'+csvFileLines);
            csvFileLines = safeSplit(csvAsString,'\n');
            for(Integer i=1;i<csvFileLines.size()-1;i++){ 
                string[] csvRecordData = csvFileLines[i].split(',');
                Decimal grossSpend = 0.00;
                Decimal demoImpsBookedSum = 0.00;
                if(csvRecordData[11] != ''){
                    if(calculatedPbeGrossSpend.containsKey(Id.valueOf(csvRecordData[10]))) {
                        grossSpend = calculatedPbeGrossSpend.get(Id.valueOf(csvRecordData[10]))+Decimal.valueOf(csvRecordData[0]); 
                        calculatedPbeGrossSpend.put(Id.valueOf(csvRecordData[10]),grossSpend);
                    } else {
                        calculatedPbeGrossSpend.put((Id.valueOf(csvRecordData[10])), Decimal.valueOf(csvRecordData[0]));
                    }
                    if(calculatedDemoImpsBooked.containsKey(Id.valueOf(csvRecordData[10]))){
                        demoImpsBookedSum = calculatedDemoImpsBooked.get(Id.valueOf(csvRecordData[10]))+Decimal.valueOf(csvRecordData[27]); 
                        calculatedDemoImpsBooked.put(Id.valueOf(csvRecordData[10]),demoImpsBookedSum);
                    }else{
                        calculatedDemoImpsBooked.put((Id.valueOf(csvRecordData[10])), Decimal.valueOf(csvRecordData[27]));
                    }
                }
            }
            for(Integer i=1;i<csvFileLines.size()-1;i++){
                OpportunityLineItem oli = new OpportunityLineItem();
                OliScheduleWrapper oliSchWrapList = new OliScheduleWrapper();
                string[] csvRecordData = csvFileLines[i].split(',');
                if(csvRecordData[11] != ''){
                    //Capture and map PricebookEntryId to oliScheduleWrapper
                    if(!pbeIdToOliSchWrapMap.containsKey(csvRecordData[10])){
                        pbeIdToOliSchWrapMap.put(csvRecordData[10], new List<OliScheduleWrapper>{oliSchWrapReserve(csvRecordData,planVersionSetValue)});
                    }else{
                        pbeIdToOliSchWrapMap.get(csvRecordData[10]).add(oliSchWrapReserve(csvRecordData,planVersionSetValue));
                    }                            
                }
                // OpportunityLineItems Creation
                if(!pbeIdSet.contains(csvRecordData[10])){                            
                    oli.Gross_Spend__c = calculatedPbeGrossSpend.get(Id.valueOf(csvRecordData[10]));   
                    oli.Guaranteed_Booked_Imps__c = calculatedDemoImpsBooked.get(Id.valueOf(csvRecordData[10])); 
                    if(csvRecordData[1] != '')
                        oli.RC_HH_Imps__c = Integer.valueof(csvRecordData[1]);
                    if(csvRecordData[2] != '')
                        oli.EST_HH_Imps__c = Integer.valueof(csvRecordData[2]);
                    if(csvRecordData[3] != '')
                        oli.EST_P2_Imps__c = Integer.valueof(csvRecordData[3]);
                    if(csvRecordData[4] != '')
                        oli.EST_Demo_Imps__c = Integer.valueof(csvRecordData[4]);
                    oli.UnitPrice = Decimal.valueof(csvRecordData[5]);
                    oli.Quantity = Decimal.valueof(csvRecordData[6]);
                    if(csvRecordData[7] != '')
                        oli.Delivered_HH_Imps__c = Integer.valueof(csvRecordData[7]);
                    if(csvRecordData[8] != '')
                        oli.Delivered_P2_Imps__c = Integer.valueof(csvRecordData[8]);
                    if(csvRecordData[9] != '')
                        oli.Delivered_Demo_Imps__c = Integer.valueof(csvRecordData[9]);
                    oli.PricebookEntryId = csvRecordData[10];
                    oli.OpportunityId = OppId;
                    
                    oliList.add(oli);
                    pbeIdSet.add(csvRecordData[10]);
                }
            }
            
            Database.SaveResult[] sr;
            Boolean insertSuccess = true;
            if(!oliList.isEmpty()){
                sr = Database.insert(oliList, False);
                if(DebugOn)
                    system.debug('oliList----------'+sr);
                for(Database.SaveResult insertedOli : sr){
                    oliIdsList.add(insertedOli.getId());         
                }
                
                //OpportunityLineItemSchedules Creation
                Integer test = 0;
                for(OpportunityLineItem oppLineItem : [Select Id,Gross_Spend__c,PricebookEntryId,Product2.Name From OpportunityLineItem WHERE Id IN: oliIdsList]){
                    if(pbeIdToOliSchWrapMap.containsKey(oppLineItem.PricebookEntryId)){
                        for(OliScheduleWrapper osw : pbeIdToOliSchWrapMap.get(oppLineItem.PricebookEntryId)){
                            OpportunityLineItemSchedule oliSchedule = new OpportunityLineItemSchedule();
                            oliSchedule.OpportunityLineItemId = oppLineItem.Id;
                            oliSchedule.Type = 'Revenue';
                            oliSchedule.ScheduleDate = Date.parse(osw.oliDate);//date.parse(schDate);
                            test++;
                            if(DebugOn)
                                system.debug('Check this out----'+test);
                            if(String.isNotBlank(osw.oliGrossSpend))
                                oliSchedule.Revenue = Decimal.valueof(osw.oliGrossSpend);
                            if(String.isNotBlank(osw.oliDescription))
                                oliSchedule.Description = osw.oliDescription;
                            if(String.isNotBlank(osw.oliBookedGrossSpend))
                                oliSchedule.Booked_Gross_Spend__c = Decimal.valueof(osw.oliBookedGrossSpend);
                            if(String.isNotBlank(osw.oliDateBroadcast))
                                oliSchedule.Broadcast_Date__c = Date.parse(osw.oliDateBroadcast);
                            if(String.isNotBlank(osw.oliDemoImpsBooked))
                                oliSchedule.Demo_Imps_Booked__c = Decimal.valueof(osw.oliDemoImpsBooked);
                            if(String.isNotBlank(osw.oliESTHHImpsBooked))
                                oliSchedule.EST_HH_Imps_Booked__c = Decimal.valueof(osw.oliESTHHImpsBooked);
                            if(String.isNotBlank(osw.oliP2ImpsBooked))
                                oliSchedule.P2_Imps_Booked__c = Decimal.valueof(osw.oliP2ImpsBooked);
                            if(String.isNotBlank(osw.oliRCHHImpsBooked))
                                oliSchedule.RC_HH_Imps_Booked__c = Decimal.valueof(osw.oliRCHHImpsBooked);
                            if(String.isNotBlank(osw.oliUnitsBookedBcast))
                                oliSchedule.Units_Booked_Bcast__c = Integer.valueof(osw.oliUnitsBookedBcast); 
                            if(String.isNotBlank(osw.oliUnitsBooked))
                                oliSchedule.Units_Booked__c = Integer.valueof(osw.oliUnitsBooked);   
                            if(String.isNotBlank(osw.oliSpotsBookedBcast))
                                oliSchedule.Spots_Booked_Bcast__c = Integer.valueof(osw.oliSpotsBookedBcast); 
                            if(String.isNotBlank(osw.oliSpotsBooked))
                                oliSchedule.Spots_Booked__c = Integer.valueof(osw.oliSpotsBooked);
                            if(String.isNotBlank(osw.oliSpotsReceivedBcast))
                                oliSchedule.Spots_Received_Bcast__c = Integer.valueof((Decimal.valueof(osw.oliSpotsReceivedBcast)).setScale(0));
                            if(String.isNotBlank(osw.oliSpotsReceived))
                                oliSchedule.Spots_Received__c = Integer.valueof((Decimal.valueof(osw.oliSpotsReceived)).setScale(0));
                            if(String.isNotBlank(osw.oliHHImpsDelivered))
                                oliSchedule.HH_Imps_Delivered__c = Decimal.valueof(osw.oliHHImpsDelivered);
                            if(String.isNotBlank(osw.oliP2ImpsDelivered))
                                oliSchedule.P2_Imps_Delivered__c = Decimal.valueof(osw.oliP2ImpsDelivered);
                            if(String.isNotBlank(osw.oliDemoImpsDelivered))
                                oliSchedule.Demo_Imps_Delivered__c = Decimal.valueof(osw.oliDemoImpsDelivered);
                            
                            oliScheduleList.add(oliSchedule);
                        }
                    }
                }
              
                if(!oliScheduleList.isEmpty()){                    
                    insert oliScheduleList;  
                }
                                
                for(Integer i=0;i<sr.size();i++){
                    if (!sr.get(i).isSuccess()){
                        insertSuccess = false;
                        break;
                    }
                }
                if(insertSuccess){
                    Attachment attach = new Attachment(Body = csvFileBody, ParentID = oppId, Name = csvFileName);
                    insert attach;
                }

            }
                if(planVersionSetValue != ''){
                    if(!oliDelMap.isEmpty()){
                        asyncLogicMethod(oliDelMap.Keyset(), OppId, oliIdsList, (new Map<Id,OpportunityLineItemSchedule>(oliScheduleList)).Keyset(), PlanVersionSetValue);
                    }else{
                        asyncLogicMethod(new Set<Id>(), OppId, oliIdsList, (new Map<Id,OpportunityLineItemSchedule>(oliScheduleList)).Keyset(), PlanVersionSetValue);
                        
                    }
                }
                //Margin Product + Schedules Insert and Plan Version Margin Update + Delete Old Products - END 
                
            //Products .csv Upload Process - END  
        }
    PageReference oppPage = new PageReference('/'+oppId+'?inline=0');     
    return oppPage;
    }
    catch(Exception e) {
        ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR,'<h3 style="color:blue; font-size:15px;">An error has occured while importing product data. Please make sure input csv file is correct  </h1>'+'<br/><b>Exception type caught: </b>' + e.getTypeName() +'<br/><b>Message: </b>' + e.getMessage() +'<br/><b>Line number: </b>' + e.getLineNumber() + '<br/><b>Stack trace: </b>' + e.getStackTraceString() + '<br/><b>Cause: </b>' + e.getCause());
        ApexPages.addMessage(errorMessage);
        System.debug('----Exception type caught: ' + e.getTypeName() +'----Message: ' + e.getMessage() +'----Line number: ' + e.getLineNumber() + '----Stack trace: ' + e.getStackTraceString() + '----Cause: ' + e.getCause());      
        return null;  
    }
}

public List<SelectOption> getPlanVersion(){
    List<SelectOption> options = new List<SelectOption>();
    options.add(new selectOption('','--- None ---'));    
    Schema.DescribeFieldResult fieldResult = Opportunity.Plan_Version__c.getDescribe();
    List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
    for( Schema.PicklistEntry f : ple){
        options.add(new SelectOption(f.getLabel(), f.getValue()));
    }       
    return options;
}

public PageReference OliDelete(){
    oliDelList = [SELECT Id from OpportunityLineItem where Product2.Name NOT IN ('Revenue','Net Revenue','Commissioned Revenue','Fee','Sold Impressions') AND OpportunityId =:oppId];
    if(!oliDelList.isEmpty())
        delete oliDelList;
    return new PageReference('/'+oppId+'?inline=0');
}

//SOLD_IMPS Product and Schedules Insert
public Static void soldOliWithSchedules(Id OppId, List<Id> tempOliIds, Set<Id> tempOliScheduleIds){
    Map<Date,Decimal> schDateToRevMap = new Map<Date,Decimal>();
    Map<Date,Decimal> schDateToBookedGrossSpendMap = new Map<Date,Decimal>();
    Map<Date,Integer> schDateToSpotsBookedMap = new Map<Date,Integer>();
    Map<Date,Decimal> schDateToRCHHImpsBookedMap = new Map<Date,Decimal>();
    Map<Date,Decimal> schDateToESTHHImpsBookedMap = new Map<Date,Decimal>();
    Map<Date,Decimal> schDateToP2ImpsBookedMap = new Map<Date,Decimal>();
    Map<Date,Decimal> schDateToDemoImpsBookedMap = new Map<Date,Decimal>();
    List<OpportunityLineItemSchedule> soldOliSchList = new List<OpportunityLineItemSchedule>(); 
    PricebookEntry pbe = [Select id, Product2.Name From PricebookEntry where Product2.Name = 'Sold Impressions' Limit 1];
    OpportunityLineItem soldOli = new OpportunityLineItem(PricebookEntryId = pbe.Id, OpportunityId = OppId, Gross_Spend__c = 0.00, RC_HH_Imps__c = 0, EST_HH_Imps__c = 0, EST_P2_Imps__c = 0, EST_Demo_Imps__c = 0, UnitPrice = 0.00, Quantity = 0.00);
    for(OpportunityLineItem oli: [SELECT Id,Gross_Spend__c,RC_HH_Imps__c,EST_HH_Imps__c,EST_P2_Imps__c,EST_Demo_Imps__c,UnitPrice,Quantity FROM OpportunityLineItem WHERE Id IN: tempOliIds]){
        if(oli.Gross_Spend__c != null)
            soldOli.Gross_Spend__c += oli.Gross_Spend__c;
        if(oli.RC_HH_Imps__c != null)
            soldOli.RC_HH_Imps__c += oli.RC_HH_Imps__c;
        if(oli.EST_HH_Imps__c != null)
            soldOli.EST_HH_Imps__c += oli.EST_HH_Imps__c;
        if(oli.EST_P2_Imps__c != null)
            soldOli.EST_P2_Imps__c += oli.EST_P2_Imps__c;
        if(oli.EST_Demo_Imps__c != null)
            soldOli.EST_Demo_Imps__c += oli.EST_Demo_Imps__c;
        if(oli.UnitPrice != null)
            soldOli.UnitPrice += oli.UnitPrice;
        if(oli.Quantity != null)
            soldOli.Quantity += oli.Quantity;
    }
    insert soldOli;

    for(OpportunityLineItemSchedule oliSch: [SELECT Id,ScheduleDate,Revenue,Booked_Gross_Spend__c,RC_HH_Imps_Booked__c,EST_HH_Imps_Booked__c,P2_Imps_Booked__c,Demo_Imps_Booked__c FROM OpportunityLineItemSchedule WHERE Id IN:tempOliScheduleIds]){
        if(schDateToRevMap.containsKey(oliSch.ScheduleDate))
            schDateToRevMap.put(oliSch.ScheduleDate, schDateToRevMap.get(oliSch.ScheduleDate) + oliSch.Revenue);
        else
            schDateToRevMap.put(oliSch.ScheduleDate, oliSch.Revenue);

        if(oliSch.Booked_Gross_Spend__c != null){
            if(schDateToBookedGrossSpendMap.containsKey(oliSch.ScheduleDate))
                schDateToBookedGrossSpendMap.put(oliSch.ScheduleDate, schDateToBookedGrossSpendMap.get(oliSch.ScheduleDate) + oliSch.Booked_Gross_Spend__c);
            else
                schDateToBookedGrossSpendMap.put(oliSch.ScheduleDate, oliSch.Booked_Gross_Spend__c);
        }
        /*if(oliSch.Spots_Booked__c != null){
        if(schDateToSpotsBookedMap.containsKey(oliSch.ScheduleDate))
            schDateToSpotsBookedMap.put(oliSch.ScheduleDate, schDateToSpotsBookedMap.get(oliSch.ScheduleDate) + oliSch.Spots_Booked__c);
        else
            schDateToSpotsBookedMap.put(oliSch.ScheduleDate, oliSch.Spots_Booked__c);
        }*/
        if(oliSch.RC_HH_Imps_Booked__c != null){
            if(schDateToRCHHImpsBookedMap.containsKey(oliSch.ScheduleDate))
                schDateToRCHHImpsBookedMap.put(oliSch.ScheduleDate, schDateToRCHHImpsBookedMap.get(oliSch.ScheduleDate) + oliSch.RC_HH_Imps_Booked__c);
            else
                schDateToRCHHImpsBookedMap.put(oliSch.ScheduleDate, oliSch.RC_HH_Imps_Booked__c);
        }
        if(oliSch.EST_HH_Imps_Booked__c != null){
            if(schDateToESTHHImpsBookedMap.containsKey(oliSch.ScheduleDate))
                schDateToESTHHImpsBookedMap.put(oliSch.ScheduleDate, schDateToESTHHImpsBookedMap.get(oliSch.ScheduleDate) + oliSch.EST_HH_Imps_Booked__c);
            else
                schDateToESTHHImpsBookedMap.put(oliSch.ScheduleDate, oliSch.EST_HH_Imps_Booked__c);
        }
        if(oliSch.P2_Imps_Booked__c != null){
            if(schDateToP2ImpsBookedMap.containsKey(oliSch.ScheduleDate))
                schDateToP2ImpsBookedMap.put(oliSch.ScheduleDate, schDateToP2ImpsBookedMap.get(oliSch.ScheduleDate) + oliSch.P2_Imps_Booked__c);
            else
                schDateToP2ImpsBookedMap.put(oliSch.ScheduleDate, oliSch.P2_Imps_Booked__c);
        }
        if(oliSch.Demo_Imps_Booked__c != null){
            if(schDateToDemoImpsBookedMap.containsKey(oliSch.ScheduleDate))
                schDateToDemoImpsBookedMap.put(oliSch.ScheduleDate, schDateToDemoImpsBookedMap.get(oliSch.ScheduleDate) + oliSch.Demo_Imps_Booked__c);
            else
                schDateToDemoImpsBookedMap.put(oliSch.ScheduleDate, oliSch.Demo_Imps_Booked__c);
        }
    }
    if(!schDateToRevMap.isEmpty()){
        for(Date schDate : schDateToRevMap.keySet()){
            OpportunityLineItemSchedule soldOliSch = new OpportunityLineItemSchedule();
            soldOliSch.OpportunityLineItemId = soldOli.Id;
            soldOliSch.Revenue = schDateToRevMap.get(schDate);
            soldOliSch.Type = 'Revenue';
            soldOliSch.ScheduleDate = schDate;
            if(schDateToBookedGrossSpendMap.containsKey(schDate))
                soldOliSch.Booked_Gross_Spend__c = schDateToBookedGrossSpendMap.get(schDate);
            if(schDateToRCHHImpsBookedMap.containsKey(schDate))
                soldOliSch.RC_HH_Imps_Booked__c = schDateToRCHHImpsBookedMap.get(schDate);
            if(schDateToESTHHImpsBookedMap.containsKey(schDate))
                soldOliSch.EST_HH_Imps_Booked__c = schDateToESTHHImpsBookedMap.get(schDate);
            if(schDateToP2ImpsBookedMap.containsKey(schDate))
                soldOliSch.P2_Imps_Booked__c = schDateToP2ImpsBookedMap.get(schDate);
            if(schDateToDemoImpsBookedMap.containsKey(schDate))
                soldOliSch.Demo_Imps_Booked__c = schDateToDemoImpsBookedMap.get(schDate);
            soldOliSchList.add(soldOliSch);
        }
    }
    insert soldOliSchList;           
}

public OliScheduleWrapper oliSchWrapReserve(String[] csvData, String tempPlanVersionValue){
    OliScheduleWrapper oliSchWrapTemp = new OliScheduleWrapper();
    oliSchWrapTemp.oliGrossSpend = csvData[0];
    oliSchWrapTemp.oliDate = csvData[11];
    oliSchWrapTemp.oliDescription = csvData[12];
    if(csvData.size() > 14){
        oliSchWrapTemp.oliDateBroadcast = csvData[14];
        oliSchWrapTemp.oliBookedGrossSpend = csvData[15];
        oliSchWrapTemp.oliUnitsBookedBcast = csvData[16];
        oliSchWrapTemp.oliUnitsBooked = csvData[17];
        oliSchWrapTemp.oliSpotsBookedBcast = csvData[18];
        oliSchWrapTemp.oliSpotsBooked = csvData[19];
        oliSchWrapTemp.oliRCHHImpsBooked = csvData[22];
        oliSchWrapTemp.oliESTHHImpsBooked = csvData[23];
        oliSchWrapTemp.oliP2ImpsBooked = csvData[25];
        oliSchWrapTemp.oliDemoImpsBooked = csvData[27];
        oliSchWrapTemp.oliSpotsReceivedBcast = csvData[20];
        oliSchWrapTemp.oliSpotsReceived = csvData[21];
        oliSchWrapTemp.oliHHImpsDelivered = csvData[24];
        oliSchWrapTemp.oliP2ImpsDelivered = csvData[26];
        oliSchWrapTemp.oliDemoImpsDelivered = csvData[28]; 
    }
    return oliSchWrapTemp;
}

public class OliScheduleWrapper{
    public transient String oliGrossSpend {get; set;}
    public transient String oliDate {get; set;}
    public transient String oliDescription {get; set;}
    public transient String oliDateBroadcast {get; set;}
    public transient String oliBookedGrossSpend {get; set;}
    public transient String oliUnitsBookedBcast {get; set;}
    public transient String oliUnitsBooked {get; set;}
    public transient String oliSpotsBookedBcast {get; set;}
    public transient String oliSpotsBooked {get; set;}
    public transient String oliSpotsReceivedBcast {get; set;}
    public transient String oliSpotsReceived {get; set;}
    public transient String oliRCHHImpsBooked {get; set;}
    public transient String oliESTHHImpsBooked {get; set;}
    public transient String oliP2ImpsBooked {get; set;}
    public transient String oliDemoImpsBooked {get; set;}
    public transient String oliHHImpsDelivered {get; set;}
    public transient String oliP2ImpsDelivered {get; set;}
    public transient String oliDemoImpsDelivered {get; set;}    
}

//Alternative to .split('\n') - dodging REGEX Too Complicated error for heavy csv file processing
public List<String> safeSplit(String inStr, String delim){
    Integer regexFindLimit = 100;
    Integer regexFindCount = 0;
    List<String> output = new List<String>();
    
    Matcher m = Pattern.compile(delim).matcher(inStr);
    Integer lastEnd = 0;

    while(!m.hitEnd()){
        while(regexFindCount < regexFindLimit && !m.hitEnd()){
            if(m.find()){
                output.add(inStr.substring(lastEnd, m.start()));  
                lastEnd = m.end();
            }else{
                output.add(inStr.substring(lastEnd));
                lastEnd = inStr.length();
            }
            regexFindCount++;
        }
    // Note: Using region() to advance instead of substring() saves drastically on heap size. 
    // Nonetheless, we still must reset the (unmodified) input sequence to avoid a 'Regex too complicated' error.
        m.reset(inStr);        
        m.region(lastEnd, m.regionEnd());
        
        regexFindCount = 0;
    }
    return output;
}    

@future
public static void asyncLogicMethod(Set<Id> oliDelRecords, Id tempOppId, List<Id> tempoliIdsList, Set<Id> tempoliSchedIdsSet, String tempPlanVersionSetValue){
    if(!oliDelRecords.isEmpty()){
        delete [SELECT Id from OpportunityLineItem WHERE Id IN: oliDelRecords];
    }if(tempPlanVersionSetValue == 'Sold')
        soldOliWithSchedules(tempOppId,tempoliIdsList,tempoliSchedIdsSet);
    MarginProdWithSchedulesCalc_AC.insertMarginProdwithSchedules(tempOppId,tempoliIdsList,tempPlanVersionSetValue);
}

}

Tried to wrap around this exception & couldn't find a better way to resolve it. Really appreciate you help Debug Log

11
  • Not sure how to share the complete debug log here
    – SMorse
    Commented Feb 22, 2022 at 8:05
  • 1
    Check to see what automation has been added to the line item and oppy. Also, can you perhaps make the processing async (have the VF start a batch to do the updates in chunks)?
    – Phil W
    Commented Feb 22, 2022 at 10:34
  • Take into account that basically managed packages have their own governor limits, EXCEPT for Apex CPU time limit. So if you can get the managed packages to not run/trigger that will also help you with this issue. Commented Feb 22, 2022 at 11:24
  • 1
    That's a lot for online processing. You might want to consider building a 'landing zone' object where you store the csv input and then an asynchronous processing mechanism that processes anything in the landing zone bit by bit. Also you might want to consider a different integration pattern, based on where this data is coming from.. Commented Feb 22, 2022 at 15:42
  • 1
    @GuyClairbois We currently store the records in Attachment/Files object after processing. So you're saying to save the file first & then do async operation to retrieve that spread sheet from File object & do the remaining logic? or do you mean save the "csvAsString" into a long text field on a new landing Object & then do async operation from there? I wish I can share the complete log but from what I have in the logs, the CPU time is happening when I do the DML on OppLineItem and its related OppLineItemSchedule which is causing its parent Opp to trigger.
    – SMorse
    Commented Feb 22, 2022 at 17:12

1 Answer 1

1

If you have thousands of records, you can't parse that kind of CSV in Apex. It's simply too expensive CPU-wise. Instead, use JavaScript to parse the CSV client-side, transform the data into records, and then pass the parsed data to Apex. Not only will this help avoid governor limits, it will drastically reduce the amount of time the user will have to wait for the files to upload. Alternatively, consider using the Bulk API. You do need to make sure the headers are correct, but the Bulk API supports CSV files directly. You can also call the Bulk API from Apex without too much effort if you really wanted to.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .