4

Objective : To populate INR__c field in Aus_Expense__c whenever INR__c is empty.

I have done the following.

-> Create a helper method in a separate class that will call the currency converter API and get the output. (This is working as expected..tested with anon apex)

Helper Method

public class CurrencyConvert {

    public static Decimal AusToINR()
    {
        String AUD_Value, INR_Value;
        Decimal AUD_d, INR_d, ftor;

        HTTPRequest req = new HTTPRequest();
        req.setEndPoint('http://api.fixer.io/latest?base=USD');
        req.setMethod('GET');

        HTTP h = new HTTP();
        HTTPResponse resp = h.send(req);
        System.debug('Response Status : '+resp.getStatus());
        System.debug('Response Status Code : '+resp.getStatusCode());
        System.debug('Response Body : '+resp.getBody());
        String response_string = String.ValueOf(resp.getBody());

        JSONParser parser = JSON.createParser(response_string);
        while(parser.nextToken() != null)
        {

            if(parser.getCurrentToken() == JSONToken.FIELD_NAME)
            {
                if(parser.getText() == 'AUD')
                {
                    parser.nextToken();
                    AUD_Value = parser.getText();
                }
                if(parser.getText() == 'INR')
                {
                    parser.nextToken();
                    INR_Value = parser.getText();
                }
            }
        }

        AUD_d = Double.valueOf(AUD_Value);
        INR_d = Double.valueOf(INR_Value);

        ftor = INR_d/AUD_d;
        Decimal rounded = ftor.setScale(2);

        System.debug('AUD_Value : '+AUD_Value);
        System.debug('INR_Value : '+INR_Value);
        System.debug('AUD_D : '+AUD_D);
        System.debug('INR_D : '+INR_D);
        System.debug('ftor : '+ftor);
        System.debug('Rounded ftor :'+rounded);

        return rounded;
    }
}

-> Call this helper method in trigger

Trigger code

trigger AusExpenseTrigger on Aus_Expense__c (before insert,before update) {

    List<Aus_Expense__c> aus_expenses = Trigger.New;

    for(Aus_Expense__c a : aus_expenses)
    {
        if(a.INR__c == null)
        {
            a.INR__c = a.Amount__c * CurrencyConvert.AusToINR();
        }
    }
}

The trigger compiles successfully but upon making an actual DML from the UI it shows the following error.

enter image description here

Question : I believe that I should @future notation to the helper method. But doing so will not allow me to return the "rounded" value from that helper method.

What can be done in this scenario ?. I even thought of creating single field Custom settings and update the custom settings record for every API call and do a SOQL on that record to get the "rounded" value.

Am I over-complicating this ? Is there a technique to call a webservice from trigger and that too when you expect a value (non-void) from the webservice ?

  • yes you need to use future method with allow callout – Ratan Paul Jan 21 '16 at 5:06
1

You can use following approach as you need to update the record with converted currency value:-

  1. Write a future annoted method in trigger with (callout=true). It should be able to pass parameter.
  2. If webservice support bulk conversion then you can pass list of Ids.
  3. Write webservice code inside future method.
  4. Make the callout and update those records with value inside future method.

But you will have to prevent recursion of trigger as update/insert will fire trigger again. In this case you can use a checkbox field which can tell the code that update has been done no need to call future method or anything. There are many possible way to prevent trigger fire again.

  • 2
    You can use System.isFuture() in trigger to avoid recursion which returns true if the trigger is called because of the DML in future method – Samir Feb 28 '17 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.