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
debprakash shawdebprakash shaw 

I want to use Upsert operation in my handler class

Hi Everyone,
I have One trigger and one handler to call my two batch insert and update batch class. when running the code I get an error(error:>> first error: UNABLE_TO_LOCK_ROW) when I do update and insert at the same time so that I merge the code to UPSERT Batch(insert + update batch). now I don't understand how to modify the handler for upsert batch.
This is the trigger to execute the handler
 
trigger BillingSchemeProductsTrigger on Billing_Scheme_Products__c (after update,after insert) {
    System.debug('Before Exception');

	BillingSchemeProductsTriggerHelper handler = new BillingSchemeProductsTriggerHelper();
    if(BillingSchemeProductsTriggerHelper.skipTrigger==false){ 
        if(Trigger.isInsert && Trigger.isAfter){
            handler.OnAfterInsert(Trigger.new);
        }  
        if(Trigger.isUpdate && Trigger.isAfter){
            handler.OnAfterUpdate(Trigger.oldMap, Trigger.new);
        } 
    }
}
handler class
public class BillingSchemeProductsTriggerHelper {
    public static boolean skipTrigger = false;
	public static String const_UnumReferrerSlug = Label.UNUM_Referrer_Slug; // This is unum_dev in QA
	
	public void OnAfterInsert( Map<ID, Billing_Scheme_Products__c> map_OldBSP,List<Billing_Scheme_Products__c> list_BSP){
		createRelatedRecord(map_OldBSP,list_BSP);
	}
	
