Coding question asked by Google
Develop a Trigger on asset to count the amount of assets for a specific account. The value of the asset should increate on insert or undeleteand decrease on delete or reparent to a new account.
Assumption: an asset cannot have a null AccountId, validation rule will fail and not save the record. Asset should always have a lookup to an account.
Apex Asset Trigger
trigger AssetTrigger on Asset (after insert, after update, after delete, after undelete) {
Integer incDecVal = 1;
if (Trigger.isDelete){
incDecVal = -1;
}
AssetHelper.countAccountAssets(trigger.newMap, trigger.oldMap, incDecVal);
}
Apex asset helper class
public with sharing class AssetHelper {
public static void countAccountAssets(Map<Id, Asset> newAssets, Map<Id, Asset> oldAssets, Integer incrementDecrementVal){
Set<Id> accountIds = new Set<Id>();
if (newAssets!=null){
for (Asset newAsset : newAssets.values())
accountIds.add(newAsset.AccountId);
}
if (oldAssets!=null){
for (Asset oldAsset : oldAssets.values())
accountIds.add(oldAsset.AccountId);
}
Map<Id, Account> accountMap = new Map<Id, Account>([Select Id, Total_Assets__c from Account where Id IN :accountIds]);
Set<Account> updateAccountSet = new Set<Account>();
if (newAssets!=null){
for (Id newAssetId : newAssets.keySet()){
Asset newAsset = newAssets.get(newAssetId);
if (accountMap.containsKey(newAsset.AccountId)){
Account updateAccount = accountMap.get(newAsset.AccountId);
updateAccount.Total_Assets__c += incrementDecrementVal;
if (updateAccount.Total_Assets__c < 0){
updateAccount.Total_Assets__c = 0;
}
updateAccountSet.add(updateAccount);
}
}
}
if (oldAssets!=null){
for (Id oldAssetId : oldAssets.keySet()){
Asset oldAsset = oldAssets.get(oldAssetId);
if (accountMap.containsKey(oldAsset.AccountId)){
Account updateAccount = accountMap.get(oldAsset.AccountId);
if (newAssets!=null && newAssets.containsKey(oldAssetId)){
Asset newAsset = newAssets.get(oldAssetId);
if (oldAsset.AccountId!=newAsset.AccountId){
updateAccount.Total_Assets__c -= incrementDecrementVal;
}
} else {
updateAccount.Total_Assets__c += incrementDecrementVal;
}
if (updateAccount.Total_Assets__c < 0){
updateAccount.Total_Assets__c = 0;
}
updateAccountSet.add(updateAccount);
}
}
}
Savepoint sp = Database.setSavePoint();
try{
Database.update(new List<Account>(updateAccountSet));
} catch(DMLException ex){
Database.rollback(sp);
}
}
}
Apex asset helper test class
@isTest public class AssetHelperTest {
@TestSetup static void setupAssetAccount(){
Account setupAccount = new Account(Name='Test Account', Total_Assets__c=0);
insert setupAccount;
Asset setupAsset = new Asset(AccountId=setupAccount.Id, Name='Test Asset Setup');
insert setupAsset;
}
@isTest static void testInsertAsset(){
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 1);
}
@isTest static void testDeleteAsset(){
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 1);
Test.startTest();
delete [Select Id from Asset][0];
Test.stopTest();
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 0);
}
@isTest static void testUnDeleteAsset(){
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 1);
Asset deleteAsset = [Select Id from Asset][0];
delete deleteAsset;
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 0);
Test.startTest();
undelete deleteAsset;
Test.stopTest();
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 1);
}
@isTest static void testReparent(){
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 1);
Account newAccount = new Account(Name='New Account', Total_Assets__c=0);
insert newAccount;
Asset updateAsset = [Select Id, AccountId from Asset][0];
updateAsset.AccountId = newAccount.Id;
Test.startTest();
update updateAsset;
Test.stopTest();
System.assertEquals([Select Total_Assets__c from Account][0].Total_Assets__c, 0);
System.assertEquals([Select Total_Assets__c from Account where Id=:newAccount.Id][0].Total_Assets__c, 1);
}
}
Is it a bad idea to simply increase per record in newMap and decrease per record in oldMap?
public with sharing class AssetTriggerHandler {
public static void updateAccounts(Map newMap, Map oldMap){
//get the all Id of the accounts that needs update
Set accountIds = new Set();
if(newMap!=null){
for(Asset asset : newMap.values()){
accountIds.add(asset.AccountId);
}
}
if(oldMap!=null){
for(Asset asset : oldMap.values()){
accountIds.add(asset.AccountId)
;
}
}
//retrieve accounts
MapaccountMap = new Map([SELECT Total_Assets__c FROM Account WHERE Id IN: accountIds]);
List updateAccounts = new List();
if(newMap!=null){
for(Asset asset : newMap.values()){
Account updateAcc = accountMap.get(asset.AccountId);
updateAcc.Total_Assets__c += 1;
updateAccounts.add(updateAcc);
}
}
if(oldMap!=null){
for(Asset asset : oldMap.values()){
Account updateAcc = accountMap.get(asset.AccountId);
updateAcc.Total_Assets__c -= 1;
updateAccounts.add(updateAcc);
}
}
//update accounts
update updateAccounts;
}
}