[SalesForce] Rollup summary of currency field using Apex Trigger

I have written an Apex Trigger to perform the rollup summary(sum ) operation.enter image description here.In the image "Total order Item value" field will be populated using trigger. And "Total Order Items" populates the value based on rollup summary.
The problem here is. under Total order Item Value instead of considering user define currency value, it is taking default company value which show with arrow.

Total Order Item Value will depend on (Quantity * Sell price)which returns value in usd. I want the same USD value under this field instead of converted.

Let me know thoughts.
Here is the code:

Apex class:

public class RollUpSummaryUtility {

    //the following class will be used to house the field names
    //and desired operations
    public class fieldDefinition {
        public String operation {get;set;}
        public String childField {get;set;}
        public String parentField {get;set;}

        public fieldDefinition (String o, String c, String p) {
            operation = o;
            childField = c;
            parentField = p;
        }
    }

    public static void rollUpTrigger(list<fieldDefinition> fieldDefinitions,
    list<sObject> records, String childObject, String childParentLookupField, 
    String parentObject, String queryFilter) {

        //Limit the size of list by using Sets which do not contain duplicate
        //elements prevents hitting governor limits
        set<Id> parentIds = new set<Id>();

        for(sObject s : records) {
            parentIds.add((Id)s.get(childParentLookupField));
        }

        //populate query text strings to be used in child aggregrator and 
        //parent value assignment
        String fieldsToAggregate = '';
        String parentFields = '';

        for(fieldDefinition d : fieldDefinitions) {
            fieldsToAggregate += d.operation + '(' + d.childField + ') ' + 
            ', ';
            parentFields += d.parentField + ', ';
        }

        //Using dynamic SOQL with aggergate results to populate parentValueMap
        String aggregateQuery = 'Select ' + fieldsToAggregate + 
        childParentLookupField + ' from ' + childObject + ' where  ' + 
        childParentLookupField + ' IN :parentIds ' + queryFilter + ' ' +
        ' group by ' + childParentLookupField;

        //Map will contain one parent record Id per one aggregate object
        map<Id, AggregateResult> parentValueMap = 
        new map <Id, AggregateResult>();

        for(AggregateResult q : Database.query(aggregateQuery)){
            parentValueMap.put((Id)q.get(childParentLookupField), q);
        }

        //list of parent object records to update
        list<sObject> parentsToUpdate = new list<sObject>();

        String parentQuery = 'select ' + parentFields + ' Id ' +
         ' from ' + parentObject + ' where Id IN :parentIds';

        //for each affected parent object, retrieve aggregate results and 
        //for each field definition add aggregate value to parent field
        for(sObject s : Database.query(parentQuery)) {

            Integer row = 0; //row counter reset for every parent record
            for(fieldDefinition d : fieldDefinitions) {
                String field = 'expr' + row.format();
                AggregateResult r = parentValueMap.get(s.Id);
                //r will be null if no records exist 
                //(e.g. last record deleted)
                if(r != null) { 
                    Decimal value = ((Decimal)r.get(field) == null ) ? 0 : 
                        (Decimal)r.get(field);
                    s.put(d.parentField, value);
                } else {
                    s.put(d.parentField, 0);
                }
                row += 1; //plus 1 for every field definition after first
            }
            parentsToUpdate.add(s);
        }

        //if parent records exist, perform update of all parent records 
        //with a single DML statement
        if(parentsToUpdate.Size() > 0) {
            update parentsToUpdate;
        }

    }

}

Trigger:

trigger GT_TotalOrderItem on OSF_Order_Items__c (after delete, after insert, 
after update, after undelete) {

    if(trigger.isInsert || trigger.isUpdate || trigger.isUnDelete){

        list<RollUpSummaryUtility.fieldDefinition> fieldDefinitions = 
        new list<RollUpSummaryUtility.fieldDefinition> {
            new RollUpSummaryUtility.fieldDefinition('SUM', 'Total_Selling_Price__c', 
            'Test_Total_Order_Item__c')
             };

        RollUpSummaryUtility.rollUpTrigger(fieldDefinitions, trigger.new, 
        'OSF_Order_Items__c', 'Opportunity__c', 'Opportunity', '');

    }

    if(trigger.isDelete){

        list<RollUpSummaryUtility.fieldDefinition> fieldDefinitions = 
        new list<RollUpSummaryUtility.fieldDefinition> {
            new RollUpSummaryUtility.fieldDefinition('SUM', 'Total_Selling_Price__c','Test_Total_Order_Item__c')

            };

        RollUpSummaryUtility.rollUpTrigger(fieldDefinitions, trigger.old, 
        'OSF_Order_Items__c', 'Opportunity__c', 'Opportunity', '');

    }

}

Best Answer

I don't see in your trigger or in your class where you're obtaining the currency of the order or the current exchange rate used by your company to calculate currency exchange.

Companies can do that differently through salesforce, depending on how they set-up multi-currency exchange (e.g. some do it quarterly). You'll need to add those factors into your class and either pass them to it through your trigger or have the class query the values.

EDIT

You'll want to look at these two links: Implications of Enabling Multiple Currencies and About Advanced Currency Management. I think they'll help provide more insight into the issues you're dealing with.

Edit2

Since you're using custom fields I recommend you review them to make certain they reflect the same type of values. There's often an Internal cost of some kind as in cost to make or purchase the item for your org, a Distributor cost or Partner cost and a Retail Cost. In my experience, depending on your org and how they've set things up, Opportunity can often reflect any one or a combination of these numbers, particularly when it comes to who they're being displayed to.

These decisions have other implications on VisualForce page bindings which don't affect your particular situation. Roll-up summary fields between two advanced currency management objects are also impacted when Advanced Currency Management is implemented. For example, roll-up summary fields are supported from an opportunity line object to its opportunity object, because both are advanced currency management enabled. However, if you enable advanced currency management, you can’t create roll-up summary fields that calculate currency on the opportunity object rolling up to the account object, and you can’t filter on the opportunity currency field on the account object. In your particular situation, since we're talking about an opportunity and it's children, plus with this being a trigger, there should be no impact.

Finally, a User's Settings determines which currency the Opportunity is displayed in. Your Org's Currency Management Settings determines how exchange rates are managed. If Advanced Currency Management is Enabled, normally Dated Exchange Rates are used for opportunities, opportunity products, opportunity product schedules, campaign opportunity fields, opportunity splits, and reports related to these objects and fields. Otherwise, Static conversion rates are used.

Based on the above, this tells me your problem is most likely either one of not having the correct fields you needed to perform your calculations (or to compare them to) or one of not having all the line items needed when performing your roll up calculations. Either that or there's a problem with your algorithm for calculating the roll-up summary value.

I hope you find this information useful to you in sorting your difficulties.

Related Topic