    public void OnAfterUpdate(Map<ID, Billing_Scheme_Products__c> map_OldBSP, List<Billing_Scheme_Products__c> list_BSP){
		    updateRelatedRecord(map_OldBSP, list_BSP);
	}
	
	
	public void createRelatedRecord(Map<ID, Billing_Scheme_Products__c> map_OldBSP,List<Billing_Scheme_Products__c> list_BSP){
		Map<Id,Set<Id>> map_BSWithBSP=new Map<Id,Set<Id>>();
		Set<Id> set_TempId = new Set<Id>();
		
		Map<Id,Set<Id>> map_BSWithProductId = new Map<Id,Set<Id>>();
		Map<String,Boolean> map_BSPStatus = new Map<String,Boolean>();
		Map<String,Boolean> map_BSPStatusOnContact = new Map<String,Boolean>();
		Set<Id> set_TempProductId = new Set<Id>();
		String strKey = '';
        for(Billing_Scheme_Products__c bsp:list_BSP){
            if(map_BSWithBSP.containsKey(bsp.Billing_Scheme__c)){
               set_TempId = map_BSWithBSP.get(bsp.Billing_Scheme__c);   
            }else{
			   set_TempId = new Set<Id>();
            }
			set_TempId.add(bsp.Id); 
			map_BSWithBSP.put(bsp.Billing_Scheme__c, set_TempId); 

			if(map_BSWithProductId.containsKey(bsp.Billing_Scheme__c)){
               set_TempProductId = map_BSWithProductId.get(bsp.Billing_Scheme__c);   
            }else{
			   set_TempProductId = new Set<Id>();
            }
			set_TempProductId.add(bsp.Product__c); 
			map_BSWithProductId.put(bsp.Billing_Scheme__c, set_TempProductId); 
			
			strKey = bsp.Billing_Scheme__c + '~' + bsp.Product__c;
			map_BSPStatus.put(strKey, bsp.Inactive__c);
			
			if(bsp.InActive_on_Partner__c){
				map_BSPStatusOnContact.put(strKey + 'Partner', bsp.InActive_on_Partner__c);
			}if(bsp.InActive_on_ChildAbove16__c){
				map_BSPStatusOnContact.put(strKey + 'Over16', bsp.InActive_on_ChildAbove16__c);
			}if(bsp.InActive_on_ChildBelow16__c){
				map_BSPStatusOnContact.put(strKey + 'Under16', bsp.InActive_on_ChildBelow16__c);
			}

			// Added on 16-02-2022
			mapExtraAttributes(map_BSPStatusOnContact, bsp.Extra_Attributes__c, strKey);
        }
		
		if(map_BSWithBSP.size()>0){
			CreatedRelatedAccountAllowancesProducts(map_BSWithBSP);
		}
		
	}
	
	
	public void CreatedRelatedAccountAllowancesProducts(Map<Id,Set<Id>> map_BSWithBSP){
		Map<Id,Id> map_AccountWithAA = new Map<Id,Id>();
		Set<Id> set_BSId = map_BSWithBSP.keySet();
		System.debug('Billing Scheme ==> ' + set_BSId);
		Map<Id, List<Id>> map_BSIdWithListOfCustomAccId = new Map<Id,List<Id>>();
		Map<Id, List<Account_Allowances__c>> map_CustomAccIdWithListOfAA = new Map<Id,List<Account_Allowances__c>>();
		Map<Id, Decimal> map_CustAccIdWithCountToBeSubstracted = new Map<Id, Decimal>();
		
		List<Id> list_CustomAccId = new List<Id>();
		Id billingSchemeId = null;

		for(Account_Allowances__c objAW:[
			SELECT id, Account__c, Account__r.Instructing_Party__r.referrer__r.name, Account__r.Instructing_Party__r.Referrer__r.Slug__c,
			Billing_Scheme__c, Products__r.Name, Max_Allownace__c, Remaining_Allowance__c
			FROM Account_Allowances__c 
			WHERE Billing_Scheme__c!=null 
			AND Billing_Scheme__c IN : set_BSId
		]){
			billingSchemeId = objAW.Billing_Scheme__c;
			map_AccountWithAA.put(objAW.Account__c,objAW.Id); // For one custom account this will store only one AA, done only for mapping of BS
			
			if(objAW.Account__r.Instructing_Party__r.Referrer__r.Slug__c == const_UnumReferrerSlug && objAW.Products__r.Name == 'Psychological Services' && 		objAW.Max_Allownace__c == 8){
				list_CustomAccId.add(objAW.Account__c);

				List<Account_Allowances__c> list_AA = new List<Account_Allowances__c>();
				list_AA.add(objAW);
				map_CustomAccIdWithListOfAA.put(objAW.Account__c, list_AA);
			}
		}

		if(list_CustomAccId.size() > 0){
			map_BSIdWithListOfCustomAccId.put(billingSchemeId, list_CustomAccId);
		}


		//Query and get BSP from BS Id
		// We are changing only one BS in one request
		for(Billing_Scheme_Products__c obj_BSPs : [
			SELECT Id, Units_Allowed__c, Billing_Scheme__c
			FROM Billing_Scheme_Products__c 
			WHERE Product__r.name = 'Psychological Services' AND Billing_Scheme__c IN: map_BSIdWithListOfCustomAccId.keySet()
		]){
			//if 8 already exist then only perform this action
			if(obj_BSPs.Units_Allowed__c == 8){
				if(map_BSIdWithListOfCustomAccId != null && map_BSIdWithListOfCustomAccId.containsKey(obj_BSPs.Billing_Scheme__c) ){
					for(Id customAccountId : map_BSIdWithListOfCustomAccId.get(obj_BSPs.Billing_Scheme__c)){
						if(map_CustomAccIdWithListOfAA != null && map_CustomAccIdWithListOfAA.containsKey(customAccountId) ){
							for(Account_Allowances__c obj_AA : map_CustomAccIdWithListOfAA.get(customAccountId)){
								// only products with mental health would be present here
								// if max allowance is 8 only then calculate remaining allowances for plus
								// we have only one of this kind
								if(obj_AA.Max_Allownace__c == 8){
									Decimal countToBeSubstracted = obj_AA.Max_Allownace__c - obj_AA.Remaining_Allowance__c;
									map_CustAccIdWithCountToBeSubstracted.put(customAccountId, countToBeSubstracted);
									// System.debug('customAccountId --> ' + countToBeSubstracted);
								}
							}
						}
					}
				}
			}
		}
		
		InsertAllowanceRecordBatch objAccBatch = new InsertAllowanceRecordBatch();
		objAccBatch.map_BSWithBSP = map_BSWithBSP;
		objAccBatch.map_AccountWithAA = map_AccountWithAA;
		objAccBatch.map_CustAccIdWithCountToBeSubstracted = map_CustAccIdWithCountToBeSubstracted;
		Database.executeBatch(objAccBatch, 500);
	}
    public void updateRelatedRecord(Map<ID, Billing_Scheme_Products__c>  map_OldBSP, List<Billing_Scheme_Products__c> list_BSP){
		Map<Id, Set<Id>> map_BS_Products = new Map<Id, Set<Id>>();
		Set<Id> set_BillingSchemeId = new Set<Id>();
		Set<Id> set_TempProduct = new Set<Id>();
        for(Billing_Scheme_Products__c objBS:list_BSP){
			String newExtraAttribute = objBS.Extra_Attributes__c;
			//get Old Billing_Scheme_Products
            Billing_Scheme_Products__c objOldBSP=map_OldBSP.get(objBS.id);
			String oldExtraAttribute = objOldBSP.Extra_Attributes__c;
            
			// Add Check for Extra attribute is changed
			if(objBS.Inactive__c!=objOldBSP.Inactive__c 
				|| objBS.InActive_on_Partner__c!=objOldBSP.InActive_on_Partner__c 
				|| objBS.InActive_on_ChildAbove16__c!=objOldBSP.InActive_on_ChildAbove16__c 
				|| objBS.InActive_on_ChildBelow16__c!=objOldBSP.InActive_on_ChildBelow16__c
				|| newExtraAttribute != oldExtraAttribute){

				if(map_BS_Products.containsKey(objBS.Billing_Scheme__c)){
					set_TempProduct = map_BS_Products.get(objBS.Billing_Scheme__c);
				}else{
					set_TempProduct = new Set<Id>();
				}
				set_TempProduct.add(objBS.Product__c);
                map_BS_Products.put(objBS.Billing_Scheme__c, set_TempProduct);
                set_BillingSchemeId.add(objBS.Billing_Scheme__c);
            }
        }
		
        system.debug('map_BS_Products----->' + map_BS_Products);
		if(map_BS_Products!=null && map_BS_Products.size()>0){
			System.debug('Run UpdateAllowanceRecordBatch on Billing Scheme Product Update');
			UpdateAllowanceRecordBatch objAccBatch = new UpdateAllowanceRecordBatch();
			objAccBatch.set_BillingSchemeId = set_BillingSchemeId;
			objAccBatch.map_BS_Products = map_BS_Products;
			objAccBatch.strAction = 'Update Billing Scheme Product';
            Database.executeBatch(objAccBatch, 500);			
        
		}
    }

	public static void mapExtraAttributes(Map<String,Boolean> map_BSPStatusOnContact, String extraAttributes, String strKey){
		// If we have Extra Attributes then use this else continue what is going till now, All Projects
		// this is only for child Contact Product, Active/Inactive of Members
		if(String.isNotBlank(extraAttributes)){
			// convert Json to map
			Map<String, Object> map_JsonEntries = (Map<String, Object>) JSON.deserializeUntyped(extraAttributes);
			Decimal childAllowedForMinAge = (Decimal) map_JsonEntries.get('childMinAge');
			Boolean isChildAllowed = (Boolean) map_JsonEntries.get('isChildAllowed');
			System.debug(childAllowedForMinAge + ' - ' + isChildAllowed);
			map_BSPStatusOnContact.put(strKey + 'FROM_EXTRA_ATTRIBUTES~' + childAllowedForMinAge, isChildAllowed);
		}
	}
}

now see the handler line number 126/163 here call the insert batch or update batch,i want to merge the insert or update batch to upsertAccountAllowences ,I already merge the Update or Insert batch to Upsert batch I want only modify the handler

Thanks in advance