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
Tyler DittoTyler Ditto 

Summary Rollup Trigger

I am new apex programming and am struggling a little bit. I have pieced together some code in an attempt to build a rollup from the Assets to Contracts.

The trigger is supposed to be able to get sum all of the assets' summary_asset_cost__c fields that are related to the contract and post it to the base_product_rev__c field on the contract. I am getting an error when trying to call the relationship in the second query. Also please notfiy if this is the best way to accomplish this goal, as stated before I am not real skilled in apex programming.



trigger AssetCostRollup on Asset (after delete, after insert, after update) {

    Set<id> contractIds = new Set<id>();
    List<Contract> contractsToUpdate = new List<Contract>();

    for (Asset item : Trigger.new)
        contractIds.add(item.Asset);

    if (Trigger.isUpdate || Trigger.isDelete) {
        for (Asset item : Trigger.old)
            contractIds.add(item.Contract);
    }

    // get a map of the contracts and the costs of the assets on the contract
    Map<id,Contract> contractMap = new Map<id,Contract>([select id, summary_asset_cost__c from Asset where id IN :contractIds]);

    // query the contracts and the related assets and sum the cost of the assets to the contracts base_product_rev__c field
    for (Contract contract : [select Id, Name, summary_asset_cost__c,(select id from contract_lookup__r) from Asset where Id IN :contractIds]) {
        contractMap.get(contract.Id).asset_summary_cost__c = contract.base_product_rev__c.sum();
        
        contractsToUpdate.add(contractMap.get(contract.Id));
    }

    update contractsToUpdate;

}
}
 
R Z KhanR Z Khan
I assume that contract is a cusotm field on asset? You cannot assign Seet records to a contract. There is no cush field as Contract or Asset on an asset object. Parent asset has a field name Parent. you need to run trhough trigger records and popoualte contract Ids, nto Assets. then jsut query for all those contracts and update the fields. You don't need a parent asset ids unless i misunderstood your requirements. 
Try the following code. Please update the "ContractField" with the API name of the contract field on your Asset object
trigger AssetTest on Asset(after delete, after insert, after update){

    Map<Id,Integer> contractsToUpdate = new Map<Id,Integer>();

if(trigger.isInsert){
    for (Asset item : Trigger.new)
        contractsToUpdate.put(item.ContractField, item.summary_asset_cost__c);
}

    if (Trigger.isDelete) {
        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, -item.summary_asset_cost__c);
    }
    if(trigger.isUpdate){
    	for(Asset item : trigger.new){
	    	Asset oldItem = trigger.oldMap.get(item.Id);
	    	if(item.ContractField == oldItem.ContractField){
		    	Integer value = item.summary_asset_cost__c - oldItem.summary_asset_cost__c;
		    	contractsToUpdate.put(item.ContractField, value);
		    }
		    else{
		    	contractsToUpdate.put(item.ContractField, item.summary_asset_cost__c);
		    	contractsToUpdate.put(oldItem.ContractField, -oldValue.summary_asset_cost__c);
		    }
    	}
    }

    // get a map of the contracts and the costs of the assets on the contract
    List<Contract> contracts = [select id,asset_summary_cost__c from Contract where Id IN :contractsToUpdate.keySet()];

   for(Contract cnt:contracts){
   	Integer tmp = contractsToUpdate.get(cnt.Id);
   	if(tmp != null){
   		cnt.asset_summary_cost__c += tmp;
   	}
   		
     
    }

    update contracts;

}

 
Tyler DittoTyler Ditto
@R Z Khan I got some errors in it. The summary_asset_cost__C field is not on the Contract object so you can reference in the query on line 29.
Daniel Zeidler (DZ)Daniel Zeidler (DZ)
Here's my attempt to fix the above code so it works with bulk transactions.
 
