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
Brian LiederBrian Lieder 

"touching" assets to trigger code

I am asking this question for our Developer, i am an Admin.

We have some code on the account layout that does a calculation on the Assets object.  Serves as a rollup since we cannot directly do a rollup summary.  The code works, the only issue is an Asset must be "touched" in order for the code to do its job.  The question is how can we get the code to run it's calculation without having to manually edit and save an asset?  
Best Answer chosen by Brian Lieder
matt.ian.thomasmatt.ian.thomas
I realized that there was the time portion of your question after I posted this. You could either execute the code in a scheduled job, OR use a time-based workflow that has a field update which would subsequently invoke this trigger.

All Answers

matt.ian.thomasmatt.ian.thomas
Can you give some more info on what that calculation is? It sounds like it's some sort of aggregate of all or a subset of all Assets on a given Account. In that case, why would you want the calculation to be run if an Asset wasn't touched? It's best in cases like this to only calculate when you absolutely need to.
Brian LiederBrian Lieder
Yes, the calculation adds all assets that have a sale date in the specified time period (last 365 days).  The problem is that this concept relies on there being a change every day so that the code will run.  If an account has no sales for, say 3 weeks, the number will not update since there was no trigger to make the code run.  I need the number to update daily 
matt.ian.thomasmatt.ian.thomas
trigger AssetTrigger on Asset (after delete, after insert, after update) {
	/**	We need to use the after contexts in this trigger, since if some sort of exception were to
	cause dml to fail, then we could possibly recalculate the number assuming that the dml succeeded,
	it fails, and we're left with an incorrectly calculated number.
	**/
	if (trigger.isDelete || trigger.isInsert) {
		/**	We need to build a list of the record ids in trigger.new that match our criteria
		so we can get all of the Accounts that we need to recalculate in one SOQL query in the
		event that we have a large batch from something like a batch data load.
		**/
		Set<Id> accountIds = new Set<Id>();
		for (Asset asset : trigger.new) {
			if (System.today() - asset.SalesDate__c <= 365) { //This is probably not what you need, but you get the point.
				accountIds.add(asset.AccountId);
			}
		}
		/** Now that we have all of the account ids that we care about, we'll get all of the 
		Accounts and all of their assets so that we can just use .size() on the Assets collection.
		**/
		List<Account> accountsThatNeedRecalculation = [Select Id, (Select Id From Asset Where TODAY() - SalesDate__c <= 365) From Account Where Id IN: accountIds];
		for (Account account : accountsThatNeedRecalculation) {
			account.CalculatedField__c = account.Assets.size();
		}

		try {
			update accountsThatNeedRecalculation;
		}
		catch (SomeException ex) {
			//Do something to handle this.
		}
	}
	else if (trigger.isUpdate) {
		/** Nearly the same logic as insert or delete contexts, but you need to use trigger.oldMap
		to determine if the record has been modified to meet the need to recalculate, not just meets the need
		since it's possible that some other field was edited. In that case, we don't care.
		**/
		Set<Id> accountIds = new Set<Id>();
		for (Asset asset : trigger.new) {
			if (System.today() - asset.SalesDate__c <= 365 && asset.SalesDate__c != trigger.oldMap.get(asset.Id).SalesDate__c) {//The second part of this is the only difference.
				accountIds.add(asset.AccountId);
			}
		}
		//Same as above.
	}
}
matt.ian.thomasmatt.ian.thomas
I realized that there was the time portion of your question after I posted this. You could either execute the code in a scheduled job, OR use a time-based workflow that has a field update which would subsequently invoke this trigger.
This was selected as the best answer
Brian LiederBrian Lieder
Both of those options make sense, i will work toward the scheduled job.  Thanks a ton for the help