- Apex 36.7%
- JavaScript 33.6%
- HTML 26.9%
- CSS 2.8%
| .husky | ||
| .vscode | ||
| config | ||
| force-app/main/default | ||
| .forceignore | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| eslint.config.js | ||
| jest.config.js | ||
| LICENSE | ||
| package-donation-entry.xml | ||
| package.json | ||
| README.md | ||
| sfdx-project.json | ||
Donation Entry - Salesforce Lightning Web Component
A Salesforce Lightning Web Component application for quick donation entry, built for The Henzi Foundation (henzi.org) to streamline their donation processing workflow in Salesforce with the Nonprofit Success Pack (NPSP).
About The Henzi Foundation
The Henzi Foundation is a 501(c)(3) nonprofit organization dedicated to providing financial assistance to families who have experienced the unexpected loss of a child. The foundation's primary initiative, The Frankie Fund, helps alleviate the financial burden of funeral expenses for grieving families in the Greater Cincinnati area.
This application was created specifically for The Henzi Foundation's Salesforce instance to support their treasurer, Rachel Henzi, in efficiently managing donation entries.
Learn more about The Henzi Foundation at henzi.org.
Overview
This Lightning Web Component provides a streamlined interface for entering multiple donations quickly. It integrates with Salesforce's Nonprofit Success Pack (NPSP) to create Opportunity records (donations) linked to Contacts and Campaigns.
Features
- Quick Contact Search: Search and select existing contacts or create new ones inline
- Campaign Association: Link donations to fundraising campaigns
- Batch Entry: Enter multiple donations in a single session
- Funding Source Tracking: Track funding sources via picklist values
- Date Handling: Flexible date input with automatic formatting
- Real-time Validation: Immediate feedback on required fields and data format
- Auto-save: Each donation row can be saved individually
- Navigation: Direct links to view created Opportunity records
Components
Lightning Web Component
donationEntry- Main component for donation entry interface
Apex Classes
DonationEntryController- Backend controller handling business logicDonationEntryControllerTest- Test class with comprehensive coverage
Installation
-
Deploy the metadata to your Salesforce org:
sfdx force:source:deploy -p force-app -
Assign the Lightning Web Component to an App Page or create a custom tab using the
Quick_Donation_Entrytab.
Usage
- Navigate to the Quick Donation Entry tab or add the component to an App Page
- Enter contact information (search for existing or create new)
- Enter donation amount
- Select funding source (optional)
- Select campaign (optional)
- Enter close date (MM/DD/YY format)
- Click Save or press Enter to save the donation
- The component automatically adds a new row for the next donation
Requirements
- Salesforce org with API version 65.0 or higher
- Nonprofit Success Pack (NPSP) installed and configured
- Appropriate permissions for:
- Creating/updating Contacts
- Creating Opportunities
- Accessing Campaigns
Dependencies
Required NPSP Custom Fields
This application requires the following NPSP (Nonprofit Success Pack) custom fields:
npsp__Primary_Contact__c(on Opportunity) - REQUIRED- This field is critical for NPSP to properly associate donations with contacts
- The application automatically sets this field when creating opportunities
- If this field doesn't exist, donations will still be created but may not properly link to contacts in NPSP
Required Custom Fields
Funding_Source__c(on Opportunity) - OPTIONAL but recommended- Custom picklist field for tracking donation funding sources
- If this field doesn't exist, the Funding Source column will be non-functional but the application will continue to work
- The application gracefully handles missing fields and will log debug messages if the field is not found
Optional Configuration
- "Donation" Record Type (on Opportunity) - OPTIONAL
- If a record type with DeveloperName = "Donation" exists, opportunities will be assigned this record type
- If it doesn't exist, opportunities will use the org's default record type
- The application will function normally without this record type
NPSP Functionality Dependencies
The application relies on NPSP's built-in functionality:
- Household Account Management: When creating new contacts, NPSP automatically creates or assigns household accounts (via
npe01__SYSTEM_AccountType__c = 'Household') - Primary Contact Linking: NPSP triggers handle the relationship between Opportunities and Contacts via the
npsp__Primary_Contact__cfield - Account Hierarchy: The application sets
AccountIdon opportunities to link to NPSP household accounts
Standard Salesforce Objects
- Contact - Standard object, no custom fields required
- Account - Standard object (NPSP manages household accounts)
- Opportunity - Standard object with custom fields listed above
- Campaign - Standard object, no custom fields required
Field Setup Instructions
If deploying to a new org, ensure:
- NPSP is installed - This provides the
npsp__Primary_Contact__cfield automatically - Create
Funding_Source__cfield (optional):- Object: Opportunity
- Type: Picklist
- Add your organization's funding source values
- Create "Donation" Record Type (optional):
- Object: Opportunity
- Developer Name:
Donation - Label: Donation
How to Adapt This to Your Organization
This component is designed for nonprofit donation entry, but can be easily adapted for enterprise sales teams, field service, or other opportunity entry scenarios. Here's how to customize it for your use case:
Common Use Cases
Enterprise Sales Teams
Scenario: Sales reps need to quickly enter opportunities after client meetings or field visits.
Key Adaptations:
- Swap Contact lookup for Account lookup (B2B sales)
- Change "Donation" terminology to "Opportunity" or "Deal"
- Add Lead Source field for tracking
- Add Probability or Forecast Category fields
- Consider adding Product/Line Items support
- Update opportunity naming convention (e.g., "{Account Name} - {Product} - {Date}")
Field Service / Service Organizations
Scenario: Service teams entering opportunities after site visits.
Key Adaptations:
- Keep Contact lookup (B2C) or switch to Account (B2B)
- Add Service Type or Work Order reference
- Add Location/Address fields
- Consider Mobile optimization (already responsive, but may need touch improvements)
- Add Photo/Attachment capability for field documentation
Nonprofit Variations
Scenario: Different nonprofit use cases beyond donations.
Key Adaptations:
- Change terminology (Grants, Sponsorships, etc.)
- Adjust required fields based on your process
- Add custom fields specific to your organization type
Step-by-Step Customization Guide
1. Change from Contact to Account Lookup (Enterprise B2B)
Apex Controller Changes (DonationEntryController.cls):
// Replace searchContacts method with:
@AuraEnabled(cacheable=true)
public static List<Account> searchAccounts(String searchTerm) {
if (String.isBlank(searchTerm) || searchTerm.length() < 2) {
return new List<Account>();
}
String searchPattern = '%' + String.escapeSingleQuotes(searchTerm) + '%';
return [
SELECT Id, Name, BillingCity, BillingState, Phone, Website
FROM Account
WHERE Name LIKE :searchPattern
OR Website LIKE :searchPattern
ORDER BY Name
LIMIT 50
];
}
// Update createOpportunities method:
// Change contactId references to accountId
// Remove npsp__Primary_Contact__c field setting
// Set AccountId directly: opp.AccountId = accountId;
LWC JavaScript Changes (donationEntry.js):
- Replace
searchContactsimport withsearchAccounts - Update
DEFAULT_ROWto useaccountIdandaccountNameinstead ofcontactIdandcontactName - Update all references throughout the component
- Remove inline contact creation (or adapt for account creation if needed)
LWC HTML Changes (donationEntry.html):
- Update column header from "Contact" to "Account"
- Update all
contactNamereferences toaccountName - Update search placeholder text
- Remove or adapt inline contact creation form
Test Class Updates (DonationEntryControllerTest.cls):
- Replace contact setup with account setup
- Update all test methods to use accounts
- Remove NPSP-specific test data (household accounts)
2. Customize Branding and Terminology
Component Title (donationEntry.html):
<!-- Change line 2: -->
<lightning-card title="Quick Opportunity Entry" icon-name="standard:opportunity">
Field Labels (donationEntry.html):
- Update column headers in the table
<th>elements - Change "Donation" references to your terminology
- Update placeholder text in input fields
Opportunity Naming (DonationEntryController.cls):
// Update generateOpportunityName method:
private static String generateOpportunityName(String accountName, Date closeDate) {
String dateStr = formatDate(closeDate);
return accountName + ' - Deal - ' + dateStr; // Customize as needed
}
CSS Styling (donationEntry.css):
- Update
.donation-entry-cardclass name if desired - Customize colors, fonts, spacing to match your org's branding
- Add your organization's logo if needed
3. Implement as Utility Bar Item
Benefits: Always accessible, doesn't take up full page space, works across all records.
Implementation Steps:
-
Create Utility Bar Item:
- Setup → App Manager → Edit your app
- Utility Items → Add Utility Item
- Select
donationEntrycomponent - Configure size (recommended: 400px width, 600px height)
-
Update Component Metadata (
donationEntry.js-meta.xml):
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__UtilityBar</target>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__UtilityBar">
<property name="height" type="Integer" default="600" />
<property name="width" type="Integer" default="400" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
- Adjust CSS for Utility Bar:
/* Add to donationEntry.css */
.donation-entry-card {
height: 100%;
overflow-y: auto;
}
.donation-table-container {
max-height: 500px; /* Adjust for utility bar */
overflow-y: auto;
}
4. Add Additional Fields
Common Additions:
-
Lead Source (Picklist):
// In DonationEntryController.cls, add to OpportunityInput: @AuraEnabled public String leadSource; // In createOpportunities method: if (String.isNotBlank(oppInput.leadSource)) { opp.LeadSource = oppInput.leadSource; } -
Probability (Number):
@AuraEnabled public Decimal probability; // Set: opp.Probability = oppInput.probability; -
Type (Picklist):
@AuraEnabled public String type; // Set: opp.Type = oppInput.type; -
Custom Fields: Follow the same pattern as
Funding_Source__c
LWC Updates:
- Add fields to
DEFAULT_ROWobject - Add table columns in HTML
- Add input handlers in JavaScript
- Update the opportunity creation logic
5. Remove NPSP Dependencies (For Non-Nonprofit Orgs)
If you're not using NPSP:
-
Remove NPSP Field References:
// In DonationEntryController.cls, remove or comment out: // opp.put('npsp__Primary_Contact__c', contact.Id); -
Update Account Handling:
- For B2B: Set
opp.AccountIddirectly - For B2C: Use standard Contact-to-Opportunity relationship or custom lookup
- For B2B: Set
-
Update Test Class:
- Remove
npe01__SYSTEM_AccountType__creferences - Use standard Account records
- Remove
6. Mobile Optimization Enhancements
For field users on mobile devices:
-
Touch-Friendly Targets:
/* Increase tap targets */ .donation-table td { min-height: 44px; /* iOS recommended minimum */ } -
Responsive Layout:
@media (max-width: 768px) { .donation-table { font-size: 14px; } .col-contact, .col-campaign { min-width: 150px; /* Reduce for mobile */ } } -
Consider Mobile App:
- Package as Salesforce Mobile App component
- Test on actual devices
- Consider offline capability if needed
Quick Reference: Key Files to Modify
| Change | Files to Edit |
|---|---|
| Contact → Account | DonationEntryController.cls, donationEntry.js, donationEntry.html, DonationEntryControllerTest.cls |
| Terminology/Branding | donationEntry.html, DonationEntryController.cls (naming methods), donationEntry.css |
| Add Fields | DonationEntryController.cls (OpportunityInput class + logic), donationEntry.js (DEFAULT_ROW + handlers), donationEntry.html (table columns) |
| Utility Bar | donationEntry.js-meta.xml, donationEntry.css (height constraints) |
| Remove NPSP | DonationEntryController.cls, DonationEntryControllerTest.cls |
Testing Your Customizations
After making changes:
- Update Test Class: Modify
DonationEntryControllerTest.clsto match your changes - Run Tests:
npm run testorsfdx force:apex:test:run - Manual Testing: Test all user flows in a sandbox
- User Acceptance: Get feedback from actual users
Need Help?
- Review the code comments - they explain the NPSP integration points
- Check Salesforce Lightning Web Component documentation
- Test changes in a sandbox before production deployment
Development
Prerequisites
- Salesforce CLI
- Node.js and npm
- VS Code with Salesforce Extensions
Setup
npm install
Testing
npm run test
Linting
npm run lint
Formatting
npm run prettier
Project Structure
force-app/
main/
default/
classes/ # Apex classes
lwc/ # Lightning Web Components
tabs/ # Custom tabs
Code Audit & Quality
Security
- ✅ SOQL Injection Protection: All user inputs are properly escaped using
String.escapeSingleQuotes()before being used in SOQL queries - ✅ Sharing Model: Controller uses
with sharingto enforce org-level sharing rules - ✅ Input Validation: All required fields are validated before database operations
- ✅ Error Handling: Comprehensive try-catch blocks with user-friendly error messages
Code Quality
- ✅ Test Coverage: Comprehensive test class (
DonationEntryControllerTest) covering:- Contact search and creation
- Campaign search
- Opportunity creation (single and multiple)
- Validation error handling
- Edge cases (empty lists, null values, invalid data)
- ✅ Error Messages: Clear, actionable error messages for users
- ✅ Debug Logging: Appropriate debug statements for troubleshooting (can be removed in production if desired)
- ✅ Code Comments: Well-documented code with clear explanations of NPSP integration points
Best Practices
- ✅ NPSP Integration: Properly uses NPSP fields and relies on NPSP triggers for household account management
- ✅ Graceful Degradation: Handles missing custom fields gracefully (Funding_Source__c, Record Types)
- ✅ User Experience: Inline contact creation, keyboard navigation, real-time validation
- ✅ Performance: Efficient SOQL queries with appropriate limits and selective field queries
Known Considerations
- Debug Statements: The code contains
System.debug()statements for troubleshooting. These can be removed or controlled via debug logs in production. - Field Dependencies: The application will function without
Funding_Source__cfield, but that feature will be disabled. - Record Type: The "Donation" record type is optional - opportunities will use the default record type if it doesn't exist.
Attribution
Created for: The Henzi Foundation (henzi.org)
Primary Contact: Rachel Henzi, Treasurer
Purpose: Streamline donation entry workflow in Salesforce
Developer: Joe Henzi - Salesforce professional with 10+ years of experience
Supporting The Henzi Foundation
If you found this project useful and would like to support The Henzi Foundation's mission of helping families who have experienced the unexpected loss of a child, please consider making a donation at henzi.org/donate. The foundation's Frankie Fund provides financial assistance for funeral expenses, allowing grieving families to focus on healing without financial stress.
License
This project is proprietary software created for The Henzi Foundation. Feel free to use and adapt this code for your own nonprofit organization's Salesforce instance.
Support
For questions or issues related to this application, please contact The Henzi Foundation or open an issue in this repository.