trigger AssetTest on Asset(after delete, after insert, after update){

    Map<Id,Integer> contractsToUpdate = new Map<Id,Integer>();

if(trigger.isInsert){
    for (Asset item : Trigger.new)
        contractsToUpdate.put(item.ContractField, 0);

    for (Asset item : Trigger.new)
        contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField)  + item.summary_asset_cost__c);
}

    if (Trigger.isDelete) {
        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, 0);

        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField,  contractsToUpdate.get(item.ContractField) - item.summary_asset_cost__c);
    }
    if(trigger.isUpdate){
        for (Asset item : Trigger.new)
            contractsToUpdate.put(item.ContractField, 0);

        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, 0);

    	for(Asset item : trigger.new){
	    	Asset oldItem = trigger.oldMap.get(item.Id);
	    	if(item.ContractField == oldItem.ContractField){
		    	Integer value = item.summary_asset_cost__c - oldItem.summary_asset_cost__c;
		    	contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField) + value);
		    }
		    else{
		    	contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField) + item.summary_asset_cost__c);
		    	contractsToUpdate.put(oldItem.ContractField, contractsToUpdate.get(oldItem.ContractField) - oldValue.summary_asset_cost__c);
		    }
    	}
    }

    // get a map of the contracts and the costs of the assets on the contract
    List<Contract> contracts = [select id,asset_summary_cost__c from Contract where Id IN :contractsToUpdate.keySet()];

   for(Contract cnt:contracts){
   	Integer tmp = contractsToUpdate.get(cnt.Id);
   	if(tmp != null){
   		cnt.asset_summary_cost__c += tmp;
   	}
   		
     
    }

    update contracts;

}

 
Daniel Zeidler (DZ)Daniel Zeidler (DZ)
It should have been base_product_rev__c. Try this.
trigger AssetTest on Asset(after delete, after insert, after update){

    Map<Id,Integer> contractsToUpdate = new Map<Id,Integer>();

if(trigger.isInsert){
    for (Asset item : Trigger.new)
        contractsToUpdate.put(item.ContractField, 0);

    for (Asset item : Trigger.new)
        contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField)  + item.summary_asset_cost__c);
}

    if (Trigger.isDelete) {
        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, 0);

        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField,  contractsToUpdate.get(item.ContractField) - item.summary_asset_cost__c);
    }
    if(trigger.isUpdate){
        for (Asset item : Trigger.new)
            contractsToUpdate.put(item.ContractField, 0);

        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, 0);

    	for(Asset item : trigger.new){
	    	Asset oldItem = trigger.oldMap.get(item.Id);
	    	if(item.ContractField == oldItem.ContractField){
		    	Integer value = item.summary_asset_cost__c - oldItem.summary_asset_cost__c;
		    	contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField) + value);
		    }
		    else{
		    	contractsToUpdate.put(item.ContractField, contractsToUpdate.get(item.ContractField) + item.summary_asset_cost__c);
		    	contractsToUpdate.put(oldItem.ContractField, contractsToUpdate.get(oldItem.ContractField) - oldValue.summary_asset_cost__c);
		    }
    	}
    }

    // get a map of the contracts and the costs of the assets on the contract
    List<Contract> contracts = [select base_product_rev__c from Contract where Id IN :contractsToUpdate.keySet()];

   for(Contract cnt:contracts){
   	Integer tmp = contractsToUpdate.get(cnt.Id);
   	if(cnt.base_product_rev__c != null){
   		cnt.base_product_rev__c += tmp;
   	} else {
                cnt.base_product_rev__c = tmp;
        }
   		
     
    }

    update contracts;

}
R Z KhanR Z Khan
Hi replace that field with base_product_rev__c.
Tyler DittoTyler Ditto
Okay, now I am getting an error at line 35. oldValue.summary_asset_cost__c does not exist. Any idea what the issue is here?
R Z KhanR Z Khan
replace oldValue with oldItem
R Z KhanR Z Khan
trigger AssetTest on Asset(after delete, after insert, after update){

    Map<Id,Integer> contractsToUpdate = new Map<Id,Integer>();

if(trigger.isInsert){
    for (Asset item : Trigger.new)
    Integer value = contractsToUpdate.get(item.ContractField);
    if(value==null){
        value=0;
    }
        contractsToUpdate.put(item.ContractField, value+item.summary_asset_cost__c);
}

    if (Trigger.isDelete) {
        Integer value = contractsToUpdate.get(item.ContractField);
    if(value==null){
        value=0;
    }
        for (Asset item : Trigger.old)
            contractsToUpdate.put(item.ContractField, value-item.summary_asset_cost__c);
    }
    if(trigger.isUpdate){
        for(Asset item : trigger.new){
            Asset oldItem = trigger.oldMap.get(item.Id);

            if(item.ContractField == oldItem.ContractField){
                Integer value = contractsToUpdate.get(item.ContractField);
    if(value==null){
        value=0;
    }
                Integer difference = item.summary_asset_cost__c - oldItem.summary_asset_cost__c;
                contractsToUpdate.put(item.ContractField, value+difference);
            }
            else{
                  Integer value = contractsToUpdate.get(item.ContractField);
    if(value==null){
        value=0;
    }
                contractsToUpdate.put(item.ContractField, item.summary_asset_cost__c);
                contractsToUpdate.put(oldItem.ContractField,value -oldItem.summary_asset_cost__c);
            }
        }
    }

    // get a map of the contracts and the costs of the assets on the contract
    List<Contract> contracts = [select id,base_product_rev__c from Contract where Id IN :contractsToUpdate.keySet()];

   for(Contract cnt:contracts){
    Integer tmp = contractsToUpdate.get(cnt.Id);
    if(tmp != null){
        cnt.base_product_rev__c += tmp;
    }
        
     
    }

    update contracts;

}

