6

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', '');

    }

}
2

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.

|improve this answer|||||
  • i'm trying to populate along with the currency but y it is converted and displaying – Sindoora Jul 10 '14 at 4:44
  • See my latest edit to my answer – crmprogdev Jul 10 '14 at 14:28
  • If your RSF field is of type Currency - SFDC is going to control the display. If your RSF field is always supposed to be USD, then make it type Numeric and use a label like my Field (USD). You will then have to take responsibility for doing the proper currency conversion – cropredy Jul 10 '14 at 18:16
  • we have enabled ACM because of this it displays an hour glass besides rollup summary fields and its dependancy. So to remove that we have written the trigger. secondly we have multi currency enabled and my org value is in euro. so when we observe the value in the child is $8000 for example.then my trigger converting this 8000 into euros and displaying as $5,880(euro4,321) which means it is converting the value into euro and displayed as $. And the expected value is $8000(euro5,880.) – Sindoora Jul 11 '14 at 11:37
  • 1
    assuming this is still open, it looks like you want to sum OSF_Order_Items__c.Total_Selling_Price__c and place into Opportunity.Test_Total_Order_Item__c. You are summing using SOQL Aggregate functions. Per doc: If a query includes a GROUP BY or HAVING clause, any currency data returned by using an aggregate function, such as SUM() or MAX(), is in the organization's default currency (EUR). Using your scenario above, what decimal value is returned by the aggregate query, what is the Opportunity CurrencyIsoCode, and what is the decimal value in Opportunity.Test_Total_Order_Item__c? – cropredy Aug 21 '14 at 4:48

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.