This is definitely possible with a trigger. To give you some pseudo code, I would write your trigger on the Invoice__c
object. It will handle any updates of the Invoice_Line_Item__c
object because of the rollup summary. You will want to have something like:
trigger InvoiceTrigger on Invoice__c (after insert, after update) {
if(Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)){
InvoiceTriggerHandler.updateAccountBalance(Trigger.newMap);
}
}
public class InvoiceTriggerHandler{
public static void updateAccountBalance(Map<Id, Invoice__c> invoices){
AggregateResult[] results = [
SELECT
Account__c, SUM(Total_Price__c)
FROM
Invoice__c
WHERE
Id IN :invoices.keySet
GROUP BY
Account__c
];
Set<Account> accountsToUpdate = new Set<Account>();
for(AggregateResult result:results){
accountsToUpdate.add(new Account(
Id = result.get('Account__c'),
Account_Balance__c = result.get('expr0')
);
}
update accountsToUpdate;
}
}
You will have to clean that up and write your own tests, but that is the general idea. Every time an Invoice_Line_Item__c
is updated and it changes the rollup summary field, this trigger will fire to update the account. There is some additional logic you may want to add, such as checking the old value of the Total_Price__c
field with the new value and only running through Accounts who have had Invoice__c
changes rather than all of them. There may be some other ways to tweak this as well, I just quickly wrote this up. Keep in mind this is not production ready by any means, but I hope this points you in the right direction.
The approach above utilizes aggregate functions and setting Id fields for update.
EDIT: I originally had the following code, which should still work, but the above is more optimal.
trigger InvoiceTrigger on Invoice__c (after insert, after update) {
if(Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)){
InvoiceTriggerHandler.updateAccountBalance(Trigger.new);
}
}
public class InvoiceTriggerHandler{
public static void updateAccountBalance(List<Invoice__c> invoices){
Set<Id> accountIds = new Set<Id>();
for(Invoice__c invoice:invoices){
accountIds.add(invoice.Account__c);
}
List<Account> accounts = [SELECT Id, Account_Balance__c, (SELECT Id, Total_Price__c FROM Invoices__r) FROM Account WHERE Id IN :accountIds];
for(Account acc:accounts){
acc.Account_Balance__c = 0;
for(Invoice__c invoice:acc.Invoices__r){
acc.Account_Balance__c += invoice.Total_Price__c;
}
}
update accounts;
}
}
I wonder if the fact that you once had advanced currency management enabled may be affecting this if you ever used it. Sometimes when you turn a feature on and use it, I believe certain internal 'flags' might get set. So even though you turn it off, there could be something internally that indicates that it was used. Again, this is all speculation on my part but it is based on a recent experience with trying to delete an approval workflow to replace it with a new one.
Even though I disabled the workflow, one user had used it to get something approved and this prevented it from being deleted. I had to delete the record that was approved, empty the recycle bin, re-create the original record, and resubmit it for approval. Just a thought.
One thing is for sure though - advanced currency management does get in the way of doing roll-ups like this. There is an Idea that you could vote up if it bothers you. It bothers me ... a lot!
https://success.salesforce.com/ideaView?id=08730000000BqMq
Best Answer
In a multi-currency org, all opportunities are stored in the org's default currency. It's simply a case of opportunities being entered in a user's default currency. However, once entered, they should be converted to the org's default currency using either the current conversion rate or the dated conversion rate if advance currency management is enabled. See Implications of Enabling Multiple Currencies for more on this.
If you want to see the roll-ups in your converted currency, you'll need to create a page that converts them to that currency after each rollup calculation. You may want to create some custom apex or formula fields that automatically do this for you for use with that page.
EDIT
After looking at your code, I see you're using queries. See Querying Currency Fields in Multi-currency Orgs. The following syntax is for using convertCurrency() with the SELECT clause:
convertCurrency(field)