Created
December 28, 2022 22:04
-
-
Save forcethesales/aa0975f7fa2ac07762a834c22eb70b94 to your computer and use it in GitHub Desktop.
bulk year end tax receipt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class qGiftsLastYear implements Database.Batchable<sObject> | |
//,Database.Stateful | |
{ | |
//ideally it could be invoked by a flow but that's not being used in this version | |
@InvocableMethod(description='Year End Tax Flow' ) | |
public static void yearEndTaxMethod () { | |
database.executeBatch(new qGiftsLastYear(),10); } | |
public Database.QueryLocator start(Database.BatchableContext bc) { | |
//get "last year" | |
Integer year = Date.Today().year()-1; | |
//return contacts who gave more than one gift last year and their gifts | |
return Database.getQueryLocator([SELECT LastName, id,Gifts_Last_Year__c, (SELECT Id, CloseDate, Amount FROM Opportunities | |
WHERE CALENDAR_YEAR(CloseDate) =:year AND IsWon = True ORDER | |
BY CloseDate) FROM Contact WHERE npo02__OppAmountLastYear__c > 1 LIMIT 200000]); | |
} | |
public void execute(Database.BatchableContext bc, List<Contact> scope) { | |
//process each batch of records | |
//put the opportunities into a table | |
List<Contact> contactsForUpdate = new List<Contact>(); | |
String loopString; | |
String longestString = '<table style="width:100%; border: 1px solid black;"><tr><th style="border: 1px solid black; padding: 15px;"> Date</th> <th style="border: 1px solid black;">Amount</th></tr>'; | |
String dateFormatString = 'MMMM d, yyyy'; | |
String finalString; | |
for (Contact con : scope) { | |
for (Opportunity opp : con.opportunities) { | |
Date d = opp.CloseDate; | |
Datetime dt = Datetime.newInstance(d.year(), d.month(),d.day()); | |
String dateString = dt.format(dateFormatString); | |
String cleanAmt = String.valueOf(opp.Amount); | |
loopString = | |
'<tr> <td style="border: 1px solid black; padding: 15px;">' + dateString + | |
'</th> <td style="border: 1px solid black; padding: 15px;"> $' + cleanAmt + '</th> </tr>'; | |
longestString = longestString + loopString; | |
} | |
finalstring = longestString + '</table>'; | |
//put the table of gifts into a custom field | |
con.Gifts_Last_Year__c = String.escapeSingleQuotes(finalstring); | |
contactsForUpdate.add(con); | |
//reset the value of longestString to the start. otherwise it's going to add everyone's gifts to the list and keep growing. | |
longestString = '<table style="width:100%; border: 1px solid black;"><tr><th style="border: 1px solid black; padding: 15px;"> Date</th> <th style="border: 1px solid black;">Amount</th></tr>'; | |
system.debug('Final String' + finalstring); | |
} | |
update contactsForUpdate; | |
} | |
public void finish(Database.BatchableContext bc){} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global class giftsLastYearSchedBatch implements Schedulable { | |
global void execute(SchedulableContext sc) { | |
qGiftsLastyear q = new qgiftsLastYear(); | |
database.executebatch(q); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Code by Jessie Rymph | |
//December 21, 2022 | |
//Tests the Year End Gift Batch process using the YearEndtestDataFactory class | |
//https://wp.me/p9qPLI-1q8 | |
@isTest | |
public class giftsLastYearSchedBatchTest { | |
@isTest static void positiveTest() { | |
// Test data setup | |
// test for Gifts Last Year | |
// Create contacts with opps through test utility | |
Integer testNumC= 2; | |
Integer testNumO = 2; | |
contact[] cons = YearEndTestDataFactory.giftsLastYear(testNumC,testNumO); | |
Test.startTest(); | |
qGiftsLastYear yEGB = new qGiftsLastYear(); | |
Id batchId = Database.executeBatch(yEGB); | |
Test.stopTest(); | |
List<Contact> contacts = new List<Contact>(); | |
for(Contact person : [SELECT Id, Gifts_Last_Year__c FROM Contact]) { | |
if(person.Gifts_Last_Year__c.contains('Date')) { | |
contacts.add(person); | |
} | |
} | |
System.assertEquals(testNumC,contacts.size(),testNumC +' '); | |
} | |
@isTest static void negativeTest() { | |
// Test data setup | |
// Test that this years gifts do not go into Gifts Last Year | |
// Create contacts with opps through test utility | |
Integer testNumC=10; | |
Integer testNumO = 12; | |
contact[] cons = YearEndTestDataFactory.GiftsThisYear(testNumC,testNumO); | |
Test.startTest(); | |
qGiftsLastYear yEGB = new qGiftsLastYear(); | |
Id batchId = Database.executeBatch(yEGB); | |
Test.stopTest(); | |
List<Contact> contacts = new List<Contact>(); | |
for(Contact person : [SELECT Id, Gifts_Last_Year__c FROM Contact]) { | |
IF(person.Gifts_Last_Year__c != null) { | |
contacts.add(person); | |
} | |
} | |
System.assertEquals(0,contacts.size(),'Expected none, got' + contacts.size()); | |
} | |
@isTest static void schedTest() { | |
// This test runs a scheduled job at midnight Sept. 3rd. 2022 | |
String CRON_EXP = '0 0 0 3 9 ? 2027'; | |
// Schedule the test job | |
String jobId = System.schedule('giftsLastYearSchedBatchTest', CRON_EXP, new giftsLastYearSchedBatch()); | |
// Get the information from the CronTrigger API object | |
CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId]; | |
// Verify the expressions are the same System.assertEquals(CRON_EXP, ct.CronExpression); | |
// Verify the job has not run | |
System.assertEquals(0, ct.TimesTriggered); | |
// Verify the next time the job will run | |
System.assertEquals('2027-09-03 00:00:00', String.valueOf(ct.NextFireTime)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Code by Jessie Rymph | |
//December 30, 2021 | |
//https://wp.me/p9qPLI-1q8 | |
@isTest | |
public class yearEndtestDataFactory { | |
public static Id devRecordTypeId = Schema.SObjectType.Opportunity.getRecordTypeInfosByName().get('Donation').getRecordTypeId(); | |
//gifts last year | |
public static List<Contact> giftsThisYear(Integer numCts, Integer numOppsPerCt){ | |
List<Contact> cons = new List<Contact>(); | |
for(Integer i=0;i<numCts;i++) { | |
Contact a = new Contact(LastName='Test'+i,Email='basket@gmail.com',npo02__OppsClosedThisYear__c =3); | |
Cons.add(a); | |
} | |
insert Cons; | |
system.debug('insert' + cons); | |
List<Opportunity> opps = new List<Opportunity>(); | |
for (Integer j=0;j<numCts;j++) { | |
Contact connie = Cons[j]; | |
//get today's date | |
Date myDate = system.today(); | |
//get the year from the date | |
Integer thisYear = myDate.year(); | |
//set a date variable for January 1 of this year. This will be the first gift date. | |
Date janDate = Date.newInstance(thisyear, 1, 1); | |
// For each contact just inserted, add opportunities | |
for (Integer k=0;k<numOppsPerCt;k++) { | |
opps.add(new Opportunity(Name=connie.Name + ' Opportunity ' + k, | |
recordTypeid=devRecordTypeId, | |
AccountId=connie.AccountId, | |
StageName='Closed Won', | |
CloseDate=janDate.addmonths(k), | |
Amount=k+990, | |
npsp__Primary_Contact__c=connie.Id)); | |
} | |
} | |
// Insert all opportunities for all accounts. | |
insert opps; | |
system.debug('all Test Opps created'); | |
return cons; | |
} | |
public static List<Contact> sendGiftReceiptCheckthisYear(Integer numCts, Integer numOppsPerCt){ | |
List<Contact> cons = new List<Contact>(); | |
for(Integer i=0;i<numCts;i++) { | |
Contact a = new Contact(LastName='Test'+i,Email='basket@gmail.com',End_of_Year_Gift_Receipt__c=True); | |
Cons.add(a); | |
} | |
insert Cons; | |
system.debug('insert' + cons); | |
List<Opportunity> opps = new List<Opportunity>(); | |
for (Integer j=0;j<numCts;j++) { | |
Contact connie = Cons[j]; | |
//get today's date | |
Date myDate = system.today(); | |
//get the year from the date | |
Integer thisYear = myDate.year(); | |
//set a date variable for January 1 of this year. This will be the first gift date. | |
Date janDate = Date.newInstance(thisyear, 1, 1); | |
// For each contact just inserted, add opportunities | |
for (Integer k=0;k<numOppsPerCt;k++) { | |
opps.add(new Opportunity(Name=connie.Name + ' Opportunity ' + k, | |
recordTypeid=devRecordTypeId, | |
AccountId=connie.AccountId, | |
StageName='Closed Won', | |
CloseDate=janDate.addyears(k), | |
Amount=k+990, | |
npsp__Primary_Contact__c=connie.Id)); | |
} | |
} | |
// Insert all opportunities for all accounts. | |
insert opps; | |
system.debug('all Test Opps created'); | |
return cons; | |
} | |
//gifts two years ago | |
public static List<Contact> gifts2YearsAgo(Integer numCts, Integer numOppsPerCt){ | |
//create Test Data | |
Campaign camp = new Campaign (Name = 'Annual Fund'); | |
insert camp; | |
List<Contact> cons = new List<Contact>(); | |
for(Integer i=0;i<numCts;i++) { | |
Contact a = new Contact(LastName='Test'+i,Email='basket@gmail.com',npo02__OppAmountLastYear__c=40, npo02__OppAmountThisYear__c=60); | |
Cons.add(a); | |
} | |
insert Cons; | |
system.debug('insert' + cons); | |
List<Opportunity> opps = new List<Opportunity>(); | |
for (Integer j=0;j<numCts;j++) { | |
Contact connie = Cons[j]; | |
//get the year of last year. start by getting today's date. | |
Date myDate = system.today(); | |
//get the year from the date | |
Integer thisYear = myDate.year(); | |
//subtract one to make it last year | |
Integer twoYears = thisYear - 2; | |
//set a date variable for January 1 of last year. This will be the first gift date. | |
Date janDate = Date.newInstance(twoYears, 1, 1); | |
// For each contact just inserted, add opportunities | |
for (Integer k=0;k<numOppsPerCt;k++) { | |
opps.add(new Opportunity(Name=connie.Name + ' Opportunity ' + k, | |
recordTypeid= devRecordTypeId, | |
AccountId=connie.AccountId, | |
StageName='Closed Won', | |
CampaignId = camp.Id, | |
//for each opp created use the JanDate variable, one month later | |
CloseDate=janDate.addmonths(k), | |
Amount=k+990, | |
npsp__Primary_Contact__c=connie.Id)); | |
} | |
} | |
// Insert all opportunities for all accounts. | |
insert opps; | |
system.debug('all Test Opps created'); | |
return cons; | |
} | |
public static List<Contact> giftsLastYear(Integer numCts, Integer numOppsPerCt){ | |
//create Test Data | |
Campaign camp = new Campaign (Name = 'Annual Fund'); | |
insert camp; | |
List<Contact> cons = new List<Contact>(); | |
for(Integer i=0;i<numCts;i++) { | |
Contact a = new Contact(LastName='Test'+i,Email='basket@gmail.com',npo02__OppAmountLastYear__c=40, npo02__OppAmountThisYear__c=60); | |
Cons.add(a); | |
} | |
insert Cons; | |
system.debug('insert' + cons); | |
List<Opportunity> opps = new List<Opportunity>(); | |
for (Integer j=0;j<numCts;j++) { | |
Contact connie = Cons[j]; | |
//get the year of last year. start by getting today's date. | |
Date myDate = system.today(); | |
//get the year from the date | |
Integer thisYear = myDate.year(); | |
//subtract one to make it last year | |
Integer twoYears = thisYear - 1; | |
//set a date variable for January 1 of last year. This will be the first gift date. | |
Date janDate = Date.newInstance(twoYears, 1, 1); | |
// For each contact just inserted, add opportunities | |
for (Integer k=0;k<numOppsPerCt;k++) { | |
opps.add(new Opportunity(Name=connie.Name + ' Opportunity ' + k, | |
recordTypeid= devRecordTypeId, | |
AccountId=connie.AccountId, | |
StageName='Closed Won', | |
CampaignId = camp.Id, | |
//for each opp created use the JanDate variable, one month later | |
CloseDate=janDate.addmonths(k), | |
Amount=k+990, | |
npsp__Primary_Contact__c=connie.Id)); | |
} | |
} | |
// Insert all opportunities for all accounts. | |
insert opps; | |
system.debug('all Test Opps created'); | |
return cons; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Learn about this code here on the appExchange.
This gist is designed to work with millions of records but we're still getting an apex cpu timeout error.