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
Account Soft Credits: Object and Rollups integration #3220
Conversation
@@ -48,6 +48,8 @@ private class CRLP_RollupAccount_TEST { | |||
private static void setupBaseTestData() { | |||
Contact c = UTIL_UnitTestData_TEST.getContact(); | |||
insert c; | |||
Account acc = UTIL_UnitTestData_TEST.createMultipleTestAccounts(1, CAO_Constants.HH_ACCOUNT_TYPE)[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not create a new unit test class that specifically validates Account Soft Credits, and can test both batch jobs? I see that this does test one Account Soft Credit rollup, but coverage of the two new batch classes is is only around 25%. Does it make sense to create a new unit test class that more completely tests various rollup types and conditions for just Account Soft Credit by itself?
Account_Soft_Credit__c accSC = new Account_Soft_Credit__c ( | ||
Amount__c = scAmount, | ||
Account__c = softCreditAcc.Id, | ||
Opportunity__c = opps[i].Id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth setting a Role value and validating the filter rule against the Role? Right now, it's just including all ASC records. I think more detailed test should validate that its only including the correct ASC records using Filter Rules.
src/classes/CRLP_VRollupHandler.cls
Outdated
@@ -53,6 +53,8 @@ public virtual class CRLP_VRollupHandler implements CRLP_Rollup_SVC.IRollupHandl | |||
protected final String allocObjectName = UTIL_Describe.getObjectDescribe(UTIL_Namespace.StrAllNSPrefix('Allocation__c')).getName(); | |||
/* @description 'Name' of the object referenced in the rollup. Visible to classes that extend this virtual class. */ | |||
protected final String rdObjectName = UTIL_Describe.getObjectDescribe('npe03__Recurring_Donation__c').getName(); | |||
/* @description 'Name' of the object referenced in the rollup. Visible to classes that extend this virtual class. */ | |||
protected final String ascObjectName = UTIL_Describe.getObjectDescribe(UTIL_Namespace.StrAllNSPrefix('Account_Soft_Credit__c')).getName(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this is used anywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of them in this section aren't -- all but opp and payment, from the looks of it. Should we remove all of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bethbrains Good point. I added them early on thinking they'd be used. Feel free to remove any of them ones that are not referenced in this class or the classes that implement this class.
// BEFORE INSERT | ||
if (triggerAction == TDTM_Runnable.Action.BeforeInsert) { | ||
synchronizeCurrencyIsoCode(listNew); | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the return null;
needed here and in the next if block?
private void synchronizeCurrencyIsoCode(list<Account_Soft_Credit__c> listAccSC) { | ||
|
||
// collect all our Opps and Contacts referenced by the PSC's | ||
set<Id> setOppId = new set<Id>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Collection types and var declarations in this class need to use capital letters:
Set
, List
, String
, Map
, Integer
Account_Soft_Credit__c accSCOld = listAccSCOld[i]; | ||
|
||
// don't allow manually changing the AccSC currency: it must be changed through the parent opportunity | ||
if (userInfo.isMultiCurrencyOrganization() && accSCNew.get('CurrencyIsoCode') != accSCOld.get('CurrencyIsoCode') && blockCurrencyChange) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this static var has a similar name to this method, I suggest specifying the class name for it: OPP_AccountSoftCredit_TDTM .blockCurrencyChange
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to understand the rationale here a bit better at some point. Thanks.
src/classes/PSC_Opportunity_TDTM.cls
Outdated
if (objType == Partial_Soft_Credit__c.SObjectType) { | ||
//query all PSCs associated with these opps, update their ISO code | ||
for (Partial_Soft_Credit__c psc : database.query('SELECT Id, Opportunity__c, CurrencyIsoCode FROM Partial_Soft_Credit__c WHERE Opportunity__c IN :oppIds')) { | ||
string oppCurrency = mapOppIdToISO.get(psc.Opportunity__c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capitalization of var types and collections should be fixed in your new code/method.
src/classes/PSC_Opportunity_TDTM.cls
Outdated
|
||
psc.put('CurrencyIsoCode', oppCurrency); | ||
results.add(psc); | ||
accountSC.put('CurrencyIsoCode', oppCurrency); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems that the code that updates the AccountSoftCredit and PartialSoftCredit Currency code is not actually working correctly.
In the example below, I started with a $151 USD Opportunity that had one AccountSoftCredit for $151, one PartialSoftCredit for $1 and one Payment for $151. I then changed the Opportunity.Currency to CAD (where the CAD exchange rate is 1.33). When saved, the Opportunity changes to CAD$151 (USD $113.53). The payment update does the same thing (i.e., the two amounts match). That is not the case for the AccountSoftCredit and PartialSoftCredit objects though. In these cases, the amounts changed to CAD$200.83 and CAD$1.33 respectively. See the PMT_Payment_TDTM.setPaymentCurrencyFromOpportunity
method for an example of how this is handled to ensure the amount is correct. Basically, you have to update both the CurrencyIsoCode and the Amount fields.
* @description Scheduler execute method to support scheduling this job directly from the UI | ||
*/ | ||
public void execute(SchedulableContext context) { | ||
String className = CRLP_AccountSkew_AccSoftCredit_BATCH.class.getName(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bethbrains It seems that using .class.getName()
returns back a namespaced class in the format of npsp.CRLP_AccountSkew_AccSoftCredit_BATCH
as opposed to npsp__ CRLP_AccountSkew_AccSoftCredit_BATCH
. This means that the hasRunningJob()
method that attempts to strip out the namespace does not actually work properly in a namespaced org. That code should be changed to use something like className.substringAfter('.');
to get the part of the string after the ".". Even though it's a bug not specific to Account Soft Credits, I'm fine if you include that fix in here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bethbrains Just making sure you saw this above comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/labels/CustomLabels.labels
Outdated
@@ -4634,7 +4634,7 @@ To check your GAU Allocation settings, go to Donations | GAU Allocations.</value | |||
<language>en_US</language> | |||
<protected>false</protected> | |||
<shortDescription>pscManageSoftCreditsCantChangeCurrency</shortDescription> | |||
<value>You can't modify Partial Soft Credit currencies directly. Update the parent Opportunity's currency, and NPSP will automatically update the curency of all related Partial Soft Credit records.</value> | |||
<value>You can't modify soft credit currencies directly. Update the parent Opportunity's currency, and NPSP will automatically update the currency of all related soft credits.</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smarovich FYI this small change because we're using the same error message on PSC and AccSC. OK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments/Suggestions on updated code
* Created by bbreisnes on 2018-07-31. | ||
*/ | ||
|
||
public with sharing class CRLP_RollupAccSoftCredit_TEST { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be `private' without a sharing declaration to match the format of all the other CRLP unit tests. Generally there isn't a reason for unit tests to be public, and "with sharing" doesn't necessarily specify anything here because the methods cannot be called by other classes that might use "without sharing".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep sorry, this was just a placeholder!! it'll go in correctly on tuesday.
src/classes/PSC_Opportunity_TDTM.cls
Outdated
|
||
psc.put('CurrencyIsoCode', oppCurrency); | ||
psc.put('Amount__c', psc.Amount__c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm always a bit wary when it comes to using non-namespaced field names in a string. It may work in a namespaced org, but it may fail. Given that we know the Amount__c
field exists here (and below), it might be safer to just use psc.Amount__c = psc.Amount__c;
(though we'll want to test that it still works as expected). The alternative is to call the UTIL_Namespace class to apply the namespace to the field.
src/labels/CustomLabels.labels
Outdated
@@ -4634,7 +4634,7 @@ To check your GAU Allocation settings, go to Donations | GAU Allocations.</value | |||
<language>en_US</language> | |||
<protected>false</protected> | |||
<shortDescription>pscManageSoftCreditsCantChangeCurrency</shortDescription> | |||
<value>You can't modify Partial Soft Credit currencies directly. Update the parent Opportunity's currency, and NPSP will automatically update the curency of all related Partial Soft Credit records.</value> | |||
<value>You can't modify soft credit currencies directly. Update the parent Opportunity's currency, and NPSP will automatically update the currency of all related soft credits.</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The single apostrophes should be escaped.
…removed, trigger mode fix to exclude accSC rollups
@force2b all addressed and ready for final (!) review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking absolutely fantastic. Two comments for you to review and possibly take action on, but otherwise approved!
* @author Salesforce.org | ||
* @date 2018 | ||
* @group Rollups | ||
* @group-content ../../ApexDocContent/Rollups2.htm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you update the Rollups2.htm file with the new classes?
@@ -217,6 +221,8 @@ public abstract class CRLP_Batch_Base_Skew extends CRLP_Batch_Base { | |||
parentKeyField = 'ContactId'; | |||
} else if (this.jobType == CRLP_RollupProcessingOptions.RollupType.AccountContactSoftCredit) { | |||
parentKeyField = 'Contact.AccountId'; | |||
} else if (this.jobType == CRLP_RollupProcessingOptions.RollupType.AccountSoftCredit) { | |||
parentKeyField = 'Account__c'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this will work in a namespaced context. The rest of the parentKeyField
values are standard fields. This is the only one referencing a custom field. I feel like it should have the namespace applied, though I'm always a bit unsure of when the namespace is absolutely required for these kind of references. Probably worth testing in a namespaced scratch org to be sure it's working as expected.
Critical Changes
Account Soft Credits
IMPORTANT: To get the most value out of Account Soft Credits, you'll want to enable Customizable Rollups so you can roll up the soft credit values to the Account records. At this time, you can't roll up Account soft credits with legacy NPSP rollups or User Defined Rollups.
Before you can start using Account soft credits, you need to give users access to the Account Soft Credit object and fields, and add the Account Soft Credit related list to your page layout. You can also optionally add more Account soft credit roles. For instructions, see the Account Soft Credit Setup section of Soft Credit and Matching Gift Setup.
Changes
Account Soft Credits
Account soft credits are credits for donations that Accounts don't actually make, but may have somehow influenced. They're very useful for situations where an Account, such as a Donor Advised Fund, uses another organization, such as a bank, to manage their money. When a donation comes from the Donor Advised Fund, the check is actually generated by the bank, so the bank gets the hard credit for the donation. Using Account soft credits, you can ensure that the Donor Advised Fund gets a soft credit for their donation.
For details on Account Soft Credits, see the Soft Credits Overview. For details on creating Account Soft Credits, see Create Soft Credits.
Issues Closed
New Metadata
Deleted Metadata