this updated code should work for you.
Tyler DittoTyler Ditto
Line 10: incompatible value type Decimal for map <id, Integer>
R Z KhanR Z Khan
Change the map signature to Map<Id, Decimal> adn it will work
Tyler DittoTyler Ditto
I haven't built any test script for it, but there doesn't appear to be any errors thus far. Thanks, guys.
R Z KhanR Z Khan
Your welcome. Please mark this question as resolved if you don't have anymore questions
Tyler DittoTyler Ditto
Where would I place a where clause to state that I only want this to happen when the active_asset__c field on the Asset object is true?
Tyler DittoTyler Ditto
Basically using the script you commented with a couple changes to the field that the rollup summary is targeting. We are always creating new assets that need to be rolled up, but that is a circumstance where assets assets will become obsolete and in that circumstance the active_asset__c field on the Asset object is unchecked to false. When the field is false we don't want the sumary asset cost to roll up to the contract.
R Z KhanR Z Khan
Tyler sorry, I htought i was replying to another question about assets. Here is the solution. Fix any syntax error s if i missed sth
trigger AssetTest on Asset(after delete, after insert, after update){

    Map<Id,Integer> contractsToUpdate = new Map<Id,Integer>();

if(trigger.isInsert){
    for (Asset item : Trigger.new){
    if(item.active_asset__c){
            Integer value = contractsToUpdate.get(item.ContractField);
            if(value==null){
                value=0;
            }
            contractsToUpdate.put(item.ContractField, value+item.summary_asset_cost__c);
        }
    }
}

    if (Trigger.isDelete) {
        for (Asset item : Trigger.old){
            if(item.active_asset__c){
                Integer value = contractsToUpdate.get(item.ContractField);
                if(value==null){
                    value=0;
                }
                contractsToUpdate.put(item.ContractField, value-item.summary_asset_cost__c);
            }
        }
    }
    if(trigger.isUpdate){
        for(Asset item : trigger.new){
            Asset oldItem = trigger.oldMap.get(item.Id);
            if(item.active_asset__c){
                if(item.ContractField == oldItem.ContractField){
                    Integer value = contractsToUpdate.get(item.ContractField);
                    if(value==null){
                        value=0;
                    }
                    Integer difference = item.summary_asset_cost__c - oldItem.summary_asset_cost__c;
                    contractsToUpdate.put(item.ContractField, value+difference);
                }
                else{
                    Integer value = contractsToUpdate.get(item.ContractField);
                    if(value==null){
                        value=0;
                    }
                    contractsToUpdate.put(item.ContractField, item.summary_asset_cost__c);
                    contractsToUpdate.put(oldItem.ContractField,value -oldItem.summary_asset_cost__c);
                }
            }
        }
    }

    // get a map of the contracts and the costs of the assets on the contract
    List<Contract> contracts = [select id,base_product_rev__c from Contract where Id IN :contractsToUpdate.keySet()];

   for(Contract cnt:contracts){
    Integer tmp = contractsToUpdate.get(cnt.Id);
    if(tmp != null){
        cnt.base_product_rev__c += tmp;
    }
        
     
    }

    update contracts;

}