-
ChatterFeed
-
0Best Answers
-
0Likes Received
-
0Likes Given
-
2Questions
-
2Replies
Extracting Information From Nested SOQL Statements in Batch
I am trying to create a batchable program that acts like a roll up helper every night on the account object. In this particular example I am trying to count the number of related activities attached to an account or account child object. I am able to pull my information in a query but when I try to then extract that informaiton I keep getting errors saying the variables I am pulling dont exist. Can someone take a look and see if I have just made a clerical error in my dot notation or someting like that? I am sure the values are returned because ive tested everything in the Query Editor before transitioning it to my code. Here is the program, query and current errors:
APEX CODE:
Current Errors:
APEX CODE:
global class NightlyAccountFieldUpdater implements Database.Batchable<SObject>{ global Database.QueryLocator start(Database.BatchableContext BC){ String query = '[SELECT id, Last_Sales_Contact_Date__c,Next_Sales_Activity_Date__c, OwnerId,'; query += ' (SELECT OwnerId, ActivityDate, ActivitySubType, EndDateTime, IsClosed, IsDeleted, PrimaryWhoId FROM ActivityHistories), '; query+= ' (SELECT OwnerId, ActivityDate, ActivitySubType, WhoId, WhatId FROM OpenActivities) FROM ACCOUNT]'; return Database.getQueryLocator(query); } global static void execute(Database.BatchableContext BC, List<Account> scope){ List<Lead> LeadActivityList = new List<Lead>([SELECT id, Account__c, (SELECT OwnerId, ActivityDate, ActivitySubType, EndDateTime, IsClosed, IsDeleted, PrimaryWhoId FROM ActivityHistories), (SELECT OwnerId, ActivityDate, ActivitySubType, WhoId, WhatId FROM OpenActivities) FROM LEAD WHERE lead.Account__C != NULL]); List<Account> masterAccountList = new List<Account>(); Map<Account, List<Activity>> accountActivityMap = new Map<Account, List<Activity>>(); for(SObject tempobj: scope){ Account tempact = new Account(Id = tempobj.Id, OwnerId = tempobj.OwnerId, Last_Sales_Contact_Date__c = tempobj.Last_Sales_Contact_Date__c, Next_Sales_Activity_Date__c = tempobj.Next_Sales_Activity_Date__c); } } global void finish(Database.BatchableContext BC){ } }
Current Errors:
- William Roach 9
- May 15, 2019
- Like
- 0
Cannot get Code Coverage on afterDelete trigger
Hello forum, I am having trouble atchieving 75% code coverage on a trigger im writting and wondered if someone here knows what I am doing incorrectly. I am deleting code and asserting after the fact. Below you can find my trigger as well as the test class and main class. I use a custom testDataFactory to produce my data.
TRIGGER:
MAIN CLASS:
TEST CLASS:
I currently have 56% code coverage on my trigger and 100% coverage on my main class.
TRIGGER:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Trigger Class * * This class is designed to trigger RateReviewAttachmentCounter when the attachment in question is * related to a Rate_Review__c object * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <REDACTED> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ trigger RateReviewAttachmentTrigger on Attachment (after insert, after update, after delete) { if(Trigger.isInsert || Trigger.isUpdate){ List<Attachment> approved = new List<Attachment>(); for(Attachment aiq: Trigger.new){ Id parentId = aiq.ParentId; if(parentId.getSObjectType().getDescribe().getName() == 'Rate_Review__c'){ approved.add(aiq); } } RateReviewAttachmentCounter instance = new RateReviewAttachmentCounter(); instance.attachmentCounter(approved); } //when handling a delete you want to pull data from trigger.old and not trigger.new if(Trigger.isAfter && Trigger.isdelete){ List<Attachment> oldboys = new List<Attachment>(); for(Attachment aiq: Trigger.old){ Id parentId = aiq.ParentId; if(parentId.getSObjectType().getDescribe().getName() == 'Rate_Review__c'){ oldboys.add(aiq); } } RateReviewAttachmentCounter oldinstance = new RateReviewAttachmentCounter(); oldinstance.attachmentCounter(oldboys); } }
MAIN CLASS:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Main Class * * This class is designed to monitor the number of attachments produced and attached to the RateReview * object. This is to be used so that a salesperson cant create a new ratereview record without asscoiating * at least one attached review with it. * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <REDACTED> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ public class RateReviewAttachmentCounter{ public void attachmentCounter(List<Attachment> attachList){ List<Rate_Review__c> rrList = new List<Rate_Review__c>(); List<Id> rrIdList = new List<Id>(); List<Attachment> relatedAttachment = new List<Attachment>(); for(Attachment attachy: attachList){ rrIdList.add(attachy.ParentId); } rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; relatedAttachment = [SELECT id, parentId FROM Attachment WHERE parentId IN: rrIdList]; for(Rate_Review__c rr: rrList){ Integer attachmentCounter = 0; id RateReviewId = rr.id; for(Attachment atch: relatedAttachment){ if(atch.parentId == RateReviewId){ attachmentCounter++; } } rr.Number_of_Attachments__c = attachmentCounter; } update rrList; } }
TEST CLASS:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Test Class * * This class is designed to test RateReviewAttachmentCounter when the attachment in question is * related to a Rate_Review__c object * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <william.roach@pushpay.com> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ @isTest public class RateReviewAttachmentCounterTest { //The test setup was omitted from this class because governing limits are not a concern when testing and its easier to get direct access to //produced data then it is to produce the data and querry for it in later tests. /*@TestSetup public static void setup(){ TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords = 1; List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords)); System.assert(rrList.size() == numRecords, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords + ' ACTUAL: ' + rrList.size()); } */ static testmethod void testAttachmentCounter(){ TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords = 5;//NumRecords dictates the total number of records produced for testing purposes. Increment for bulk testing and decrement for easy to read logs List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords)); System.assert(rrList.size() == numRecords, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords + ' ACTUAL: ' + rrList.size()); System.debug('RATE REVIEW OBJECTS: ' + rrList); List<Attachment> attachmentList = new List<Attachment>(dataGenerator.generateAttachments(rrList, numRecords)); System.debug('ATTACHMENT LIST: ' + attachmentList); List<Id> rrIdList = new List<Id>(); for(Rate_Review__c rateReview: rrList){ rrIdList.add(rateReview.id); } Test.startTest(); RateReviewAttachmentCounter methodtest = new RateReviewAttachmentCounter(); methodtest.attachmentCounter(attachmentList); Test.stopTest(); rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; System.assert(rrList.size() == numRecords, 'NOT ENOUGH RATE REVIEWS. EXPECTED: ' + numRecords + ' ACTUAL: ' + rrList.size() ); for(Rate_Review__c rrfinal: rrList){ System.assert(rrfinal.Number_of_Attachments__c == numRecords, 'NUM OF ATTACHMENTS NOT SET'); System.debug('NUMBER OF ATTACHMENTS FIELD: ' + rrfinal.Number_of_Attachments__c); } } static testmethod void testAttachmentCounterDelete(){ Test.startTest(); TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords1 = 5;//NumRecords dictates the total number of records produced for testing purposes. Increment for bulk testing and decrement for easy to read logs List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords1)); System.assert(rrList.size() == numRecords1, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords1 + ' ACTUAL: ' + rrList.size()); System.debug('RATE REVIEW OBJECTS: ' + rrList); List<Attachment> attachmentList = new List<Attachment>(dataGenerator.generateAttachments(rrList, numRecords1)); System.debug('ATTACHMENT LIST: ' + attachmentList); List<Id> rrIdList = new List<Id>(); for(Rate_Review__c rateReview: rrList){ rrIdList.add(rateReview.id); } RateReviewAttachmentCounter methodtest = new RateReviewAttachmentCounter(); methodtest.attachmentCounter(attachmentList); delete attachmentList; Test.stopTest(); rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; System.assert(rrList.size() == numRecords1, 'NOT ENOUGH RATE REVIEWS. EXPECTED: ' + 0 + ' ACTUAL: ' + rrList.size() ); for(Rate_Review__c rrfinal: rrList){ System.assert(rrfinal.Number_of_Attachments__c == 0 , 'NUM OF ATTACHMENTS NOT SET EXPECTED: ' + rrfinal.Number_of_Attachments__c + ' ACTUAL: ' + numRecords1); System.debug('NUMBER OF ATTACHMENTS FIELD: ' + rrfinal.Number_of_Attachments__c); } } }
I currently have 56% code coverage on my trigger and 100% coverage on my main class.
- William Roach 9
- April 29, 2019
- Like
- 0
Cannot get Code Coverage on afterDelete trigger
Hello forum, I am having trouble atchieving 75% code coverage on a trigger im writting and wondered if someone here knows what I am doing incorrectly. I am deleting code and asserting after the fact. Below you can find my trigger as well as the test class and main class. I use a custom testDataFactory to produce my data.
TRIGGER:
MAIN CLASS:
TEST CLASS:
I currently have 56% code coverage on my trigger and 100% coverage on my main class.
TRIGGER:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Trigger Class * * This class is designed to trigger RateReviewAttachmentCounter when the attachment in question is * related to a Rate_Review__c object * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <REDACTED> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ trigger RateReviewAttachmentTrigger on Attachment (after insert, after update, after delete) { if(Trigger.isInsert || Trigger.isUpdate){ List<Attachment> approved = new List<Attachment>(); for(Attachment aiq: Trigger.new){ Id parentId = aiq.ParentId; if(parentId.getSObjectType().getDescribe().getName() == 'Rate_Review__c'){ approved.add(aiq); } } RateReviewAttachmentCounter instance = new RateReviewAttachmentCounter(); instance.attachmentCounter(approved); } //when handling a delete you want to pull data from trigger.old and not trigger.new if(Trigger.isAfter && Trigger.isdelete){ List<Attachment> oldboys = new List<Attachment>(); for(Attachment aiq: Trigger.old){ Id parentId = aiq.ParentId; if(parentId.getSObjectType().getDescribe().getName() == 'Rate_Review__c'){ oldboys.add(aiq); } } RateReviewAttachmentCounter oldinstance = new RateReviewAttachmentCounter(); oldinstance.attachmentCounter(oldboys); } }
MAIN CLASS:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Main Class * * This class is designed to monitor the number of attachments produced and attached to the RateReview * object. This is to be used so that a salesperson cant create a new ratereview record without asscoiating * at least one attached review with it. * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <REDACTED> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ public class RateReviewAttachmentCounter{ public void attachmentCounter(List<Attachment> attachList){ List<Rate_Review__c> rrList = new List<Rate_Review__c>(); List<Id> rrIdList = new List<Id>(); List<Attachment> relatedAttachment = new List<Attachment>(); for(Attachment attachy: attachList){ rrIdList.add(attachy.ParentId); } rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; relatedAttachment = [SELECT id, parentId FROM Attachment WHERE parentId IN: rrIdList]; for(Rate_Review__c rr: rrList){ Integer attachmentCounter = 0; id RateReviewId = rr.id; for(Attachment atch: relatedAttachment){ if(atch.parentId == RateReviewId){ attachmentCounter++; } } rr.Number_of_Attachments__c = attachmentCounter; } update rrList; } }
TEST CLASS:
/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Rate Review Attachment Counter Test Class * * This class is designed to test RateReviewAttachmentCounter when the attachment in question is * related to a Rate_Review__c object * ────────────────────────────────────────────────────────────────────────────────────────────────── * @author William L. Roach-Barrette <william.roach@pushpay.com> * @modifiedBy * @maintainedBy * @version 1.0 * @created 2019-04-16 * @modified YYYY-MM-DD * ────────────────────────────────────────────────────────────────────────────────────────────────── * @changes * vX.X EMAIL * YYYY-MM-DD Explanation of the change. Multiple lines can be used to explain the change, but * each line should be indented till left aligned with the previous description text. * * vX.X EMAIL * YYYY-MM-DD Each change to this file should be documented by incrementing the version number, * and adding a new entry to this @changes list. Note that there is a single blank * line between each @changes entry. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ @isTest public class RateReviewAttachmentCounterTest { //The test setup was omitted from this class because governing limits are not a concern when testing and its easier to get direct access to //produced data then it is to produce the data and querry for it in later tests. /*@TestSetup public static void setup(){ TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords = 1; List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords)); System.assert(rrList.size() == numRecords, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords + ' ACTUAL: ' + rrList.size()); } */ static testmethod void testAttachmentCounter(){ TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords = 5;//NumRecords dictates the total number of records produced for testing purposes. Increment for bulk testing and decrement for easy to read logs List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords)); System.assert(rrList.size() == numRecords, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords + ' ACTUAL: ' + rrList.size()); System.debug('RATE REVIEW OBJECTS: ' + rrList); List<Attachment> attachmentList = new List<Attachment>(dataGenerator.generateAttachments(rrList, numRecords)); System.debug('ATTACHMENT LIST: ' + attachmentList); List<Id> rrIdList = new List<Id>(); for(Rate_Review__c rateReview: rrList){ rrIdList.add(rateReview.id); } Test.startTest(); RateReviewAttachmentCounter methodtest = new RateReviewAttachmentCounter(); methodtest.attachmentCounter(attachmentList); Test.stopTest(); rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; System.assert(rrList.size() == numRecords, 'NOT ENOUGH RATE REVIEWS. EXPECTED: ' + numRecords + ' ACTUAL: ' + rrList.size() ); for(Rate_Review__c rrfinal: rrList){ System.assert(rrfinal.Number_of_Attachments__c == numRecords, 'NUM OF ATTACHMENTS NOT SET'); System.debug('NUMBER OF ATTACHMENTS FIELD: ' + rrfinal.Number_of_Attachments__c); } } static testmethod void testAttachmentCounterDelete(){ Test.startTest(); TestDataFactory dataGenerator = new TestDataFactory(); Integer numRecords1 = 5;//NumRecords dictates the total number of records produced for testing purposes. Increment for bulk testing and decrement for easy to read logs List<Rate_Review__c> rrList = new List<Rate_Review__c>(dataGenerator.generateRateReview(numRecords1)); System.assert(rrList.size() == numRecords1, 'INCORRECT NUMBER OF RECORDS PRODUCED. REQUIRED: ' + numRecords1 + ' ACTUAL: ' + rrList.size()); System.debug('RATE REVIEW OBJECTS: ' + rrList); List<Attachment> attachmentList = new List<Attachment>(dataGenerator.generateAttachments(rrList, numRecords1)); System.debug('ATTACHMENT LIST: ' + attachmentList); List<Id> rrIdList = new List<Id>(); for(Rate_Review__c rateReview: rrList){ rrIdList.add(rateReview.id); } RateReviewAttachmentCounter methodtest = new RateReviewAttachmentCounter(); methodtest.attachmentCounter(attachmentList); delete attachmentList; Test.stopTest(); rrList = [SELECT id, Number_of_Attachments__c FROM Rate_Review__c WHERE id IN: rrIdList]; System.assert(rrList.size() == numRecords1, 'NOT ENOUGH RATE REVIEWS. EXPECTED: ' + 0 + ' ACTUAL: ' + rrList.size() ); for(Rate_Review__c rrfinal: rrList){ System.assert(rrfinal.Number_of_Attachments__c == 0 , 'NUM OF ATTACHMENTS NOT SET EXPECTED: ' + rrfinal.Number_of_Attachments__c + ' ACTUAL: ' + numRecords1); System.debug('NUMBER OF ATTACHMENTS FIELD: ' + rrfinal.Number_of_Attachments__c); } } }
I currently have 56% code coverage on my trigger and 100% coverage on my main class.
- William Roach 9
- April 29, 2019
- Like
- 0