I'm trying to update a field on the account field with a trigger using after insert and update. I am using a future method to make a callout to a rest API to get the rate of BTC in USD.
My issue is that I am getting this error when I try to execute a DML statement within the future method.
The error: FATAL_ERROR System.DmlException: Update failed. First exception on row 0 with id 0016800000UlQ04AAF; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountTrigger: execution of AfterUpdate
The trigger handler calls the callFutureMethod() method which in turn calls the method that executes the callout to the API.
Class & methods that make the callout to the API:
public static List <Account> accountsWithAlteredRevenueList = new List <Account>();
public static Set <Id> accountIdsSet = new Set <Id>();
//AFTER
public void getAccountsFromTrigger(Account account) {
if (!accountIdsSet.contains(account.Id)) {
accountsWithAlteredRevenueList.add(account);
accountIdsSet.add(account.Id);
system.debug('ADDED IN ACCOUNT');
} else {
system.debug('ALREADY IN THERE');
}
}
public static void callFutureMethod() {
String serialised_list = JSON.serialize(accountsWithAlteredRevenueList);
getDefaultCurrencyRateInBTC(serialised_list);
}
@future(callout=true)
public static void getDefaultCurrencyRateInBTC(String serialised_list){
Decimal rate = 0;
HttpRequest req = new HttpRequest();
req.setEndpoint('https://bitpay.com/api/rates');
req.setMethod('GET');
HttpResponse res = new Http().send(req);
List<Object> all_currency_info = new List<Object>();
if (res.getStatusCode() == 200) {
List<Object> response_data = (List<Object>) JSON.deserializeUntyped(res.getBody());
for (Object obj : response_data) {
all_currency_info.add(obj);
}
}
for (Object single_currency : all_currency_info) {
Map<String, Object> currencies_map = (Map<String, Object>)single_currency;
if (currencies_map.containsKey('rate') && currencies_map.get('code') == 'USD') {
rate = (Decimal)currencies_map.get('rate');
defaultRate = rate;
CalculateAnnualRevInBTC.annualRevInBTC(serialised_list, defaultRate);
break;
}
}
}
This is the method that is called within the future method to execute a DML action.
public static void annualRevInBTC(String serialised_list, Decimal rate) {
List <Account> update_revenues = new List <Account>();
List <Account> deserialised_account_list = deserialiseList(serialised_list);
for (Account acc : deserialised_account_list) {
acc.Annual_Revenue_Bitcoin__c = (acc.AnnualRevenue / rate).setScale(8);
//After
update_revenues.add(acc);
}
//AFTER
if (!update_revenues.isEmpty()) {
update update_revenues;
}
}
Any suggestions that can help me avoid this error will be welcome. Thanks in advance!