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

Account Soft Credits: Object and Rollups integration #3220

Merged
merged 134 commits into from Aug 14, 2018

Conversation

bethbrains
Copy link
Contributor

@bethbrains bethbrains commented May 29, 2018

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

  • Account_Soft_Credit__c object
  • CRLP_AccountSkew_AccSoftCredit_BATCH
  • CRLP_Account_AccSoftCredit_BATCH
  • CRLP_RollupAccSoftCredit_SVC
  • TDTM_AccountSoftCredit
  • CRLP_RollupAccSoftCredit_TEST

Deleted Metadata

bethbrains and others added 28 commits May 18, 2018 12:40
@@ -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];
Copy link
Contributor

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);
Copy link
Contributor

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.

@@ -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();
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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;
Copy link
Contributor

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>();
Copy link
Contributor

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) {
Copy link
Contributor

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

Copy link
Contributor Author

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.

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);
Copy link
Contributor

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.


psc.put('CurrencyIsoCode', oppCurrency);
results.add(psc);
accountSC.put('CurrencyIsoCode', oppCurrency);
Copy link
Contributor

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.

image

* @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();
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -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>
Copy link
Contributor Author

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?

Copy link
Contributor

@force2b force2b left a 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 {
Copy link
Contributor

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".

Copy link
Contributor Author

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.


psc.put('CurrencyIsoCode', oppCurrency);
psc.put('Amount__c', psc.Amount__c);
Copy link
Contributor

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.

@@ -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>
Copy link
Contributor

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.

@bethbrains
Copy link
Contributor Author

@force2b all addressed and ready for final (!) review.

@force2b force2b changed the base branch from feature/rollups to master August 8, 2018 22:18
Copy link
Contributor

@force2b force2b left a 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
Copy link
Contributor

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';
Copy link
Contributor

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.

@dgamboni dgamboni merged commit 2dafd17 into master Aug 14, 2018
@dgamboni dgamboni deleted the feature/rollups__acct-soft-credits branch August 14, 2018 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants