-
ChatterFeed
-
0Best Answers
-
0Likes Received
-
0Likes Given
-
9Questions
-
5Replies
Remove SOQL from For Loop (Apex controller - Lightning component)
I am looking for some pointers on how to correctly structure this short apex function. I am using this to populate a lightning component list like so:
The issue is I am trying to remove the soql query on the campaigns from the campaignMember.campaignId but need some direction. Any ideas?
@AuraEnabled public static List<Campaign> getCampaigns(String conId, String RT){ List<CampaignMember> cmL = new List<CampaignMember>(); List<Campaign> cl = new List<Campaign>(); Custom_Related_Lists__c cusRL =[SELECT Record_Type_API_Name__c, Fields__c FROM Custom_Related_Lists__c WHERE Record_Type_API_Name__c=:RT LIMIT 1]; sObject r = [SELECT id, name, DeveloperName from RecordType Where sObjectType='Campaign' AND DeveloperName=:RT LIMIT 1]; cmL = [SELECT campaignId, ContactId FROM CampaignMember Where ContactId=:conId]; for(CampaignMember c: cmL){ try{ Campaign cam = new Campaign(); String rId = r.id; String cId = c.campaignId; String query = 'SELECT id, Name, RecordTypeId,' + cusRL.Fields__c + ' from campaign where RecordTypeId=:rId AND id=:cId order by CreatedDate desc'; cam = Database.query(query); System.debug('cam' +cam); if(cam!=null){ cl.add(cam); } } catch(exception e){ System.debug('error' + e); } } return cl; }
- Ben Allington 7
- November 24, 2017
- Like
- 0
Can't get test coverage where am i going wrong? Apex Trigger
Hi Dev community, I have written an apex trigger to automatically convert an opportunity product to an asset dependent on criteria, I have managed to write a test class but I think I am missing something simple to get coverage. As it stands I only get 9% coverage on my trigger.
Apex Trigger
trigger OpportunityAssetonClosedWon on Opportunity (after insert, after update) { for(Opportunity o: trigger.new){ if(o.isWon==true && o.HasOpportunityLineItem==true){ String opptyId = o.Id; OpportunityLineItem[] OLI = [Select UnitPrice, Quantity, PricebookEntry.Product2Id, Product2.Name, Product2.Family, PricebookEntry.Product2.Name From OpportunityLineItem WHERE OpportunityId=:opptyId]; Asset[] ast = new Asset[]{}; Asset a = new Asset(); for(OpportunityLineItem ol: OLI){ if(ol.Product2.Family=='Terminal' || ol.Product2.Family=='Gateway' ){ a = new Asset(); a.AccountId = o.AccountId; a.Product2Id= ol.PricebookEntry.Product2Id; a.Quantity= 1; a.Price= ol.UnitPrice; a.PurchaseDate=o.CloseDate; a.status='Purchased'; a.Name = ol.Product2.Name; ast.add(a); ol.Converted_to_Asset__c = true; } } update OLI; insert ast; } } }
Apex Test Class
@isTest public class OpportunityAssetonClosedWonTest { static testMethod void closedOpportunity() { Account testAcc = new Account(Name = 'TestAccount'); insert testAcc; Pricebook2 p = new Pricebook2(Name = 'Testbook'); insert p; Opportunity testOpportunity = new Opportunity( StageName = 'Sourcing Demand', CloseDate = Date.newInstance(2017,12,31), AccountId = testAcc.Id, Name = 'Test Opportunity Triggers', Pricebook2Id=Test.getStandardPricebookId() ); insert testOpportunity; Pricebook2 pb22 = new Pricebook2(Name='testDIE'); insert pb22; Product2 pro1 = new Product2(Name='BXAD', isActive=true ,Family = 'Terminal'); insert pro1; Product2 pro2 = new Product2(Name='BXCD', isActive=true ,Family = 'Gateway'); insert pro2; Product2 pro3 = new Product2(Name='BXBD', isActive=true ,Family = 'Card Not Present'); insert pro3; PricebookEntry pbe1 =new PricebookEntry(UnitPrice=10000,Product2Id=pro1.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe1; PricebookEntry pbe2 =new PricebookEntry(UnitPrice=5000,Product2Id=pro2.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe2; PricebookEntry pbe3 =new PricebookEntry(UnitPrice=1000,Product2Id=pro3.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe3; OpportunityLineItem OPplineitem1 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe1.Id); insert OPplineitem1; OpportunityLineItem OPplineitem2 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe2.Id); insert OPplineitem2; OpportunityLineItem OPplineitem3 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe3.Id); insert OPplineitem3; Test.startTest(); testOpportunity.StageName = 'Closed/Won'; update testOpportunity; Test.stopTest(); System.assertEquals(testOpportunity.StageName, 'Closed/Won'); } }
- Ben Allington 7
- March 06, 2017
- Like
- 0
Help structuring Apex Test class for Opportunity trigger
I have developed a test class which automatically converts opportunity products to assets taking dependant values as seen below:
I am having trouble structuring my test class I have left with what I have up until I am getting errors. If someone could show me how to approach the rest would be hugely appreciated. Test class is shown below
trigger OpportunityAssetonClosedWon on Opportunity (after insert, after update) { for(Opportunity o: trigger.new){ if(o.isWon==true && o.HasOpportunityLineItem==true){ String opptyId = o.Id; OpportunityLineItem[] OLI = [Select UnitPrice, Quantity, PricebookEntry.Product2Id, Product2.Name, Product2.Family, PricebookEntry.Product2.Name From OpportunityLineItem WHERE OpportunityId=:opptyId]; Asset[] ast = new Asset[]{}; Asset a = new Asset(); for(OpportunityLineItem ol: OLI){ if(ol.Product2.Family=='Terminal' || ol.Product2.Family=='Gateway' ){ a = new Asset(); a.AccountId = o.AccountId; a.Product2Id= ol.PricebookEntry.Product2Id; a.Quantity= 1; a.Price= ol.UnitPrice; a.PurchaseDate=o.CloseDate; a.status='Purchased'; a.Name = ol.Product2.Name; ast.add(a); ol.Converted_to_Asset__c = true; } } update OLI; insert ast; } } }
I am having trouble structuring my test class I have left with what I have up until I am getting errors. If someone could show me how to approach the rest would be hugely appreciated. Test class is shown below
@isTest public class OpportunityAssetonClosedWonTest { static testMethod void closedOpportunity() { Account testAcc = new Account( Name = 'TestAccount' ); insert testAcc; Pricebook2 p = new Pricebook2( Name = 'Testbook'); insert p; Opportunity testOpportunity = new Opportunity( StageName = 'Sourcing Demand', CloseDate = Date.newInstance(2017,12,31), AccountId = testAcc.Id, Name = 'Test Opportunity Triggers', Pricebook2Id=p.id ); insert testOpportunity; Product2 p1 = new Product2( Name = 'prod1', Family = 'Terminal'); insert p1; PricebookEntry pE = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p1.Id); Product2 p2 = new Product2( Name='prod2', Family='Gateway'); insert p2; PricebookEntry pE2 = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p2.Id); Product2 p3 = new Product2( Name = 'prod3', Family = 'Card Not Present'); insert p3; PricebookEntry pE3 = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p3.Id); testOpportunity.StageName = 'Closed/Won'; Test.startTest(); update testOpportunity; Test.stopTest(); } }
- Ben Allington 7
- March 02, 2017
- Like
- 0
Help structuring test class for Apex Trigger
I have developed a test class which automatically converts opportunity products to assets taking dependant values as seen below:
I am having trouble structuring my test class but ive finally worked out my errors. I think I am missing something. Test class is shown below
trigger OpportunityAssetonClosedWon on Opportunity (after insert, after update) { for(Opportunity o: trigger.new){ if(o.isWon==true && o.HasOpportunityLineItem==true){ String opptyId = o.Id; OpportunityLineItem[] OLI = [Select UnitPrice, Quantity, PricebookEntry.Product2Id, Product2.Name, Product2.Family, PricebookEntry.Product2.Name From OpportunityLineItem WHERE OpportunityId=:opptyId]; Asset[] ast = new Asset[]{}; Asset a = new Asset(); for(OpportunityLineItem ol: OLI){ if(ol.Product2.Family=='Terminal' || ol.Product2.Family=='Gateway' ){ a = new Asset(); a.AccountId = o.AccountId; a.Product2Id= ol.PricebookEntry.Product2Id; a.Quantity= 1; a.Price= ol.UnitPrice; a.PurchaseDate=o.CloseDate; a.status='Purchased'; a.Name = ol.Product2.Name; ast.add(a); ol.Converted_to_Asset__c = true; } } update OLI; insert ast; } } }
I am having trouble structuring my test class but ive finally worked out my errors. I think I am missing something. Test class is shown below
@isTest public class OpportunityAssetonClosedWonTest { static testMethod void closedOpportunity() { Account testAcc = new Account( Name = 'TestAccount' ); insert testAcc; Pricebook2 p = new Pricebook2( Name = 'Testbook'); insert p; Opportunity testOpportunity = new Opportunity( StageName = 'Sourcing Demand', CloseDate = Date.newInstance(2017,12,31), AccountId = testAcc.Id, Name = 'Test Opportunity Triggers', Pricebook2Id=p.id ); insert testOpportunity; Product2 p1 = new Product2( Name = 'prod1', Family = 'Terminal'); insert p1; PricebookEntry pE = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p1.Id); Product2 p2 = new Product2( Name='prod2', Family='Gateway'); insert p2; PricebookEntry pE2 = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p2.Id); Product2 p3 = new Product2( Name = 'prod3', Family = 'Card Not Present'); insert p3; PricebookEntry pE3 = new PricebookEntry( Pricebook2Id=p.Id, Product2Id=p3.Id); OpportunityLineItem OLI1 = new OpportunityLineItem( OpportunityId=testOpportunity.Id, Quantity = 1, UnitPrice = 1 ); insert OLI1; testOpportunity.StageName = 'Closed/Won'; Test.startTest(); update testOpportunity; Test.stopTest(); } }
- Ben Allington 7
- March 02, 2017
- Like
- 0
Using Batch Scheduling for mass emails apex
I am wondering how to implement my mass emails so they are scheduled so a batch of 100 is sent out every 30 minutes until all emails are sent out, as it stands I have added in ability to batch send all your emails but due to the limitations of 5,000 emails per day I am looking to develop a work around.
I have managed to add the logic for the process in my SchSentReport class but am struggling to get them working together so that the batches of 100 are processed separately. Thanks
SchSentReport
SendReportPageController
I dont think this class has any relevance on the functionality but added it just incase anyone felt it was relevant.
I have managed to add the logic for the process in my SchSentReport class but am struggling to get them working together so that the batches of 100 are processed separately. Thanks
SchSentReport
global class SchSentReport implements Schedulable{ integer count = 1; public SchSentReport(){ } global void execute(SchedulableContext sc) { //check apex job available in system before run batch if(BatchSendReports.isAvailableApexJob()){ BatchSendReports batch = new BatchSendReports(); Database.executeBatch(batch, 100);//100 because single email allow send 100 records per mail setScheduleNext30mn(); System.debug('Batch No. ' + count + ' Added'); count = count + 1; }else{ System.abortJob(SC.getTriggerId()); } } /** * The shedule will start next 30mn */ public void setScheduleNext30mn(){ SchSentReport sch = new SchSentReport(); String myTime = '0 $1 h do m ? y'; Datetime dt = System.now(); dt = dt.addMinutes(30 * count); //schedule at next 30 minutes System.debug('Batch Time set for :' + dt); myTime=myTime.replace('h', dt.hour()+''); myTime=myTime.replace('do', dt.day()+''); myTime=myTime.replace('m', dt.month()+''); myTime=myTime.replace('y', dt.year()+''); myTime=myTime.replace('$1', dt.minute()+''); System.debug('My Time :' + myTime); System.schedule('SchSentReport', myTime, sch); } }
SendReportPageController
public with sharing class SendReportPageController { public Boolean sendDashboard {get;set;} public Boolean sendLocationCO2Report {get;set;} public Boolean sendGroupCO2Report {get;set;} public Boolean sendPartnerReport {get;set;} public Boolean sendLinkedReport {get;set;} public SendReportPageController(){ sendDashboard = false; sendLocationCO2Report = false; sendGroupCO2Report = false; sendPartnerReport = false; sendLinkedReport = false; } public PageReference doSend(){ if(!sendDashboard && !sendLocationCO2Report && !sendGroupCO2Report && !sendPartnerReport && !sendLinkedReport){ Apexpages.Message msg = new Apexpages.Message(ApexPages.Severity.ERROR, 'You have to select at least a report type!'); Apexpages.addMessage(msg); return null; } String msgVal = ''; Boolean isSent = false; if(BatchSendReports.isAvailableApexJob()){ BatchSendReports batch = new BatchSendReports(); batch.sendDashboard = sendDashboard; batch.sendLocationCO2Report = sendLocationCO2Report; batch.sendGroupCO2Report = sendGroupCO2Report; batch.sendPartnerReport = sendPartnerReport; batch.sendLinkedReport = sendLinkedReport; Database.executeBatch(batch, 100);//100 because single email allow send 100 records per mail msgVal = 'Sending report is in progress.'; isSent = true; }else{ msgVal = 'Apex job isnot available. Please try again later.'; } Apexpages.Message msg = new Apexpages.Message(isSent ? ApexPages.Severity.CONFIRM : ApexPages.Severity.Warning, msgVal); Apexpages.addMessage(msg); return null; }BatchSendReports
I dont think this class has any relevance on the functionality but added it just incase anyone felt it was relevant.
public class BatchSendReports implements Database.Batchable<sObject>{ private ID accid; private static final String DASHBOARD_TEMP = 'Monthly_Location_Dashboard'; private static final String MONTHLY_TEMP = 'Monthly_Recycling_Report'; private static final String GROUP_TEMP = 'Group_Recycling_Report'; private static final String PARTNER_TEMP = 'Partner_Recycling_Report'; private static final String LINKED_TEMP = 'Linked_Recycling_Report'; private static final String DASHBOARD_REPORT= 'dashboard'; private static final String MONTHLY_REPORT = 'co2 report'; private static final String GROUP_REPORT = 'enqix spreadsheet'; private static final String PARTNER_REPORT = 'partnership co2 report'; private static final String LINKED_REPORT = 'linked account co2 report'; private Map<String, String> mapReportTypeEmailTemplate = new Map<String, String>{ DASHBOARD_REPORT=> DASHBOARD_TEMP, MONTHLY_REPORT => MONTHLY_TEMP, GROUP_REPORT => GROUP_TEMP, PARTNER_REPORT => PARTNER_TEMP, LINKED_REPORT => LINKED_TEMP}; public Boolean sendDashboard {get;set;} public Boolean sendLocationCO2Report {get;set;} public Boolean sendGroupCO2Report {get;set;} public Boolean sendPartnerReport {get;set;} public Boolean sendLinkedReport {get;set;} //for testing public BatchSendReports(ID accid){ this.accid = accid; ////If run from test, default value will true this.sendDashboard = Test.isRunningTest(); this.sendLocationCO2Report = Test.isRunningTest(); this.sendGroupCO2Report = Test.isRunningTest(); this.sendPartnerReport = Test.isRunningTest(); this.sendLinkedReport = Test.isRunningTest(); } public BatchSendReports(){ //If run from test, default value will true this.sendDashboard = Test.isRunningTest(); this.sendLocationCO2Report = Test.isRunningTest(); this.sendGroupCO2Report = Test.isRunningTest(); this.sendPartnerReport = Test.isRunningTest(); this.sendLinkedReport = Test.isRunningTest(); } public Database.QueryLocator start(Database.BatchableContext BC){ Set<String> reportTypes = new Set<String>(); if(sendDashboard) reportTypes.add(DASHBOARD_REPORT); if(sendLocationCO2Report) reportTypes.add(MONTHLY_REPORT); if(sendGroupCO2Report) reportTypes.add(GROUP_REPORT); if(sendPartnerReport) reportTypes.add(PARTNER_REPORT); if(sendLinkedReport) reportTypes.add(LINKED_REPORT); String query = 'Select Name, Main_Contact_Email__c, Report_Type__c From Account '; String condition = ' Where Report_Type__c != null AND Report_Type__c in:reportTypes ' + (accid != null ? ' AND id=:accid ' : '') ; return Database.getQueryLocator(query + condition); } public void execute(Database.BatchableContext BC, List<sObject> scope){ //get all related email templates Map<String, String> mapEmailTemplates = new Map<String, String>(); for (EmailTemplate et : [SELECT Id, DeveloperName FROM EmailTemplate WHERE DeveloperName in:mapReportTypeEmailTemplate.values()]) { mapEmailTemplates.put(et.DeveloperName, et.Id); } //get all Contacts related Account that its Receive_Global_Report__c = true Map<String, List<String>> mapAccConGlobalReport = new Map<String, List<String>>(); for(Contact con: [Select Email, AccountId From Contact Where Receive_Global_Report__c = true AND Email != null AND AccountID in: (List<Account>) scope]) { if(!mapAccConGlobalReport.containsKey(con.AccountId)){ mapAccConGlobalReport.put(con.AccountId, new List<String>()); } mapAccConGlobalReport.get(con.AccountId).add(con.Email); } List<OrgWideEmailAddress> orgWilds = [Select Id From OrgWideEmailAddress Where DisplayName ='First Mile' AND IsAllowAllProfiles = true limit 1]; List<Messaging.SingleEmailMessage> lstMails = new List<Messaging.SingleEmailMessage>(); List<ResultReportSent__c> lstRecordResults = new List<ResultReportSent__c>(); for(Account acc: (List<Account>) scope){ String reportType = acc.Report_Type__c.toLowerCase(); Boolean isGeneratePDF = mapReportTypeEmailTemplate.containsKey(reportType) && !mapReportTypeEmailTemplate.get(reportType).equalsIgnoreCase(DASHBOARD_TEMP); Boolean isGroup = reportType.equalsIgnoreCase(GROUP_REPORT); Boolean isPartner = reportType.equalsIgnoreCase(PARTNER_REPORT); Boolean isLinked = reportType.equalsIgnoreCase(LINKED_REPORT); //get email template by Account report type String emailTemp = mapReportTypeEmailTemplate.containsKey(reportType) ? mapReportTypeEmailTemplate.get(reportType) : ''; if(emailTemp == '') continue; String emailTemplateId = mapEmailTemplates.containsKey(emailTemp) ? mapEmailTemplates.get(emailTemp) : ''; if(emailTemplateId == '') continue; List<String> lstReciptients = new List<String>(); //if Account report type is Dashboard or Monthly report, it required acc.Main_Contact_Email__c if((reportType.equalsIgnoreCase(DASHBOARD_REPORT) || reportType.equalsIgnoreCase(MONTHLY_REPORT)) && acc.Main_Contact_Email__c == null) continue; if(acc.Main_Contact_Email__c != null){ lstReciptients.add(acc.Main_Contact_Email__c); } //when the "Group Recycling Report" or "Partner Recycling Report" OR "Linked Recycled Report" is pressed, //any contacts for that account that "Receive Global Report" checked will get the group report. if((isGroup || isPartner || isLinked) && mapAccConGlobalReport.containsKey(acc.Id)){ lstReciptients.addall(mapAccConGlobalReport.get(acc.Id)); } //record the results by report type of the number sent for each batch lstRecordResults.add(new ResultReportSent__c( Account__c = acc.Id, Status__c = 'Sent', Date_Sent__c = System.today(), Name = System.now().format('MMMM yyyy') + ' Report')); //prepare email lstMails.add(SendingEmailUtils.generateEmail(emailTemplateId, acc.Id, lstReciptients, orgWilds, isGeneratePDF, isGroup, isPartner, isLinked)); } if(!lstMails.isEmpty()){ try { Messaging.sendEmail(lstMails); if(!lstRecordResults.isEmpty()){ insert lstRecordResults; } }catch (Exception ex) { System.debug('****** Error: ' + ex.getMessage()); } } } public void finish(Database.BatchableContext BC){ AsyncApexJob asyn = [Select Status, CreatedBy.Email, TotalJobItems, NumberOfErrors From AsyncApexJob Where id=:BC.getJobId() limit 1]; String[] toAddresses = new String[]{asyn.CreatedBy.Email}; Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setSubject('Batch Sending Report ' + asyn.Status); mail.setPlainTextBody('The batch Apex job processed ' + asyn.TotalJobItems + ' batches with ' + asyn.NumberOfErrors + ' failures.'); mail.setToAddresses(toAddresses); mail.setBccAddresses(new List<String>{/*'customers@thefirstmile.co.uk'*/}); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } public static Boolean isAvailableApexJob(){ return 5 > [Select count() From AsyncApexJob where Status in ('Processing', 'Preparing')]; } }
- Ben Allington 7
- December 21, 2016
- Like
- 0
Can't get 100% code coverage with test class, stuck at 63%
Can't seem to get above 65% test coverage, I have marked where I am lacked coverage as far as I can tell it should cover this area but I am clearly missing something, any ideas?
MainClass
TestClass
MainClass
public class RelatedContantClass { public static void addRelatedContact (List <Lead> leadsFromTrigger) { //Create List for Opportunities to be updated from list <Opportunity> opportunityUpdates = new list <Opportunity> (); //For each Lead in the Trigger for (Lead currentLead : leadsFromTrigger){ //Check if they have been converted if (currentLead.IsConverted == TRUE){ //Check if the Lead Conversion included an Opportunity, then assign the contact to the Opportunity as Opportunity Contact Role Records if (currentLead.convertedOpportunityId != NULL) { list <Lead_Contact_Connector__c> LeadContactList = new list <Lead_Contact_Connector__c> ([Select Related_Contact__c, Contact_Role__c, Lead__c From Lead_Contact_Connector__c where Lead__c = :currentLead.Id]); list <OpportunityContactRole> ContactRoleNew = new list <OpportunityContactRole> (); for (Lead_Contact_Connector__c CurrentContact: LeadContactList){ OpportunityContactRole OppCon = new OpportunityContactRole(); OppCon.ContactId = CurrentContact.Related_Contact__c; OppCon.OpportunityId = currentLead.convertedOpportunityId; OppCon.Role = CurrentContact.Contact_Role__c; ContactRoleNew.add(OppCon); } insert ContactRoleNew; } } }}}
TestClass
@isTest private class RelatedContactClassTest { static testMethod void testCreateContactFromCandidate() { //Set up basic testing data. //Create a single Account for converting with an Opportunity Account aAccount = new Account ( Name = 'First Test'); //Create a single Contact for converting with an Opportunity Contact aContact = new Contact ( FirstName = 'First Test', LastName = 'Lead', AccountId = aAccount.Id); //Create a single Lead for converting with an Opportunity Lead aLead = new Lead ( FirstName = 'First Test', LastName = 'Lead', Company = 'Test Company X', Status = 'New', LeadSource = 'Web'); //create opportunity Opportunity aOpp = new Opportunity( Name='Test Opp' ); //Create a single Related Contact for converting with an Opportunity Lead_Contact_Connector__c aRelatedContact = new Lead_Contact_Connector__c( Lead__c = aLead.Id, Contact_Role__c = 'Authorised Contact', Related_Contact__c = aContact.Id); //Create a single Lead for converting without an Opportunity Lead bLead = new Lead ( FirstName = 'Second Test', LastName = 'Lead - No Opportunity', Company = 'Test Company Y', Status = 'New', LeadSource = 'Web'); //Create a single Account for converting with an Opportunity Account bAccount = new Account ( Name = 'First Test'); //Create a single Contact for converting with an Opportunity Contact bContact = new Contact ( FirstName = 'First Test', LastName = 'Lead', AccountId = bAccount.Id); //Create a single Related Contact for converting with an Opportunity Lead_Contact_Connector__c bRelatedContact = new Lead_Contact_Connector__c( Lead__c = bLead.Id, Contact_Role__c = 'Authorised Contact', Related_Contact__c = bContact.Id); // Create 210 Leads for Converting with Opportunities List <Lead> leadList = new List <Lead> (); List <Account> AccountList = new List <Account> (); List <Contact> ContactList = new List <Contact> (); List <Lead_Contact_Connector__c> LCCList = new List <Lead_Contact_Connector__c> (); //Loop to create 210 Leads For (Integer i=0; i < 210; i++) { Account currentAccount = new Account (); currentAccount.Name = 'Test ' + i; Contact currentContact = new Contact (); currentContact.FirstName = 'Test ' + i; currentContact.LastName = 'Lead'; currentContact.AccountId = currentAccount.Id; ContactList.add(currentContact); Lead currentLead = new Lead (); currentLead.FirstName = 'Test ' + i; currentLead.LastName = 'Lead'; currentLead.Company = 'Test Company ' + i; currentLead.Status = 'New'; currentLead.LeadSource = 'Web'; Lead_Contact_Connector__c relatedContactLarge = new Lead_Contact_Connector__c (); relatedContactLarge.Lead__c = currentLead.Id; relatedContactLarge.Contact_Role__c = 'Authorised Contact'; relatedContactLarge.Related_Contact__c = currentContact.Id; LCCList.add(relatedContactLarge); leadList.add(currentLead); AccountList.add(currentAccount); } //Set the converted Lead Status as a Lead Status that exists in the org. LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1]; //_______________________________________________ //Create each of the single leads and multi leads system.debug('single Lead: ' + aLead.FirstName + aLead.LastName); insert aLead; system.debug('single Lead: ' + bLead.FirstName + bLead.LastName); insert bLead; system.debug(leadList); database.insert(leadList); database.insert(LCCList); database.insert(ContactList); database.insert(AccountList); //_______________________________________________ //Carry out the processes and testing logic //Test1 //Verify that the single Lead converts with anis the converted Contact. Database.LeadConvert lc = new database.LeadConvert(); lc.setLeadId(aLead.id); //This selects this first converted lead status possible. lc.setConvertedStatus(convertStatus.MasterLabel); lc.setOpportunityName('Test Opp 1'); //This tests that the Lead conversion was successful. Database.LeadConvertResult lcr = Database.convertLead(lc); System.assert(lcr.isSuccess()); system.debug(lcr.isSuccess()); System.assert(LCCList.size() != 0); }
- Ben Allington 7
- December 20, 2016
- Like
- 0
CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, LineItemCreation: maximum trigger depth exceeded
I have created two triggers to affect the opportunity line item and opprtunity. Keep getting thrown that error and unsure where my bulkification has gone wrong.
LineItemCreation Trigger
OpportunityUpdate Trigger
LineItemCreation Trigger
trigger LineItemCreation on OpportunityLineItem (after insert, after update) { Product2 productsRef = new Product2(); Opportunity oppRef = new Opportunity(); String oliIdd; Decimal OliDayPrice; Integer daysDiff; List<OpportunityLineItemSchedule> OLISlist = new List<OpportunityLineItemSchedule>(); for(OpportunityLineItem OLI :Trigger.new){ OLIidd = OLI.Id; try{ productsRef = [SELECT Id, Basis__c, Family FROM Product2 WHERE Id =:OLI.Product2Id]; } catch(Exception e){ System.debug('The following exception has occurred: ' + e.getMessage()); } oppRef = [SELECT Id, Contract_Start_Date__c, Go_Live_Date__c, Contract_End_Date__c FROM Opportunity WHERE Id=:OLI.OpportunityId]; daysDiff = oppRef.Contract_Start_Date__c.daysBetween(oppRef.Contract_End_Date__c); System.Debug('DaysDifference = ' + daysDiff); OliDayPrice = (OLI.TotalPrice / daysDiff); System.Debug('Dailys Schedule Record Price = ' + oliDayPrice); Decimal totalPaid = 0; } for(Integer i=0; i < daysDiff; i++){ if((productsRef.Basis__c =='Per Site Per Month' || productsRef.Basis__c =='Per Device Per Month') && productsRef.Family=='Licensing'){ OpportunityLineItemSchedule OLISl = new OpportunityLineItemSchedule( OpportunityLineItemId=OLIidd, Revenue=OliDayPrice, ScheduleDate=(oppRef.Contract_Start_Date__c + i), //issue with it adding on revenue to saleprice Type='Revenue'); OLISlist.add(OLISl); } } if(trigger.isInsert || trigger.isUpdate){ if(!OLISlist.isEmpty()){ insert OLISlist; System.debug('List Inserted:' + OLISlist); } } }
OpportunityUpdate Trigger
trigger OpportunityUpdateTrigger on Opportunity (after update) { List<Product2> getProducts = new List<Product2>(); List<Opportunity> oldOpp = new List<Opportunity>(); List<Opportunity> newOpp = new List<Opportunity>(); List<OpportunityLineItemSchedule> getSchedules = new List<OpportunityLineItemSchedule>(); List<OpportunityLineItem> OLIlist = new List<OpportunityLineItem>(); Date conStartNew; Date conStartOld; Date conEndNew; Date conEndOld; Date goLiveNew; Date goLiveOld; set<Id> getOLI = new set<Id>(); set<Id> OLIid = new set<Id>(); for(Opportunity old : trigger.old){ //get oli and add to list conStartOld = old.Contract_Start_Date__c; conEndOld = old.Contract_End_Date__c; goLiveOld = old.Go_Live_Date__c; for(OpportunityLineItem OLI : [SELECT Id, Product2Id, Quantity FROM OpportunityLineItem WHERE OpportunityId=:old.Id]){ getOLI.add(OLI.Product2Id); OLIid.add(OLI.Id); OLIlist.add(OLI); } //GET PRODUCTS ADD TO LIST for(Product2 p : [SELECT Id, Basis__c, Family FROM Product2 WHERE Id=:getOLI AND Family='Licensing' AND (Basis__c='Per Device Per Month' OR Basis__c='Per Site Per Month')]){ getProducts.add(p); System.debug('products : ' + getProducts); } //GET ALL REVENUE SCHEDULES RELATED TO OLI for(OpportunityLineItemSchedule s : [SELECT Id, ScheduleDate FROM OpportunityLineItemSchedule WHERE OpportunityLineItemId = :OLIid]){ System.debug('OLI ID =' + OLIid); getSchedules.add(s); System.debug('Schedules =' + getSchedules); } } System.debug('s = ' + getSchedules); for(Opportunity o : trigger.new){ conStartNew = o.Contract_Start_Date__c; conEndNew = o.Contract_End_Date__c; goLiveNew = o.Go_Live_Date__c; } if(Trigger.isUpdate){ if(conStartNew != conStartOld || goLiveNew != goLiveOld || conEndNew != conEndOld){ System.debug('Date changed!'); Delete getSchedules; System.debug('Schedules Removed'); for(OpportunityLineItem x : [SELECT Id FROM OpportunityLineItem WHERE Id=:OLIid]){ update x; } } } }
- Ben Allington 7
- December 06, 2016
- Like
- 0
CSV import class failing after adding new lookup object
The system currently takes a csv file to be uploaded and populates the fields, after adding our partnership lookup field object below:
The upload has been displaying this error and failing:
I have looked at the idea of perhaps the field filter being the issue but this doesn't appear to be the case, I have looked over my import class and seem to have hit a wall, if anyone can pin point where the issue seems to stem from that would be hugely appreciated. My apex class is below and hopefully you can give me some advice.
EnquixAccountImportBatch
The upload has been displaying this error and failing:
processing started... The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 552 The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 1082 The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 1122 .....
I have looked at the idea of perhaps the field filter being the issue but this doesn't appear to be the case, I have looked over my import class and seem to have hit a wall, if anyone can pin point where the issue seems to stem from that would be hugely appreciated. My apex class is below and hopefully you can give me some advice.
EnquixAccountImportBatch
global without sharing class EnquixAccountImportBatch implements Database.Batchable<String>, Database.Stateful { @TestVisible private Enqix_Import__c currentRecord; @TestVisible private Boolean headerProcessed; @TestVisible private Integer startRow; @TestVisible private String csvFile; @TestVisible private List<String> messages; @TestVisible private Map<String, Integer> headerIndexes; global EnquixAccountImportBatch() { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch .ctor - start'); messages = new List<String>(); headerProcessed = false; List<Enqix_Import__c> enqixImports = EquixImportManager.getPendingEnqixImports(EquixImportManager.IMPORT_TYPE_ACCOUNT); System.debug(LoggingLevel.DEBUG, 'enqixImports : ' + enqixImports); if (enqixImports.size() > 0) { currentRecord = enqixImports[0]; currentRecord.Status__c = EquixImportManager.STATUS_IN_PROGRESS; update currentRecord; } System.debug(LoggingLevel.DEBUG, 'currentRecord: ' + currentRecord); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch .ctor - end'); } global Iterable<String> start(Database.BatchableContext info) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - start'); messages.add('processing started...'); try { if (currentRecord == null) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end no records'); return new List<String>(); } else { Attachment att = EquixImportManager.getLatestAttachmentForEnqixImport(currentRecord.Id); // csvFile = att.Body.toString(); // if (!csvFile.endsWith(Parser.CRLF)) { // // csvFile += Parser.CRLF; // } //csvFile = csvFile.subString(csvFile.indexOf(Parser.CRLF) + Parser.CRLF.length(), csvFile.length()); System.debug('Final heap size: ' + Limits.getHeapSize()); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end processing'); return new CSVIterator(att.Body.toString(), Parser.CRLF); } } catch (Exception ex) { System.debug(LoggingLevel.ERROR, ex.getMessage() + ' :: ' + ex.getStackTraceString()); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end no attachment'); messages.add(String.format('Error while parsing Enquix Import: {0}. Error details: {1}. Stack Trace: {2}', new List<String> { currentRecord.Id, ex.getMessage(), ex.getStackTraceString() })) ; return new List<String>(); } } global void execute(Database.BatchableContext info, List<String> scope) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch execute - start'); System.debug(LoggingLevel.DEBUG, 'scope.size(): ' + scope.size()); //first create new csv from the scope lines String importFile = ''; for (String row : scope) { importFile += row + Parser.CRLF; } List<List<String>> parsedData = new List<List<String>>(); try { parsedData = CSVReader.readCSVFile(importFile); } catch (Exception ex) { messages.add(String.format('Error while parsing Enquix Import: {0}. Error details: {1}', new List<String> { currentRecord.Id, ex.getStackTraceString() })); System.debug(LoggingLevel.ERROR, ex.getMessage() + '\n' + ex.getStackTraceString()); return; } System.debug(LoggingLevel.DEBUG, 'parsedData.size(): ' + parsedData.size()); //then process header if needed System.debug(LoggingLevel.DEBUG, 'headerProcessed: ' + headerProcessed); if (!headerProcessed) { headerIndexes = EquixImportManager.processHeader(parsedData[0]); headerProcessed = true; parsedData.remove(0); } List<Account> accounts = new List<Account>(); Set<String> accountsEnqixIdSet = new Set<String>(); for (List<String> csvLine : parsedData) { try{ if (!accountsEnqixIdSet.contains(csvLine.get(headerIndexes.get(EnquixImportMappingsManager.PARENT_ID_LOCATION_MAPPING)))) { accounts.add(AccountManager.createAccountRecordFromCSVLine( csvLine , EquixImportManager.getImportMappingMap().get( EquixImportManager.IMPORT_TYPE_ACCOUNT).get( EnquixImportMappingsManager.ACCOUNT_RECORD_GROUP) , headerIndexes )); accountsEnqixIdSet.add(csvLine.get(headerIndexes.get(EnquixImportMappingsManager.PARENT_ID_LOCATION_MAPPING))); } } catch(Exception ex) { messages.add('The following error has occurred.\n' + ex.getStackTraceString() + ': ' + ex.getMessage() + '. Row causing the error:' + String.join(csvLine, ',')); System.debug('The following error has occurred.'); System.debug(ex.getStackTraceString() + ': ' + ex.getMessage()); System.debug('Row causing the error:' + String.join(csvLine, ',')); } } System.debug(LoggingLevel.DEBUG, 'accounts.size(): ' + accounts.size()); Database.UpsertResult[] saveResults = Database.upsert(accounts, Account.Enqix_ID__c, false); Integer listIndex = 0; // We start at 2 because the CSV data starts in row 2 for (Database.UpsertResult sr : saveResults) { if (!sr.isSuccess()) { for (Database.Error err : sr.getErrors()) { messages.add('The following error has occurred.\n' + err.getStatusCode() + ': ' + err.getMessage() + '. Account fields that affected this error:\n ' + err.getFields() + '\NRow index : ' + listIndex+2); System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Account fields that affected this error: ' + err.getFields()); System.debug('The error was caused by the sobject at index: ' + listIndex); System.debug(accounts.get(listIndex)); } } listIndex++; } List<Account> locations = new List<Account>(); for (List<String> csvLine : parsedData) { locations.add(AccountManager.createLocationRecordFromCSVLine( csvLine , EquixImportManager.getImportMappingMap().get( EquixImportManager.IMPORT_TYPE_ACCOUNT).get( EnquixImportMappingsManager.LOCATION_RECORD_GROUP) , headerIndexes )); } System.debug(LoggingLevel.DEBUG, 'locations.size(): ' + locations.size()); saveResults = Database.upsert(locations, Account.Enqix_Location_ID__c, false); listIndex = 0; // We start at 2 because the CSV data starts in row 2 for (Database.UpsertResult sr : saveResults) { if (!sr.isSuccess()) { for (Database.Error err : sr.getErrors()) { messages.add('The following error has occurred.\n' + err.getStatusCode() + ': ' + err.getMessage() + '. Account fields that affected this error:\n ' + err.getFields() + '\NRow index : ' + listIndex+2); System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Account fields that affected this error: ' + err.getFields()); System.debug('The error was caused by the sobject at index: ' + listIndex); System.debug(locations.get(listIndex)); } } listIndex++; } System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch execute - end'); } global void finish(Database.BatchableContext info) { if (currentRecord != null) { messages.add('Processing completed'); currentRecord.Log__c = String.join(messages, '\n'); if(currentRecord.Log__c.length() > EquixImportManager.getLogFieldLength()) { currentRecord.Log__c = currentRecord.Log__c.abbreviate(EquixImportManager.getLogFieldLength()); } if(currentRecord.Log__c.contains('error')) { currentRecord.Status__c = EquixImportManager.STATUS_ERROR; } else { currentRecord.Status__c = EquixImportManager.STATUS_COMPLETED; } update currentRecord; } if (!Test.isRunningTest()) { if (EquixImportManager.getPendingEnqixImports(EquixImportManager.IMPORT_TYPE_ACCOUNT).size() > 0) { EnquixAccountImportBatch.batchMe(); } else { EnquixOrderImportBatch.batchMe(); } } } public static Boolean batchMe() { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch batchMe - start'); Id jobId; if (!BatchUtility.accountBatchInstanceRunning()) { System.debug(LoggingLevel.DEBUG, 'Account_Batch_Size__c: ' + Integer.valueOf(EnqixImportCSVParametersManager.getCsvParameters().Account_Batch_Size__c)); jobId = Database.executeBatch(new EnquixAccountImportBatch(), Integer.valueOf(EnqixImportCSVParametersManager.getCsvParameters().Account_Batch_Size__c)); } System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch batchMe - end'); return jobId != null; }
- Ben Allington 7
- November 14, 2016
- Like
- 0
Writing Test Class for my search lightning component
I have been attempting to write a test class for my search function but its throwing me a little, my first time designing a lightning component so if someone could walk me through it that would I would hugely appreciate it.
ContactList.cmp
ControllerListController.js
ContactListController.apxc
SearchBar.cmp
SearchBarController.js
ContactList.cmp
<aura:component controller="ContactListController"> <aura:attribute name="accounts" type="account[]"/> <aura:handler name="init" value="{!this}" action="{!c.doInit}" /> <aura:handler event="c:SearchKeyChange" action="{!c.searchKeyChange}"/> <ul> <aura:iteration items="{!v.accounts}" var="account"> <li> <a href="{! '#/sObject/' + account.Id + '/view'}"> <p>{!account.Name}</p> <p>{!account.Phone}</p> <p>{!account.BillingStreet}</p> </a> </li> </aura:iteration> </ul> </aura:component>
ControllerListController.js
({ doInit : function(component, event) { var action = component.get("c.findAll"); action.setCallback(this, function(a) { component.set("v.accounts", a.getReturnValue()); }); $A.enqueueAction(action); }, searchKeyChange: function(component, event) { var searchKey = event.getParam("searchKey"); var action = component.get("c.findByLocation"); action.setParams({ "searchKey": searchKey }); action.setCallback(this, function(a) { component.set("v.accounts", a.getReturnValue()); }); $A.enqueueAction(action); } })
ContactListController.apxc
public with sharing class ContactListController { @AuraEnabled public static List<Account> findAll() { return [SELECT id, name, BillingStreet, phone FROM Account LIMIT 50]; } @AuraEnabled public static List<Account> findByLocation(String searchKey) { String name = '%' + searchKey + '%'; return [SELECT id, name, phone, BillingStreet FROM Account WHERE BillingStreet LIKE :name LIMIT 50]; } }
SearchBar.cmp
<aura:component > <div> <input type="text" class="form-control" placeholder="Search" onkeyup="{!c.searchKeyChange}"/> </div> </aura:component>
SearchBarController.js
({ searchKeyChange : function(component, event, helper) { var myEvent = $A.get("e.c:SearchKeyChange"); myEvent.setParams({"searchKey":event.target.value}); myEvent.fire(); } })
- Ben Allington 7
- November 07, 2016
- Like
- 0
Remove SOQL from For Loop (Apex controller - Lightning component)
I am looking for some pointers on how to correctly structure this short apex function. I am using this to populate a lightning component list like so:
The issue is I am trying to remove the soql query on the campaigns from the campaignMember.campaignId but need some direction. Any ideas?
@AuraEnabled public static List<Campaign> getCampaigns(String conId, String RT){ List<CampaignMember> cmL = new List<CampaignMember>(); List<Campaign> cl = new List<Campaign>(); Custom_Related_Lists__c cusRL =[SELECT Record_Type_API_Name__c, Fields__c FROM Custom_Related_Lists__c WHERE Record_Type_API_Name__c=:RT LIMIT 1]; sObject r = [SELECT id, name, DeveloperName from RecordType Where sObjectType='Campaign' AND DeveloperName=:RT LIMIT 1]; cmL = [SELECT campaignId, ContactId FROM CampaignMember Where ContactId=:conId]; for(CampaignMember c: cmL){ try{ Campaign cam = new Campaign(); String rId = r.id; String cId = c.campaignId; String query = 'SELECT id, Name, RecordTypeId,' + cusRL.Fields__c + ' from campaign where RecordTypeId=:rId AND id=:cId order by CreatedDate desc'; cam = Database.query(query); System.debug('cam' +cam); if(cam!=null){ cl.add(cam); } } catch(exception e){ System.debug('error' + e); } } return cl; }
- Ben Allington 7
- November 24, 2017
- Like
- 0
Can't get test coverage where am i going wrong? Apex Trigger
Hi Dev community, I have written an apex trigger to automatically convert an opportunity product to an asset dependent on criteria, I have managed to write a test class but I think I am missing something simple to get coverage. As it stands I only get 9% coverage on my trigger.
Apex Trigger
trigger OpportunityAssetonClosedWon on Opportunity (after insert, after update) { for(Opportunity o: trigger.new){ if(o.isWon==true && o.HasOpportunityLineItem==true){ String opptyId = o.Id; OpportunityLineItem[] OLI = [Select UnitPrice, Quantity, PricebookEntry.Product2Id, Product2.Name, Product2.Family, PricebookEntry.Product2.Name From OpportunityLineItem WHERE OpportunityId=:opptyId]; Asset[] ast = new Asset[]{}; Asset a = new Asset(); for(OpportunityLineItem ol: OLI){ if(ol.Product2.Family=='Terminal' || ol.Product2.Family=='Gateway' ){ a = new Asset(); a.AccountId = o.AccountId; a.Product2Id= ol.PricebookEntry.Product2Id; a.Quantity= 1; a.Price= ol.UnitPrice; a.PurchaseDate=o.CloseDate; a.status='Purchased'; a.Name = ol.Product2.Name; ast.add(a); ol.Converted_to_Asset__c = true; } } update OLI; insert ast; } } }
Apex Test Class
@isTest public class OpportunityAssetonClosedWonTest { static testMethod void closedOpportunity() { Account testAcc = new Account(Name = 'TestAccount'); insert testAcc; Pricebook2 p = new Pricebook2(Name = 'Testbook'); insert p; Opportunity testOpportunity = new Opportunity( StageName = 'Sourcing Demand', CloseDate = Date.newInstance(2017,12,31), AccountId = testAcc.Id, Name = 'Test Opportunity Triggers', Pricebook2Id=Test.getStandardPricebookId() ); insert testOpportunity; Pricebook2 pb22 = new Pricebook2(Name='testDIE'); insert pb22; Product2 pro1 = new Product2(Name='BXAD', isActive=true ,Family = 'Terminal'); insert pro1; Product2 pro2 = new Product2(Name='BXCD', isActive=true ,Family = 'Gateway'); insert pro2; Product2 pro3 = new Product2(Name='BXBD', isActive=true ,Family = 'Card Not Present'); insert pro3; PricebookEntry pbe1 =new PricebookEntry(UnitPrice=10000,Product2Id=pro1.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe1; PricebookEntry pbe2 =new PricebookEntry(UnitPrice=5000,Product2Id=pro2.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe2; PricebookEntry pbe3 =new PricebookEntry(UnitPrice=1000,Product2Id=pro3.Id,Pricebook2Id=Test.getStandardPricebookId(), isActive=true,UseStandardPrice = false); insert pbe3; OpportunityLineItem OPplineitem1 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe1.Id); insert OPplineitem1; OpportunityLineItem OPplineitem2 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe2.Id); insert OPplineitem2; OpportunityLineItem OPplineitem3 = new OpportunityLineItem (Quantity=1, OpportunityId=testOpportunity.Id,UnitPrice=0.01,PriceBookEntryId=pbe3.Id); insert OPplineitem3; Test.startTest(); testOpportunity.StageName = 'Closed/Won'; update testOpportunity; Test.stopTest(); System.assertEquals(testOpportunity.StageName, 'Closed/Won'); } }
- Ben Allington 7
- March 06, 2017
- Like
- 0
CSV import class failing after adding new lookup object
The system currently takes a csv file to be uploaded and populates the fields, after adding our partnership lookup field object below:
The upload has been displaying this error and failing:
I have looked at the idea of perhaps the field filter being the issue but this doesn't appear to be the case, I have looked over my import class and seem to have hit a wall, if anyone can pin point where the issue seems to stem from that would be hugely appreciated. My apex class is below and hopefully you can give me some advice.
EnquixAccountImportBatch
The upload has been displaying this error and failing:
processing started... The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 552 The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 1082 The following error has occurred. FIELD_FILTER_VALIDATION_EXCEPTION: Account selected is not a partner. Account fields that affected this error: (Partnership__c) Row index : 1122 .....
I have looked at the idea of perhaps the field filter being the issue but this doesn't appear to be the case, I have looked over my import class and seem to have hit a wall, if anyone can pin point where the issue seems to stem from that would be hugely appreciated. My apex class is below and hopefully you can give me some advice.
EnquixAccountImportBatch
global without sharing class EnquixAccountImportBatch implements Database.Batchable<String>, Database.Stateful { @TestVisible private Enqix_Import__c currentRecord; @TestVisible private Boolean headerProcessed; @TestVisible private Integer startRow; @TestVisible private String csvFile; @TestVisible private List<String> messages; @TestVisible private Map<String, Integer> headerIndexes; global EnquixAccountImportBatch() { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch .ctor - start'); messages = new List<String>(); headerProcessed = false; List<Enqix_Import__c> enqixImports = EquixImportManager.getPendingEnqixImports(EquixImportManager.IMPORT_TYPE_ACCOUNT); System.debug(LoggingLevel.DEBUG, 'enqixImports : ' + enqixImports); if (enqixImports.size() > 0) { currentRecord = enqixImports[0]; currentRecord.Status__c = EquixImportManager.STATUS_IN_PROGRESS; update currentRecord; } System.debug(LoggingLevel.DEBUG, 'currentRecord: ' + currentRecord); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch .ctor - end'); } global Iterable<String> start(Database.BatchableContext info) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - start'); messages.add('processing started...'); try { if (currentRecord == null) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end no records'); return new List<String>(); } else { Attachment att = EquixImportManager.getLatestAttachmentForEnqixImport(currentRecord.Id); // csvFile = att.Body.toString(); // if (!csvFile.endsWith(Parser.CRLF)) { // // csvFile += Parser.CRLF; // } //csvFile = csvFile.subString(csvFile.indexOf(Parser.CRLF) + Parser.CRLF.length(), csvFile.length()); System.debug('Final heap size: ' + Limits.getHeapSize()); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end processing'); return new CSVIterator(att.Body.toString(), Parser.CRLF); } } catch (Exception ex) { System.debug(LoggingLevel.ERROR, ex.getMessage() + ' :: ' + ex.getStackTraceString()); System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch start - end no attachment'); messages.add(String.format('Error while parsing Enquix Import: {0}. Error details: {1}. Stack Trace: {2}', new List<String> { currentRecord.Id, ex.getMessage(), ex.getStackTraceString() })) ; return new List<String>(); } } global void execute(Database.BatchableContext info, List<String> scope) { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch execute - start'); System.debug(LoggingLevel.DEBUG, 'scope.size(): ' + scope.size()); //first create new csv from the scope lines String importFile = ''; for (String row : scope) { importFile += row + Parser.CRLF; } List<List<String>> parsedData = new List<List<String>>(); try { parsedData = CSVReader.readCSVFile(importFile); } catch (Exception ex) { messages.add(String.format('Error while parsing Enquix Import: {0}. Error details: {1}', new List<String> { currentRecord.Id, ex.getStackTraceString() })); System.debug(LoggingLevel.ERROR, ex.getMessage() + '\n' + ex.getStackTraceString()); return; } System.debug(LoggingLevel.DEBUG, 'parsedData.size(): ' + parsedData.size()); //then process header if needed System.debug(LoggingLevel.DEBUG, 'headerProcessed: ' + headerProcessed); if (!headerProcessed) { headerIndexes = EquixImportManager.processHeader(parsedData[0]); headerProcessed = true; parsedData.remove(0); } List<Account> accounts = new List<Account>(); Set<String> accountsEnqixIdSet = new Set<String>(); for (List<String> csvLine : parsedData) { try{ if (!accountsEnqixIdSet.contains(csvLine.get(headerIndexes.get(EnquixImportMappingsManager.PARENT_ID_LOCATION_MAPPING)))) { accounts.add(AccountManager.createAccountRecordFromCSVLine( csvLine , EquixImportManager.getImportMappingMap().get( EquixImportManager.IMPORT_TYPE_ACCOUNT).get( EnquixImportMappingsManager.ACCOUNT_RECORD_GROUP) , headerIndexes )); accountsEnqixIdSet.add(csvLine.get(headerIndexes.get(EnquixImportMappingsManager.PARENT_ID_LOCATION_MAPPING))); } } catch(Exception ex) { messages.add('The following error has occurred.\n' + ex.getStackTraceString() + ': ' + ex.getMessage() + '. Row causing the error:' + String.join(csvLine, ',')); System.debug('The following error has occurred.'); System.debug(ex.getStackTraceString() + ': ' + ex.getMessage()); System.debug('Row causing the error:' + String.join(csvLine, ',')); } } System.debug(LoggingLevel.DEBUG, 'accounts.size(): ' + accounts.size()); Database.UpsertResult[] saveResults = Database.upsert(accounts, Account.Enqix_ID__c, false); Integer listIndex = 0; // We start at 2 because the CSV data starts in row 2 for (Database.UpsertResult sr : saveResults) { if (!sr.isSuccess()) { for (Database.Error err : sr.getErrors()) { messages.add('The following error has occurred.\n' + err.getStatusCode() + ': ' + err.getMessage() + '. Account fields that affected this error:\n ' + err.getFields() + '\NRow index : ' + listIndex+2); System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Account fields that affected this error: ' + err.getFields()); System.debug('The error was caused by the sobject at index: ' + listIndex); System.debug(accounts.get(listIndex)); } } listIndex++; } List<Account> locations = new List<Account>(); for (List<String> csvLine : parsedData) { locations.add(AccountManager.createLocationRecordFromCSVLine( csvLine , EquixImportManager.getImportMappingMap().get( EquixImportManager.IMPORT_TYPE_ACCOUNT).get( EnquixImportMappingsManager.LOCATION_RECORD_GROUP) , headerIndexes )); } System.debug(LoggingLevel.DEBUG, 'locations.size(): ' + locations.size()); saveResults = Database.upsert(locations, Account.Enqix_Location_ID__c, false); listIndex = 0; // We start at 2 because the CSV data starts in row 2 for (Database.UpsertResult sr : saveResults) { if (!sr.isSuccess()) { for (Database.Error err : sr.getErrors()) { messages.add('The following error has occurred.\n' + err.getStatusCode() + ': ' + err.getMessage() + '. Account fields that affected this error:\n ' + err.getFields() + '\NRow index : ' + listIndex+2); System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Account fields that affected this error: ' + err.getFields()); System.debug('The error was caused by the sobject at index: ' + listIndex); System.debug(locations.get(listIndex)); } } listIndex++; } System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch execute - end'); } global void finish(Database.BatchableContext info) { if (currentRecord != null) { messages.add('Processing completed'); currentRecord.Log__c = String.join(messages, '\n'); if(currentRecord.Log__c.length() > EquixImportManager.getLogFieldLength()) { currentRecord.Log__c = currentRecord.Log__c.abbreviate(EquixImportManager.getLogFieldLength()); } if(currentRecord.Log__c.contains('error')) { currentRecord.Status__c = EquixImportManager.STATUS_ERROR; } else { currentRecord.Status__c = EquixImportManager.STATUS_COMPLETED; } update currentRecord; } if (!Test.isRunningTest()) { if (EquixImportManager.getPendingEnqixImports(EquixImportManager.IMPORT_TYPE_ACCOUNT).size() > 0) { EnquixAccountImportBatch.batchMe(); } else { EnquixOrderImportBatch.batchMe(); } } } public static Boolean batchMe() { System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch batchMe - start'); Id jobId; if (!BatchUtility.accountBatchInstanceRunning()) { System.debug(LoggingLevel.DEBUG, 'Account_Batch_Size__c: ' + Integer.valueOf(EnqixImportCSVParametersManager.getCsvParameters().Account_Batch_Size__c)); jobId = Database.executeBatch(new EnquixAccountImportBatch(), Integer.valueOf(EnqixImportCSVParametersManager.getCsvParameters().Account_Batch_Size__c)); } System.debug(LoggingLevel.DEBUG, 'EnquixAccountImportBatch batchMe - end'); return jobId != null; }
- Ben Allington 7
- November 14, 2016
- Like
- 0
unable to delete/edit a post posted to discussion forum
hi all,
I urgently need to edit/delete a post made by me on this discussion forum...But its not allowing me to do so and pops up
saying that 'you cant delete this question as others are interested in it'.
There are no likes and no comments on it still i am unable to delete it
Any help would be highly appreciated
Its very urgent,
Thanks,
I urgently need to edit/delete a post made by me on this discussion forum...But its not allowing me to do so and pops up
saying that 'you cant delete this question as others are interested in it'.
There are no likes and no comments on it still i am unable to delete it
Any help would be highly appreciated
Its very urgent,
Thanks,
- SFDC coder
- August 14, 2014
- Like
- 0