Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for advanced currency management orgs (also known as dated exchange rate) #591

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Kilay
Copy link

@Kilay Kilay commented Nov 30, 2017

Added support for advanced currency management orgs (issue #82 )
Replace PR #583

@afawcett
Copy link
Collaborator

@Kilay sorry for the late response on this.

  • Can you update the CurrencyManagement class to use soley dynamic SOQL. The reason i ask is that the package will upload with a dependency on this org feature which blocks its use for non-advanced currency use cases.
  • Also i noticed the test had the asserts commented out here can you comment on this please?

Thanks, and sorry again for the delay in responding.

Andy

@Kilay
Copy link
Author

Kilay commented Mar 21, 2018

@afawcett

  • Not sure why I commented out these assertions. I run tests again with asserts uncommented and it works well
  • I am not very familiar with package dependency in Salesforce. Is it alright with this CurrencyManagement class :
public with sharing class CurrencyManagement {
    private static Map<Id, Sobject> dcrMap;
    private static String corporateCurrency;

    public static Boolean isCorporateCurrency(String currencyIso) {
        if(corporateCurrency == null) {
			Sobject corporateCurrencyType = Database.query('SELECT IsoCode FROM CurrencyType WHERE IsActive = true AND IsCorporate = true');
			corporateCurrency = (String) corporateCurrencyType.get('IsoCode');
        }
        return currencyIso == corporateCurrency;
    }

    public static Decimal convertToCorporateCurrency(String currencyIso, Decimal currencyVal, Date currencyDate) {
        Decimal res;
        if(currencyIso != null && currencyVal != null && !CurrencyManagement.isCorporateCurrency(currencyIso)) {
            if(dcrMap == null) {
                dcrMap = new Map<Id, Sobject>(Database.query('SELECT Id, IsoCode, ConversionRate, StartDate, NextStartDate FROM DatedConversionRate'));
            }
            for(Sobject dcr: dcrMap.values()) {
                if((String) dcr.get('IsoCode') != currencyIso) continue;   // look for a match in table against input currency
                if(currencyDate < (Date) dcr.get('StartDate') || currencyDate >= (Date) dcr.get('NextStartDate')) continue;   // not in the range of effective dates
                res =  currencyVal / (Decimal) dcr.get('ConversionRate');
                break;
            }
        }
        else if(currencyIso != null && CurrencyManagement.isCorporateCurrency(currencyIso)) {
            return currencyVal;
        }
        return res;
    }

    public static Decimal convertFromCorporateCurrency(String currencyIso, Decimal currencyVal, Date currencyDate) {
        Decimal res;
        if(currencyIso != null && currencyVal != null) {
            if (dcrMap == null) {
                dcrMap = new Map<Id, Sobject>(Database.query('SELECT Id, IsoCode, ConversionRate, StartDate, NextStartDate FROM DatedConversionRate'));
            }
            for(Sobject dcr: dcrMap.values()) {
                if((String) dcr.get('IsoCode') != currencyIso) continue;   // look for a match in table against input currency
                if(currencyDate < (Date) dcr.get('StartDate') || currencyDate >= (Date) dcr.get('NextStartDate')) continue;   // not in the range of effective dates
                res =  currencyVal * (Decimal) dcr.get('ConversionRate');
                break;
            }
        }
        return res;
    }
}

@Kilay
Copy link
Author

Kilay commented Apr 5, 2018

@afawcett : Is it what you meant by "using soley dynamic SOQL" ?

@afawcett
Copy link
Collaborator

@Kilay yep thats it. So i am going to focus this weekend on getting this merged. Its tricky because i changed the source format to move to DX since. However i'll get it done! 👍

@afawcett
Copy link
Collaborator

afawcett commented Apr 14, 2018

@Kilay just taking a closer look at these changes. Did you wire up the new functionality in LREngine to the rest of the code base? How does the user actually configure this without flowing it through RollupService and the defining it via the picklist on the custom object/metadata types? I can wire this up myself, but just wanted to check if these files are just missing from the PR by accident?

@afawcett
Copy link
Collaborator

@Kilay can you also tell me a bit more about the motivation behind the setDateField and addAdditionalField methods and the use case behind them? I think i can see what the intent is by looking at the tests. But a bit more background from you would be useful. Thanks! 👍

afawcett added a commit that referenced this pull request Apr 15, 2018
@afawcett
Copy link
Collaborator

FYI: I have started a branch (using the new DX format for the repo) with these changes in. https://github.com/afawcett/declarative-lookup-rollup-summaries/tree/advanced-currency.

@Kilay
Copy link
Author

Kilay commented Apr 16, 2018

@Kilay just taking a closer look at these changes. Did you wire up the new functionality in LREngine to the rest of the code base? How does the user actually configure this without flowing it through RollupService and the defining it via the picklist on the custom object/metadata types? I can wire this up myself, but just wanted to check if these files are just missing from the PR by accident?

You are right, I didn't wire up to the rest of the code because I am only using the LREngine via custom apex code. Let me know if you need some help.

@Kilay can you also tell me a bit more about the motivation behind the setDateField and addAdditionalField methods and the use case behind them? I think i can see what the intent is by looking at the tests. But a bit more background from you would be useful. Thanks!

setDateField method defined which date field should used in order to get the correct rate to use. It can be a field on the same object (like Opportunity is using CloseDate field) or from a related object (like OpportunityLineItem is using CloseDate field from related Opportunity). That is why I have a setDateLookupField function to set the related object where the date field is. I refactored this a little bit to have only one function for this, I will try to update the PR soon.

addAdditionalField method can be used to get more field from the parent object (as it uses a SOQL with GROUP function, we can only get information from the parent object and not the child object).
For instance, I need to tag Opportunity as "Late Renewal" when "Contract Start Date" on at least one OpportunityLineItem is after the Opportunity CloseDate and vice versa. I cannot only query OpportunityLineItem where "Contract Start Date" are after Opportunity CloseDate because it will never untag "Late Renewal". Here is a sample code :

// Define rollup context (Parent : Opportunity, Child : OpportunityLineItem, rollup only before PO Received)
LREngine.Context opportunityCtx = new LREngine.Context(
	Opportunity.SobjectType,
	OpportunityLineItem.SobjectType,
	Schema.SObjectType.OpportunityLineItem.fields.OpportunityId,
	'Opportunity.IsClosed = false AND Opportunity.StageName != \'PO Received\''
);
// Define rollup (rollup Start Date to Contract Start Date using MIN)
opportunityCtx.add(
	new LREngine.RollupSummaryField(
		Schema.SObjectType.Opportunity.fields.Contract_Start_Date__c,
		Schema.SObjectType.OpportunityLineItem.fields.Start_date__c,
		LREngine.RollupOperation.Min
	)
);
// Add Close Date field to query
opportunityCtx.addAdditionalField(Schema.SObjectType.Opportunity.fields.CloseDate);

// Rollup
List<sObject> masters = LREngine.rollUp(opportunityCtx, rollupStartDate);
for(sObject master : masters) {
	// Update only if the rolled up Contract Start Date is not null
	if(!mastersToUpdate.containsKey(master.Id) && master.get('Contract_Start_Date__c') != null) {
		// If Close Date is in a month after min Start Date, tag as Late
		Date closeDate = (Date) master.get('CloseDate');
		if ((master.get('Opportunity_Type__c') == 'Contract Renewal - Customer has no licenses to credit' || master.get('Opportunity_Type__c') == 'Maintenance/Subscription - Defined by existing contract') && Date.newInstance(closeDate.year(), closeDate.month(), 1) > (Date) master.get('Contract_Start_Date__c')) {
			master.put('Late__c', true);
		} else {
			master.put('Late__c', false);
		}

		mastersToUpdate.put(master.Id, master);
	}
}

@afawcett
Copy link
Collaborator

afawcett commented Apr 22, 2018

Thanks @Kilay. So the LREngine class is from another repo, this tool wraps this class to expose its features to admins without code. So while your changes are valid for this class, it might be best to apply (either now or after) to the original repo. https://github.com/abhinavguptas/Salesforce-Lookup-Rollup-Summaries. Meanwhile i will keep the branch open and update the rest of the code to pick up your change so that admins can use it. Thanks again, i will re-read your code and description a again later and may have more questions, but for now it seemed to have made sense! Thanks!

@Kilay
Copy link
Author

Kilay commented Apr 24, 2018

I had the same thought so I submitted (almost a year ago) a PR to this repo (abhinavguptas/Salesforce-Lookup-Rollup-Summaries#19). But it seems that this repo is not maintained as I never get any answer.
I finally ended started with LREngine from your repo because your LREngine class is already "in advanced" compared to the one in original repo.

@afawcett
Copy link
Collaborator

@Kilay understood.

@timteagueuk
Copy link

@afawcett what can I do here as I believe this issue is messing up my roll up. Any advice is appreciated. Our corporate currency is GBP but we have opps in USD, EURO and dates exchange rates. Please see a better explanation here https://success.salesforce.com/answers?id=9063A000000t1wx

@timteagueuk
Copy link

timteagueuk commented Sep 4, 2018

Please enable and fix as this has made us very stuck see #733 will this be fixed anytime soon or shall we uninstall the tool? Please can you also make it clear on the app that this isn't supported as we rolled out a subscription spend process that had to be halted.

@harrisoe69
Copy link

@afawcett have there been any developments to this issue?

@jbunford
Copy link

I'd also love an update. Currently considering using free-RUH and DLRS in tandem which I'd rather not do!

@CSchulenburg
Copy link

Any update an is there a work around available?

Thanks
Christian

@afawcett
Copy link
Collaborator

afawcett commented Apr 6, 2020

Yes this is a long standing PR sorry folks. Its deep in the tool of course. Meanwhile any thoughts on the formula field workaround here > #859?

@Szandor72 Szandor72 marked this pull request as draft July 23, 2022 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants