• Ben Allington 7
  • NEWBIE
  • 20 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 9
    Questions
  • 5
    Replies

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:
User-added image

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;
}

 

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');
	}
}

 
I have developed a test class which automatically converts opportunity products to assets taking dependant values as seen 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(); 
	}
}

 
I have developed a test class which automatically converts opportunity products to assets taking dependant values as seen 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(); 
	}
}

 
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
 
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')];
}



}


 
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
 
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);
        
    }

 
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
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;    
                                             }   
                   }  
                   
        }
}

 
The system currently takes a csv file to be uploaded and populates the fields, after adding our partnership lookup field object below:

Partnership__c
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;
    }

 
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
<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();
    
    }
    })

 

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:
User-added image

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;
}

 

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');
	}
}

 
The system currently takes a csv file to be uploaded and populates the fields, after adding our partnership lookup field object below:

Partnership__c
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;
    }

 
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,