• John Neilan 18
  • NEWBIE
  • 70 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 16
    Questions
  • 18
    Replies
I am trying to figure out a way that I can look at the value of a text field and check it to see if any part of the text contains values that are entries in a Custom Setting. I tried the following to set up my Custom Setting list of words:  
List<Keywords__c> listKeywords = [SELECT Name FROM Keywords__c];
 
Set<String> kw = new Set<String>;
Then within a loop of my custom object, I am trying to check if any part of the text field is one of the words in the list above:

   
for(Object__c = object:Trigger.new){
    IF(kw.contains(object.Notes__c){
        object.Impact__c = TRUE;
    }else{
        object.Impact__c = FALSE;
    }
}

The problem with this is that it checks the entire value of the Notes__c field against the list and does not just look for any part of Notes__c that is contained in the list.  For example, if "Test" is in my custom setting, the code above works if the Notes__c field is "Test" but it does not work if the Notes__c field is "Test Test". Can anyone help with the proper code to get this to work?
I have 2 batch Apex classes that update Account fields from different custom objects. I was running into issues of accessing records and found a way to run the batches in order. The test class for my 1st batch runs and covers my classes.  When I run the 2nd test class, I get the following error & Stack Trace:

   
System.StringException: Only CronTrigger IDs and batch, future, and queueable job IDs are supported.
    
    Class.AccountTotalReferralsBatch.finish: line 23, column 1

Can anyone help me resolve this error?

Batch Class:

   
public class AccountTotalReferralsBatch implements Database.Batchable<sObject> {
        public Database.QueryLocator start(Database.BatchableContext context) {
            return Database.getQueryLocator([SELECT Id FROM Account]);
        }
        public void execute(Database.batchableContext context, Account[] scope) {
            Map<Id, AggregateResult> results = new Map<Id, AggregateResult>([
                SELECT Account__c Id, COUNT(Id) amt
                FROM Referral__c
                WHERE Account__c = :scope AND Age__c<366 GROUP BY Account__c]);
                
            for(Account record: scope) {
                AggregateResult amount = results.get(record.Id);
                if(amount != null) {
                    record.Referrals__c = (Decimal)amount.get('amt');
                } else {
                    record.Referrals__c = null;
                }
            }
            update scope;
        }
        public void finish(Database.BatchableContext bc) {
            BatchSchedule__c b = BatchSchedule__c.getOrgDefaults();
                System.abortJob(b.Scheduled_Id__c);
        }         
    }

Scheduler Class:

   
global class AccountTotalReferralsSchedule implements Schedulable{
        global void execute(SchedulableContext sc){
            AccountTotalReferralsBatch ref = new AccountTotalReferralsBatch();
            database.executebatch(ref,200);
        }
    }

Test Class:
@istest (SeeAllData=FALSE)
    public class AccountTotalReferralsTest{
        
        public static testmethod void testBatch1() {
            Test.startTest();
            
            Account account = TestUtility.createAccount('Prospect', Constants.RECORDTYPEID_ACCOUNT_FAMILY);
            insert account;
            
            Contact contact = TestUtility.createContact(account.Id, Constants.RECORDTYPEID_CONTACT_FAMILY, 'Primary');
            insert contact;
            
            Encounters__c encounter = TestUtility.createEncounter(account.Id, contact.Id, '', '');
            insert encounter;
            
            BatchSchedule__c batchSchedEnc = new BatchSchedule__c();
            insert batchSchedEnc;
            
    AccountTotalReferralsBatch();
    
                string chron = '0 0 23 * * ?';
                string jobid = System.schedule('testScheduledApex', chron, new AccountTotalEncountersSchedule());
                CronTrigger ct = [Select id , CronExpression from CronTrigger where id = :jobId];
    
            Referral__c testRef = new Referral__c();
            testRef.Name = 'Test';
            testRef.Account__c = account.Id;
            insert testRef;
    
            batchSchedEnc = [SELECT Id,Scheduled_Id__c FROM BatchSchedule__c WHERE ID =: batchSchedEnc.Id];
                batchSchedEnc.Scheduled_Id__c = ct.Id;
            
            AccountTotalReferralsBatch testBatch = new AccountTotalReferralsBatch();
            
            Database.executebatch(testBatch);        
            Test.stopTest();
        }
    }


   
Hi,

I have a lookup (Contact) field on the Account object. When a Contact is entered in this field, the trigger helper class below is meant to increment a field on the Contact (Referrals__c) by 1. It then also increments the Contact's associated Account field Referrals__c) by 1.  I don't think it is written in a way that is efficient. Is there a better way to accomplish this?
 
public class AccountUtility {
    public static void updateContactAccountReferredBy(List<Account> newAccountList){
        
		List<Contact> listContact = new List<Contact>();
        
        id oldReferredBy;

        for(Account account : newAccountList){
            Account oldAccount = (Account)Trigger.oldMap.get(account.Id);
            oldReferredBy = oldAccount.Referred_by__c;
            
            if(account.Referred_By__c != null && account.Referred_By__c != oldAccount.Referred_By__c){
                listContact = [SELECT Id,AccountId,Referrals__c
                               FROM Contact
                               WHERE Id =: account.Referred_By__c];
                for(Contact addReferral :listContact){
                    addReferral.Referrals__c += 1;
                    Account account2 = [SELECT Id, Referrals__c
                                      FROM Account
                                      WHERE Id =: addReferral.Id];
                    List<Contact> listContacts = [SELECT Id, Referrals__c
                                                 FROM Contact
                                                 WHERE AccountId =: account2.Id];
                    for(Contact contact2 :listContacts){
                        account2.Referrals__c += contact2.Referrals__c;
                    }
                    update account2;
                }
            update listContact;
            }
}

 
Hi,

I am struggling on how to cover lines 46 - 48 in my Test Class below.  Am I missing something in my test class? I don't get an error, the lines jsut aren't covered.

Test Class
 
@isTest 
private class Test_NewRecController {

    static testMethod void testMethod1()
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
		PageReference pageRef = Page.NewRecType;
            pageRef.getParameters().put('contId','testContact.Id');
            pageRef.getParameters().put('acctId','testAccount.Id');

	Test.StartTest();
        
        NewRecController testNewRec2 = new NewRecController();
	        testNewRec2.addRecType();

        NewRecController testNewRec3 = new NewRecController();
        	Pagereference pageRef1 = Page.NewRecType;
                pageRef1.getParameters().put('rec','0');
        		Test.setCurrentPage(pageRef1);
	        testNewRec3.removeType();

	Test.StopTest();
    }

    static testMethod void testMethod2()
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
        Rec_Type__c testRec1 = new Rec_Type__c();
            testRec1.Account__c = testAccount.Id;
            testRec1.Contact__c = testContact.Id;
            testRec1.Rec_Type__c = 'Celebrity';
        insert testRec1;

	Test.StartTest();

        NewRecController testNewRec = new NewRecController();

        PageReference pageRef = Page.NewRecType;

	            pageRef.getParameters().put('contId','testContact.Id');
    	        pageRef.getParameters().put('acctId','testAccount.Id');
    	        pageRef.getParameters().put('Rec_Type__C','Celebrity');

        	Test.setCurrentPage(pageRef);

        testNewRec.saveType();
//        System.assertNotEquals(null,testNewRec.saveType());
        
	Test.StopTest();
    }
}

VF Controller
public class NewRecController {

    Rec_Type__c rec1 = new Rec_Type__c();
    public list<Rec_Type__c> listRecType{ get; set; }

    Id acctId;
    Id contId;
    Public Integer rec {get; set;}
    Public List<Rec_Type__c> ContRecList {get; set;}
    
//    Constructor 

	public NewRecController() { 
        acctId = ApexPages.currentPage().getParameters().get('acctId');
        contId = ApexPages.currentPage().getParameters().get('contId');
        
        vip.Account__c = acctId;
        vip.Contact__c = contId;
        
        ContRecList = [SELECT Rec_Type__c
                      FROM Rec_Type__c
                      WHERE Contact__c =: contId];
system.debug('@@@@@@ - ContactTypes: '+ContVIPList);

        listRecType = new list<Rec_Type__c>();
        listRecType.add(rec1);
	} 

    Public void addRecType() {
        Rec_Type__c rec1a = new Rec_Type__c();
    		rec1a.Contact__c = contId;
        	rec1a.Account__c = acctId;
		listRecType.add(rec1a);
system.debug('@@@### - listVIPType: '+listVIPType);
        }

	public PageReference RemoveType() {
    	rec = Integer.valueOf(ApexPages.currentPage().getParameters().get('rec'));
        listRecType.remove(rec);
        return null;
    }
     
    public PageReference saveType() {
    	try {
        	insert listRecType;
        		PageReference contRecord = new PageReference('/'+contId);
       			contRecord.setRedirect(true);
    	return contRecord;
    	} catch(DmlException e) {
        	ApexPages.addMessages(e);
        return null;
    	}
    }
}

 
Hi,

I have a VF page that allows a user to dynamically add and remove rows before saving each row as a new custom object record.  I am trying to put together a test class to cover the removal part of my controller, but I can't seem to get any values through to the test as I am getting an error:
 
System.NullPointerException: Argument cannot be null.

Class.NewRecController.RemoveType: line 24, column 1
Class.Test_NewRecController.testMethod1: line 27, column 1

What am I missing?

Controller
public class NewRecController {

    Rec_Type__c rec = new Rec_Type__c();
    public list<Rec_Type__c> listRecType{ get; set; }

    Id acctId;
    Id contId;
    Public Integer rec {get; set;}
    
//    Constructor 

	public NewRecController() { 
        acctId = ApexPages.currentPage().getParameters().get('acctId');
        contId = ApexPages.currentPage().getParameters().get('contId');
        
        rec.Account__c = acctId;
        rec.Contact__c = contId;
        
        listRecType = new list<Rec_Type__c>();
        listRecType.add(rec);
	} 


	public PageReference RemoveType() {
    	rec = Integer.valueOf(ApexPages.currentPage().getParameters().get('rec'));
        listRecType.remove(rec);
        return null;
    }
     
    public PageReference saveType() {
    	try {
        	insert listRecType;
    	} catch(DmlException e) {
        	ApexPages.addMessages(e);
        return null;
    	}
        PageReference contRecord = new PageReference('/'+contId);
        contRecord.setRedirect(true);
    return contRecord;
    }
}

Test Class
@isTest 
private class Test_NewRecController {

    static testMethod void testMethod1() 
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
	Test.StartTest();
        PageReference pageRef = Page.NewRecType;
        	pageRef.getParameters().put('contId','testContact.Id');
        	pageRef.getParameters().put('acctId','testAccount.Id');
        	pageRef.getParameters().put('Rec_Type__c','Type 2');
        
        NewRecController testNewRec = new NewRecController();
        	testNewRec.rec = 1;
        
        testNewRec.RemoveType();
        testNewRec.saveType();

	Test.StopTest();
    }
}

​​​​​​​
Hi,

I have a VF page with a custom controller that allows a user to enter multiple records for a custom object using a Type picklist field. I also have a trigger that populates those values to the parent record (Contact) and only allows 1 of each Type for the child records. If there are duplicates, an error message is thrown.

Currently, the error message shows as an non user-friendly messge on the page:
 
Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, This Type already exists for this Contact: []
Error is in expression '{!saveType}' in component <apex:commandButton> in page newrectype: Class.NewRecController.saveType: line 46, column 1

An unexpected error has occurred. Your development organization has been notified.

What can I do to get this message to show on the VF page at the top as a simple message like "This Type already Exists"?

My Save method is below and I do have <apex:pageMessages> in my VF page.
 
public PageReference saveType() {
    	insert listRecType;
        PageReference contRecord = new PageReference('/'+contId);
        contRecord.setRedirect(true);
    return contRecord;
    }

 
Hi,

I have a pretty simple VF page that allows a user to create 1 or more records of a custom object that has master-detail relationships to the Account and Contact objects. The user can enter a Type value for the custom object, but each related Contact can only have 1 record of each Type value. Type values on the custom object can be repeated on different Contacts.  

What I'm trying to do is highlight the Type values the user is choosing to create, that already exist for that Contact so they can then change the value or remove it. Is there a way to accomplish this?

VF Page
<apex:page Controller="NewRecController">
<apex:form >
    <apex:pageBlock >
        <apex:pageMessages id="showMsg"/>
        <apex:pageBlockTable value="{!listRecType}" var="rec1" >
            <apex:column headerValue="Record Type">
                <apex:inputField value="{!rec1.Rec_Type__c}"/>
            </apex:column>
        </apex:pageBlockTable>
        <apex:pageBlockButtons >
            <apex:commandButton value="Add Another Record Type" action="{!addRecType}"/>
            <apex:commandButton value="Save All Record Types" action="{!saveType}" reRender="showMsg"/>
        </apex:pageBlockButtons>
        </apex:pageBlock>
</apex:form>
</apex:page>

Controller
public class NewRecController {

    Record_Type__c rec = new Record_Type__c();
    public list<Record_Type__c> listRecType{ get; set; }

    Id acctId;
    Id contId;
    String RecTypes;
    
//    Constructor 

	public NewRecController() { 
        acctId = ApexPages.currentPage().getParameters().get('acctId');
        contId = ApexPages.currentPage().getParameters().get('contId');
        RecTypes = ApexPages.currentPage().getParameters().get('acctTypes');
        
        rec.Account__c = acctId;
        rec.Contact__c = contId;
system.debug('@@@@@@ - AccountTypes: '+acctTypes);

        listRecType = new list<Record_Type__c>();
        listRecType.add(rec);
	} 

    Public void addRecType() {
        Record_Type__c rec1 = new Record_Type__c();
    		rec1.Contact__c = contId;
        	rec1.Account__c = acctId;
system.debug('@@@@@@ - AccountTypes: '+acctTypes);
system.debug('@@@@@@ - Record Type: '+rec1);
		listRecType.add(rec1);
        }
            
    public PageReference saveType() {
    	insert listRecType;
    return Page.NewRecType;
    }
}


 
Hi,

I have a simple Visualforce page with 3 fields that launches from a controller method related to another VF page. The page loads properly using the controller below, but I am trying to pre-populate the Contact and Account records that are the master part of the custom object master-detail relationship. Can anyone advise how I can do this?
 
public class NewObjController {

    Engage__c eng = new Engage__c();
    public list<Engage__c> listEngage{ get; set; }
 
    public NewObjController() {
        listEngage=new list<Engage__c>();
        listEngage.add(eng);
        }
 
    Public void addEngage() {
        Engage__c eng1 = new Engage__c();
            listEngage.add(eng1);
            }
            
    public PageReference saveEngage() {
        for(Integer i=1; i<listEngage.size(); i++) {
    insert listEngage;
    }
    }
}

 
Hello,

I am trying to create a test class for a relatively simple custom controller extension.  However, I am having trouble covering one of my methods in the controller that handled deletion of records.

I need to somehow pass a value for the DelAddrId variable in my controller from my test class, but I'm not sure how to do that. Can anyone assist?

Test Class
@isTest 
private class Test_AcctAddressesController {

    static testMethod void testMethod1() 
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
	Test.StartTest();
        Account_Addresses__c testAcctAddr = new Account_Addresses__c();
            testAcctAddr.Account__c = testAccount.Id;
            testAcctAddr.Street__c = '1010 Test Ave';
            testAcctAddr.City__c = 'New York';
            testAcctAddr.State__c = 'NY';
            testAcctAddr.Zip_Postal_Code__c = '11212';
            testAcctAddr.Country__c = 'USA';
            testAcctAddr.Primary__c = TRUE;
            testAcctAddr.Current__c = TRUE;
        insert testAcctAddr;

        PageReference testPage = Page.Acct_Addresses;
			testPage.getParameters().put('DelAddrId', testAcctAddr.Id);   
   		Test.setCurrentPage(testPage);

        ApexPages.StandardController AcctAdd = new ApexPages.standardController(testAccount);
        	AcctAddresses AcctAdd1 = new AcctAddresses(AcctAdd);
System.assertNotEquals(null,AcctAdd1.deleteAddress());

        AcctAdd1.save();
        AcctAdd1.deleteAddress();
	Test.StopTest();
    }
}

Controller
public class AcctAddresses {     

    public List<Account_Addresses__c> addresses{get;set;}
    public string DelAddrId { get; set;}
    public Account accounts {get;set;} 
    public Account acct {get;set;} 

//Constructor 

    public AcctAddresses(ApexPages.StandardController controller) { 

        acct = (account)controller.getRecord();      

        accounts = [SELECT Id
                    FROM account
                    WHERE id=: acct.id LIMIT 1]; 

        addresses = [SELECT Id, Name, Primary__c, Current__c, Street__c, City__c, State__c, Zip_Postal_Code__c, Country__c, Account__c
                    FROM Account_Addresses__c
                    WHERE Account__r.Id = :accounts.id ORDER BY Primary__c, State__c];     
} 

//This method is to edit the existing contact record while clicking the Edit link 

        public pageReference Save(){
            update addresses;
        return ApexPages.CurrentPage();
        }

//This method is to delete the contact record while clicking the Del link 

    public pageReference deleteAddress(){

        Account_addresses__c ToBeDeleted = [SELECT Id FROM Account_addresses__c WHERE id = : DelAddrId LIMIT 1]; 
	        delete ToBeDeleted; 
    		    String baseUrl = URL.getSalesforceBaseUrl().toExternalForm(); 
        		PageReference redirectPage = new PageReference(baseUrl+'/'+acct.id); 
        	return redirectPage;  
    }   
}

 
I am trying to develop a test class to cover a trigger but I am only able to get to 64%. I'm not sure how to get the lines below covered. Can anyone advise?

Test Class:
Not covered - lines 13-16; lines 36-41; lines 47-56
@isTest
private class TestVIP_Types_Trigger {
    
    Private static testMethod void vipScenarioTests() {
        
Test.startTest();
        
        Account testAccount = new Account();
        	testAccount.Name = 'Test JN Account';
            testAccount.AccountSource = 'Networking';
		insert testAccount;
        
        Contact testContact = new Contact();
            testContact.LastName = 'LastTest';
            testContact.Phone = '5555555555';
            testContact.AccountId = testAccount.Id;
        insert testContact;

        Contact testContact2 = new Contact();
            testContact2.LastName = 'LastTest';
            testContact2.Phone = '5555555555';
            testContact2.AccountId = testAccount.Id;
        insert testContact2;
        
    	VIP_Type__c testVIP1 = new VIP_Type__c();
            testVIP1.Account__c = testAccount.Id;
            testVIP1.Contact__c = testContact.Id;
            testVIP1.VIP_Type__c = 'Ambassador';
        insert testVIP1;

        VIP_Type__c testVIP2 = new VIP_Type__c();
            testVIP2.Account__c = testAccount.Id;
            testVIP2.Contact__c = testContact.Id;
            testVIP2.VIP_Type__c = 'Influencer';
        insert testVIP2;

        Boolean errThrown = false;
        try{
        VIP_Type__c testVIP3 = new VIP_Type__c();
            testVIP3.Account__c = testAccount.Id;
            testVIP3.Contact__c = testContact.Id;
            testVIP3.VIP_Type__c = 'Ambassador';
        insert testVIP3;
        }catch(Exception e) {
            errThrown = true;
				Boolean expErr = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr, e.getMessage());
        }
        System.assertEquals(false,errThrown,'No exception was thrown');
        

        Boolean errThrown2 = false;
        try{
        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Ambassador';
        update testVIP2;
        }catch(Exception e) {
            errThrown2 = true;
				Boolean expErr2 = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr2, e.getMessage());
        }
        System.assertEquals(false,errThrown2,'No exception was thrown');

        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Celebrity';
        update testVIP2;

        VIP_Type__c testVIP1a = new VIP_Type__c();
            testVIP1a.Account__c = testAccount.Id;
            testVIP1a.Contact__c = testContact2.Id;
            testVIP1a.VIP_Type__c = 'Ambassador';
        insert testVIP1a;

        VIP_Type__c testVIP2a = new VIP_Type__c();
            testVIP2a.Account__c = testAccount.Id;
            testVIP2a.Contact__c = testContact2.Id;
            testVIP2a.VIP_Type__c = 'Celebrity';
        insert testVIP2a;

        delete testVIP1;
        delete testContact;
        delete testAccount;
Test.stopTest();
    }
}



Trigger:
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

 if(checkRecursive.runOnce())
    {
	Set<Id> acctIds = new Set<ID>();
	Set<Id> contIds = new Set<ID>();
//	  Set<String> vipTypes = new Set<String>();
	Map<VIP_Type__c, VIP_Type__c> contactTypeMap = new Map<VIP_Type__c, VIP_Type__c>();
	Map<Id, Set<String>> contactTypeMapDel = new Map<Id, Set<String>>();
    
// Get all the Account & Contact Ids in the Set 
	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);
            contactTypeMapDel.put(vip.Contact__c , new set<String>());
//            contactTypeMap.put(vip.Contact__c, vip.VIP_Type__c);
		}
	}
	else{

    	for(VIP_Type__c vip : Trigger.new) {
    		acctIds.add(vip.Account__c);
    		contIds.add(vip.Contact__c);
     	}
//	 }

	List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                            FROM VIP_Type__c
                            WHERE Contact__c = :contIds AND ID NOT IN:trigger.new];

//Check for VIP Types already entered for Contact
	Map<Id,set<string>> existingTypeMap = new Map<Id,set<string>>();
    
    for(VIP_Type__c vip: vipRecs) {
		set<string> existingTypes = new set<string>();
        if(existingTypeMap.containsKey(vip.Contact__c)){
            existingTypes = existingTypeMap.get(vip.Contact__c);
        }
        existingTypes.add(vip.VIP_Type__c);
        existingTypeMap.put(vip.Contact__c,existingTypes);
    }

	for (VIP_Type__c vip : trigger.new)
    {
        if (existingTypeMap.containsKey(vip.Contact__c)){
            if (existingTypeMap.get(vip.contact__c).contains(vip.VIP_Type__c)){
system.debug('@@@### - Check Map:  '+existingTypeMap.get(vip.contact__c));
system.debug('@@@### - Check VIP Type:  '+vip.VIP_Type__c);
                trigger.newMap.get(vip.Id).addError('This Type already exists for this Contact');
            }
            else
            {
                Set<string> existingTypes = existingTypeMap.get(vip.Contact__c);
                existingTypes.add(vip.VIP_Type__c);
                existingTypeMap.put(vip.Contact__c,existingTypes);
            }

        }
    } 
    }


// Query the Accounts
		List<Account> acct = new List<Account>();

// Use the VIP Types to get all the related Types for the Account 
			acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r ORDER BY VIP_Type__c) 
					FROM Account 
					WHERE Id in :acctIds]; 

// Iterate over each Account and VIP record 
			for(Account a : acct){ 
				a.VIP_Types__c = ''; 

				for(VIP_Type__c vip: a.VIP_Types__r){ 

					if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == ''){ // Check if the Type is already in the Account Field. if not add it otherwise skip 

					a.VIP_Types__c += vip.VIP_Type__c + '; '; 
					} 
				} 
			} 
// Update the Account 
		update acct; 
}
}

 
Hello,

I have a custom object called Account_Addresses__c that has a master-detail relationship to the Account object. That object houses address information as each account may have multiple addresses, however, only one of those addresses can be marked "current". I have a field on the custom object called Current__c to capture which address is current.

I created a trigger (below) to mark and unmark the addresses whena user changes the Current__c field and I am trying (in the same trigger) to then update a checkbox field on the Account record (Left_CA__c) if the newly selected current address is not in California and the Left_CA__c field on the Account was not already checked off.  However, this part of my trigger does not seem to be firing properly. From the logs, it looks like my Account map is initially null but then somehow gets populated. What am I doing wrong?

DEBUG|@@@### - parentAcct Map: {}
AcctAddrPrimCurr on Account_Addresses trigger event AfterUpdate|__sfdc_trigger/AcctAddrPrimCurr 0
DEBUG|@@@### - parentAcct Map: {0011h00000lC9vvAAC=Account:{Id=0011h00000lC9vvAAC, Left_NY__c=false}}
 
trigger AcctCurr on Account_Addresses__c(after update,after insert) {


//Update Account Address for Current
    List<Account_Addresses__c> acctAddr2 = new List<Account_Addresses__c>();

// Sets holding Account IDs (unique) and Addresses IDs (unique)
	Set<Id> CurrAcctIds = new Set<Id>();
	Set<Id> acctAddrIds2 = new Set<Id>();

    for(Account_Addresses__c aa2 : trigger.new){
       if(aa2.Current__c == TRUE){
            CurrAcctIds.add(aa2.Account__c);
			acctAddrIds2.add(aa2.id);
        }
    }

// get the records from Account Addresses that are under the Account but not meant to be Current

    acctAddr2 = [SELECT Id,Current__c
                FROM Account_Addresses__c
                WHERE Current__c = TRUE AND Account__c IN:CurrAcctIds AND Id NOT IN:acctAddrIds2];
	for(Account_Addresses__c aa2:acctAddr2)
		aa2.Current__c = FALSE;
    update acctAddr2;

//update related Account to check if new current address is not CA
	Map<ID, Account> parentAcct = new Map<ID, Account>();

    parentAcct = new Map<Id, Account>([SELECT Id, Left_CA__c, Date_Left_CA__c 
                                       FROM Account 
                                       WHERE Id IN :CurrAcctIds AND Left_CA__c != TRUE]);
system.debug('@@@### - parentAcct Map:  '+parentAcct);
    if(parentAcct != null){
    
	for(Account_Addresses__c ca: trigger.new){
    	Account myParentAcct = parentAcct.get(ca.Account__c);
        if(ca.Current__c == TRUE && ca.State__c != 'CA'){
            myParentAcct.Left_CA__C = TRUE;
            myParentAcct.Date_Left_CA__C = system.TODAY();
        }
    }
}
}

 
Hello,

I have a trigger where the 1st part is desiged to loop through custom object records of a Contact and prevent users from entering duplicate records for each account.  I have a statement that checks a map against the record being inserted/changed. When I look at my logs, I see that the IF statement returns a FALSE result, so the trigger should move on, but it is still throwing the addError message.  Does anyone know why this might be hapening?  The line is question is Line 48 below.
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

Set<Id> acctIds = new Set<ID>();
Set<Id> contIds = new Set<ID>();
Set<String> vipTypes = new Set<String>();
    
Map<VIP_Type__c, VIP_Type__c> contactTypeMap = new Map<VIP_Type__c, VIP_Type__c>();
// Get all the Account & Contact Ids in the Set 

	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);
		    VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
		}
	}
	else{

    for(VIP_Type__c vip : Trigger.new) {
    	acctIds.add(vip.Account__c);
    	contIds.add(vip.Contact__c);
        vipTypes.add(vip.VIP_Type__c);
    	VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
system.debug('@@@### - Key Check:  '+key);
system.debug('@@@### - vip Check:  '+vip);
system.debug('@@@### - 1st Map Check:  '+contactTypeMap.put( key, vip ));
system.debug('@@@### - 2nd Map Check:  '+contactTypeMap.get( key ));
system.debug('@@@### - 2nd Map Check:  '+contactTypeMap);

	        if(contactTypeMap.put( key, vip ) != null) {
	       		contactTypeMap.get( key ).addError( 'This type already exits for this Contact' );
    		}
     }
	 }

List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                            FROM VIP_Type__c
                            WHERE Contact__c = :contIds AND Account__c = :acctIds AND ID NOT IN:trigger.new];

//Check for VIP Types already entered for Contact
for(VIP_Type__c vip: vipRecs) {
system.debug('@@@### - Check for Types:  '+vipRecs);
    VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
system.debug('@@@### - Check for Types-key:  '+key);
system.debug('@@@### - Check contactTypeMap:  '+contactTypeMap);
system.debug('@@@### - Check contactTypeMap (key):  '+contactTypeMap.containsKey(key));

    if(contactTypeMap.containsKey(key)) {
        contactTypeMap.get(key).addError('This Type already exists for this Contact');
    }
}
    

// Query the Accounts
		List<Account> acct = new List<Account>();

// Use the VIP Types to get all the related Types for the Account 
			acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r) 
					FROM Account 
					WHERE Id in :acctIds]; 

// Iterate over each Account and VIP record 
			for(Account a : acct){ 
				a.VIP_Types__c = ''; 

				for(VIP_Type__c vip: a.VIP_Types__r){ 

					if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == ''){ // Check if the Type is already in the Account Field. if not add it otherwise skip 

					a.VIP_Types__c += vip.VIP_Type__c + '; '; 
					} 
				} 
			} 
// Update the Account 
		update acct; 
}

 
Hello,

I have a trigger that is checking a picklist field on a custom object (VIP_Type__c) to make sure duplicate records are not allowed under the parent object (Contact).  I am getting an Apex error message related to the error message line in my trigger. Can anyone help me understand why?
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

	Set<Id> acctIds = new Set<ID>();
	Set<Id> contIds = new Set<ID>();

	map<Id, set<String>> contact_type_map = new map<Id, set<String>>();

// Get all the Account & Contact Ids in the Set 
	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);

			contact_type_map.put(vip.Contact__c , new set<String>());
		}
	}
	else{
        for(VIP_Type__c vip : Trigger.new){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);

            contact_type_map.put(vip.Contact__c, new set<String>{vip.VIP_Type__c});
System.Debug('@@@###-contact_Type_Map: '+contact_Type_Map);
	}
    }
		List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                                    FROM VIP_Type__c
                                    WHERE Contact__c in:contIds];


//Check for VIP Types already entered for Contact
    for(VIP_Type__c objVIP: vipRecs){
		if(contact_type_map.get(objVIP.Contact__c).contains(objVIP.VIP_Type__c)){
system.debug('@@@### - Error message:  '+objVIP.VIP_Type__c);
                trigger.newMap.get(objVIP.Id).addError('This Type already exists for this Contact');
system.debug('@@@### - Error message:  '+trigger.newMap.get(objVIP.Id));
        }
        else{
            contact_type_map.get(objVIP.Contact__c).add(objVIP.VIP_Type__c);
        }
    }

 
Hi,

I have a pretty basic question (I think) about the use of a Set within a map.  I have a trigger with a piece of code:
 
map<Id, set<String>> newMap = new map<Id, set<String>>();

For(Custom_Object__c cust : Trigger.new){
newMap.put(cust.Contact__c, new set<String>());
}

I am trying to create a keyset of Contact ID & Type on a custom object so I can compare to ensure Contact records only allow 1 Type of each related custom object record.  When I run the Debug statements, the map is only populating the Contact ID.  I have 2 questions:

What are the set<string> in my map and new set<string> in my put statement designed to do, and how do I get the set<string> to populate?
I have a trigger that is designed to write unique values of a Picklist from a child object (VIP_Type__c) to the associated Account record. I am having trouble figuring out how to convert the picklist value to a string value to check if the Account field contains the picklist value. The line of code I have is:
if(!a.VIP_Types__r.contains(vip.VIP_Type__c))

Where vip.VIP_Type__c is the picklist field and VIP_Types__r is the text field on the Account.  I am getting an error:

"Method does not exist or incorrect signature: void contains(String) from the type List<VIP_Type__c>"

Any ideas?  My full trigger is below:
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){
        
        Set<Id> acctIds = new Set<ID>();
        
        // Get all the Account Ids in the Set
        for(VIP_Type__c vip : Trigger.new){
            acctIds.add(vip.Account__c);
        }
        // QUery the Accounts
        List<Account> acct = new List<Account>();
        // Use the VIP Types to get all the related Types for the Account
        acct = [SELECT Id, VIP_Types__c
                FROM Account
                WHERE Id in :acctIds];
        
        // Iterate over each Account and VIP record
        for(Account a : acct){
                if(a.Id !=NULL){
                    for(VIP_Type__c vip: a.VIP_Types__r){
                        if(!a.VIP_Types__r.contains(vip.VIP_Type__c)){ // Check if the Type is already in the Account Field. if not add it otherwise skip
                            a.VIP_Types__c += vip.VIP_Type__c + ';';
                        }
                    }
                }
        }
        // Update the Account
        update acct;
    }

 
I have a Visualforce Page that uses the standard Contact controller with a controller extension. The page is embedded on the Contact record layout and displays a related list of a custom object that has a master-detail to the Contact and Account records.

I am trying to create a custom button on the embedded VF page to create a new record that pre-populates the associated Contact and Account (from the Contact) IDs to 2 lookup fields on the custom object record. I am using a CommandButton with !URLFOR($Action attributes to open the new record creation page (in Lightning), however, I cannot figure out how to get the Account pre-populated and then redirect back to the contact record once saved.

The line below opens the pop-up and pre-populated the Contact ID, but I need to select the Account and then it directs to the new record created, not the original Contact record. Is it possible to do what I am trying to do with a CommandButton?
 
<div style="margin-left: 30%;">
<apex:commandButton action="{!URLFOR($Action.Type__c.New)}" value="New Type" oncomplete="window.open('/{ContactId}&retURL=(ContactId}')"/>
</div>
I have 2 batch Apex classes that update Account fields from different custom objects. I was running into issues of accessing records and found a way to run the batches in order. The test class for my 1st batch runs and covers my classes.  When I run the 2nd test class, I get the following error & Stack Trace:

   
System.StringException: Only CronTrigger IDs and batch, future, and queueable job IDs are supported.
    
    Class.AccountTotalReferralsBatch.finish: line 23, column 1

Can anyone help me resolve this error?

Batch Class:

   
public class AccountTotalReferralsBatch implements Database.Batchable<sObject> {
        public Database.QueryLocator start(Database.BatchableContext context) {
            return Database.getQueryLocator([SELECT Id FROM Account]);
        }
        public void execute(Database.batchableContext context, Account[] scope) {
            Map<Id, AggregateResult> results = new Map<Id, AggregateResult>([
                SELECT Account__c Id, COUNT(Id) amt
                FROM Referral__c
                WHERE Account__c = :scope AND Age__c<366 GROUP BY Account__c]);
                
            for(Account record: scope) {
                AggregateResult amount = results.get(record.Id);
                if(amount != null) {
                    record.Referrals__c = (Decimal)amount.get('amt');
                } else {
                    record.Referrals__c = null;
                }
            }
            update scope;
        }
        public void finish(Database.BatchableContext bc) {
            BatchSchedule__c b = BatchSchedule__c.getOrgDefaults();
                System.abortJob(b.Scheduled_Id__c);
        }         
    }

Scheduler Class:

   
global class AccountTotalReferralsSchedule implements Schedulable{
        global void execute(SchedulableContext sc){
            AccountTotalReferralsBatch ref = new AccountTotalReferralsBatch();
            database.executebatch(ref,200);
        }
    }

Test Class:
@istest (SeeAllData=FALSE)
    public class AccountTotalReferralsTest{
        
        public static testmethod void testBatch1() {
            Test.startTest();
            
            Account account = TestUtility.createAccount('Prospect', Constants.RECORDTYPEID_ACCOUNT_FAMILY);
            insert account;
            
            Contact contact = TestUtility.createContact(account.Id, Constants.RECORDTYPEID_CONTACT_FAMILY, 'Primary');
            insert contact;
            
            Encounters__c encounter = TestUtility.createEncounter(account.Id, contact.Id, '', '');
            insert encounter;
            
            BatchSchedule__c batchSchedEnc = new BatchSchedule__c();
            insert batchSchedEnc;
            
    AccountTotalReferralsBatch();
    
                string chron = '0 0 23 * * ?';
                string jobid = System.schedule('testScheduledApex', chron, new AccountTotalEncountersSchedule());
                CronTrigger ct = [Select id , CronExpression from CronTrigger where id = :jobId];
    
            Referral__c testRef = new Referral__c();
            testRef.Name = 'Test';
            testRef.Account__c = account.Id;
            insert testRef;
    
            batchSchedEnc = [SELECT Id,Scheduled_Id__c FROM BatchSchedule__c WHERE ID =: batchSchedEnc.Id];
                batchSchedEnc.Scheduled_Id__c = ct.Id;
            
            AccountTotalReferralsBatch testBatch = new AccountTotalReferralsBatch();
            
            Database.executebatch(testBatch);        
            Test.stopTest();
        }
    }


   
Hi,

I have a VF page that allows a user to dynamically add and remove rows before saving each row as a new custom object record.  I am trying to put together a test class to cover the removal part of my controller, but I can't seem to get any values through to the test as I am getting an error:
 
System.NullPointerException: Argument cannot be null.

Class.NewRecController.RemoveType: line 24, column 1
Class.Test_NewRecController.testMethod1: line 27, column 1

What am I missing?

Controller
public class NewRecController {

    Rec_Type__c rec = new Rec_Type__c();
    public list<Rec_Type__c> listRecType{ get; set; }

    Id acctId;
    Id contId;
    Public Integer rec {get; set;}
    
//    Constructor 

	public NewRecController() { 
        acctId = ApexPages.currentPage().getParameters().get('acctId');
        contId = ApexPages.currentPage().getParameters().get('contId');
        
        rec.Account__c = acctId;
        rec.Contact__c = contId;
        
        listRecType = new list<Rec_Type__c>();
        listRecType.add(rec);
	} 


	public PageReference RemoveType() {
    	rec = Integer.valueOf(ApexPages.currentPage().getParameters().get('rec'));
        listRecType.remove(rec);
        return null;
    }
     
    public PageReference saveType() {
    	try {
        	insert listRecType;
    	} catch(DmlException e) {
        	ApexPages.addMessages(e);
        return null;
    	}
        PageReference contRecord = new PageReference('/'+contId);
        contRecord.setRedirect(true);
    return contRecord;
    }
}

Test Class
@isTest 
private class Test_NewRecController {

    static testMethod void testMethod1() 
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
	Test.StartTest();
        PageReference pageRef = Page.NewRecType;
        	pageRef.getParameters().put('contId','testContact.Id');
        	pageRef.getParameters().put('acctId','testAccount.Id');
        	pageRef.getParameters().put('Rec_Type__c','Type 2');
        
        NewRecController testNewRec = new NewRecController();
        	testNewRec.rec = 1;
        
        testNewRec.RemoveType();
        testNewRec.saveType();

	Test.StopTest();
    }
}

​​​​​​​
Hi,

I have a VF page with a custom controller that allows a user to enter multiple records for a custom object using a Type picklist field. I also have a trigger that populates those values to the parent record (Contact) and only allows 1 of each Type for the child records. If there are duplicates, an error message is thrown.

Currently, the error message shows as an non user-friendly messge on the page:
 
Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, This Type already exists for this Contact: []
Error is in expression '{!saveType}' in component <apex:commandButton> in page newrectype: Class.NewRecController.saveType: line 46, column 1

An unexpected error has occurred. Your development organization has been notified.

What can I do to get this message to show on the VF page at the top as a simple message like "This Type already Exists"?

My Save method is below and I do have <apex:pageMessages> in my VF page.
 
public PageReference saveType() {
    	insert listRecType;
        PageReference contRecord = new PageReference('/'+contId);
        contRecord.setRedirect(true);
    return contRecord;
    }

 
Hi,

I have a pretty simple VF page that allows a user to create 1 or more records of a custom object that has master-detail relationships to the Account and Contact objects. The user can enter a Type value for the custom object, but each related Contact can only have 1 record of each Type value. Type values on the custom object can be repeated on different Contacts.  

What I'm trying to do is highlight the Type values the user is choosing to create, that already exist for that Contact so they can then change the value or remove it. Is there a way to accomplish this?

VF Page
<apex:page Controller="NewRecController">
<apex:form >
    <apex:pageBlock >
        <apex:pageMessages id="showMsg"/>
        <apex:pageBlockTable value="{!listRecType}" var="rec1" >
            <apex:column headerValue="Record Type">
                <apex:inputField value="{!rec1.Rec_Type__c}"/>
            </apex:column>
        </apex:pageBlockTable>
        <apex:pageBlockButtons >
            <apex:commandButton value="Add Another Record Type" action="{!addRecType}"/>
            <apex:commandButton value="Save All Record Types" action="{!saveType}" reRender="showMsg"/>
        </apex:pageBlockButtons>
        </apex:pageBlock>
</apex:form>
</apex:page>

Controller
public class NewRecController {

    Record_Type__c rec = new Record_Type__c();
    public list<Record_Type__c> listRecType{ get; set; }

    Id acctId;
    Id contId;
    String RecTypes;
    
//    Constructor 

	public NewRecController() { 
        acctId = ApexPages.currentPage().getParameters().get('acctId');
        contId = ApexPages.currentPage().getParameters().get('contId');
        RecTypes = ApexPages.currentPage().getParameters().get('acctTypes');
        
        rec.Account__c = acctId;
        rec.Contact__c = contId;
system.debug('@@@@@@ - AccountTypes: '+acctTypes);

        listRecType = new list<Record_Type__c>();
        listRecType.add(rec);
	} 

    Public void addRecType() {
        Record_Type__c rec1 = new Record_Type__c();
    		rec1.Contact__c = contId;
        	rec1.Account__c = acctId;
system.debug('@@@@@@ - AccountTypes: '+acctTypes);
system.debug('@@@@@@ - Record Type: '+rec1);
		listRecType.add(rec1);
        }
            
    public PageReference saveType() {
    	insert listRecType;
    return Page.NewRecType;
    }
}


 
Hi,

I have a simple Visualforce page with 3 fields that launches from a controller method related to another VF page. The page loads properly using the controller below, but I am trying to pre-populate the Contact and Account records that are the master part of the custom object master-detail relationship. Can anyone advise how I can do this?
 
public class NewObjController {

    Engage__c eng = new Engage__c();
    public list<Engage__c> listEngage{ get; set; }
 
    public NewObjController() {
        listEngage=new list<Engage__c>();
        listEngage.add(eng);
        }
 
    Public void addEngage() {
        Engage__c eng1 = new Engage__c();
            listEngage.add(eng1);
            }
            
    public PageReference saveEngage() {
        for(Integer i=1; i<listEngage.size(); i++) {
    insert listEngage;
    }
    }
}

 
Hello,

I am trying to create a test class for a relatively simple custom controller extension.  However, I am having trouble covering one of my methods in the controller that handled deletion of records.

I need to somehow pass a value for the DelAddrId variable in my controller from my test class, but I'm not sure how to do that. Can anyone assist?

Test Class
@isTest 
private class Test_AcctAddressesController {

    static testMethod void testMethod1() 
    {
        Account testAccount = test_CreateRecords.createAcct(0);
        insert testAccount;
        
        Contact testContact = test_CreateRecords.createCont(testAccount.Id);
        insert testContact;
        
	Test.StartTest();
        Account_Addresses__c testAcctAddr = new Account_Addresses__c();
            testAcctAddr.Account__c = testAccount.Id;
            testAcctAddr.Street__c = '1010 Test Ave';
            testAcctAddr.City__c = 'New York';
            testAcctAddr.State__c = 'NY';
            testAcctAddr.Zip_Postal_Code__c = '11212';
            testAcctAddr.Country__c = 'USA';
            testAcctAddr.Primary__c = TRUE;
            testAcctAddr.Current__c = TRUE;
        insert testAcctAddr;

        PageReference testPage = Page.Acct_Addresses;
			testPage.getParameters().put('DelAddrId', testAcctAddr.Id);   
   		Test.setCurrentPage(testPage);

        ApexPages.StandardController AcctAdd = new ApexPages.standardController(testAccount);
        	AcctAddresses AcctAdd1 = new AcctAddresses(AcctAdd);
System.assertNotEquals(null,AcctAdd1.deleteAddress());

        AcctAdd1.save();
        AcctAdd1.deleteAddress();
	Test.StopTest();
    }
}

Controller
public class AcctAddresses {     

    public List<Account_Addresses__c> addresses{get;set;}
    public string DelAddrId { get; set;}
    public Account accounts {get;set;} 
    public Account acct {get;set;} 

//Constructor 

    public AcctAddresses(ApexPages.StandardController controller) { 

        acct = (account)controller.getRecord();      

        accounts = [SELECT Id
                    FROM account
                    WHERE id=: acct.id LIMIT 1]; 

        addresses = [SELECT Id, Name, Primary__c, Current__c, Street__c, City__c, State__c, Zip_Postal_Code__c, Country__c, Account__c
                    FROM Account_Addresses__c
                    WHERE Account__r.Id = :accounts.id ORDER BY Primary__c, State__c];     
} 

//This method is to edit the existing contact record while clicking the Edit link 

        public pageReference Save(){
            update addresses;
        return ApexPages.CurrentPage();
        }

//This method is to delete the contact record while clicking the Del link 

    public pageReference deleteAddress(){

        Account_addresses__c ToBeDeleted = [SELECT Id FROM Account_addresses__c WHERE id = : DelAddrId LIMIT 1]; 
	        delete ToBeDeleted; 
    		    String baseUrl = URL.getSalesforceBaseUrl().toExternalForm(); 
        		PageReference redirectPage = new PageReference(baseUrl+'/'+acct.id); 
        	return redirectPage;  
    }   
}

 
I am trying to develop a test class to cover a trigger but I am only able to get to 64%. I'm not sure how to get the lines below covered. Can anyone advise?

Test Class:
Not covered - lines 13-16; lines 36-41; lines 47-56
@isTest
private class TestVIP_Types_Trigger {
    
    Private static testMethod void vipScenarioTests() {
        
Test.startTest();
        
        Account testAccount = new Account();
        	testAccount.Name = 'Test JN Account';
            testAccount.AccountSource = 'Networking';
		insert testAccount;
        
        Contact testContact = new Contact();
            testContact.LastName = 'LastTest';
            testContact.Phone = '5555555555';
            testContact.AccountId = testAccount.Id;
        insert testContact;

        Contact testContact2 = new Contact();
            testContact2.LastName = 'LastTest';
            testContact2.Phone = '5555555555';
            testContact2.AccountId = testAccount.Id;
        insert testContact2;
        
    	VIP_Type__c testVIP1 = new VIP_Type__c();
            testVIP1.Account__c = testAccount.Id;
            testVIP1.Contact__c = testContact.Id;
            testVIP1.VIP_Type__c = 'Ambassador';
        insert testVIP1;

        VIP_Type__c testVIP2 = new VIP_Type__c();
            testVIP2.Account__c = testAccount.Id;
            testVIP2.Contact__c = testContact.Id;
            testVIP2.VIP_Type__c = 'Influencer';
        insert testVIP2;

        Boolean errThrown = false;
        try{
        VIP_Type__c testVIP3 = new VIP_Type__c();
            testVIP3.Account__c = testAccount.Id;
            testVIP3.Contact__c = testContact.Id;
            testVIP3.VIP_Type__c = 'Ambassador';
        insert testVIP3;
        }catch(Exception e) {
            errThrown = true;
				Boolean expErr = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr, e.getMessage());
        }
        System.assertEquals(false,errThrown,'No exception was thrown');
        

        Boolean errThrown2 = false;
        try{
        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Ambassador';
        update testVIP2;
        }catch(Exception e) {
            errThrown2 = true;
				Boolean expErr2 = (e.getMessage().contains('This Type already exists')) ? true : false;
        System.assertEquals(true,expErr2, e.getMessage());
        }
        System.assertEquals(false,errThrown2,'No exception was thrown');

        testVIP2=[SELECT Id, VIP_Type__c FROM VIP_Type__c WHERE Id =: testVIP2.Id];
            testVIP2.VIP_Type__c = 'Celebrity';
        update testVIP2;

        VIP_Type__c testVIP1a = new VIP_Type__c();
            testVIP1a.Account__c = testAccount.Id;
            testVIP1a.Contact__c = testContact2.Id;
            testVIP1a.VIP_Type__c = 'Ambassador';
        insert testVIP1a;

        VIP_Type__c testVIP2a = new VIP_Type__c();
            testVIP2a.Account__c = testAccount.Id;
            testVIP2a.Contact__c = testContact2.Id;
            testVIP2a.VIP_Type__c = 'Celebrity';
        insert testVIP2a;

        delete testVIP1;
        delete testContact;
        delete testAccount;
Test.stopTest();
    }
}



Trigger:
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

 if(checkRecursive.runOnce())
    {
	Set<Id> acctIds = new Set<ID>();
	Set<Id> contIds = new Set<ID>();
//	  Set<String> vipTypes = new Set<String>();
	Map<VIP_Type__c, VIP_Type__c> contactTypeMap = new Map<VIP_Type__c, VIP_Type__c>();
	Map<Id, Set<String>> contactTypeMapDel = new Map<Id, Set<String>>();
    
// Get all the Account & Contact Ids in the Set 
	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);
            contactTypeMapDel.put(vip.Contact__c , new set<String>());
//            contactTypeMap.put(vip.Contact__c, vip.VIP_Type__c);
		}
	}
	else{

    	for(VIP_Type__c vip : Trigger.new) {
    		acctIds.add(vip.Account__c);
    		contIds.add(vip.Contact__c);
     	}
//	 }

	List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                            FROM VIP_Type__c
                            WHERE Contact__c = :contIds AND ID NOT IN:trigger.new];

//Check for VIP Types already entered for Contact
	Map<Id,set<string>> existingTypeMap = new Map<Id,set<string>>();
    
    for(VIP_Type__c vip: vipRecs) {
		set<string> existingTypes = new set<string>();
        if(existingTypeMap.containsKey(vip.Contact__c)){
            existingTypes = existingTypeMap.get(vip.Contact__c);
        }
        existingTypes.add(vip.VIP_Type__c);
        existingTypeMap.put(vip.Contact__c,existingTypes);
    }

	for (VIP_Type__c vip : trigger.new)
    {
        if (existingTypeMap.containsKey(vip.Contact__c)){
            if (existingTypeMap.get(vip.contact__c).contains(vip.VIP_Type__c)){
system.debug('@@@### - Check Map:  '+existingTypeMap.get(vip.contact__c));
system.debug('@@@### - Check VIP Type:  '+vip.VIP_Type__c);
                trigger.newMap.get(vip.Id).addError('This Type already exists for this Contact');
            }
            else
            {
                Set<string> existingTypes = existingTypeMap.get(vip.Contact__c);
                existingTypes.add(vip.VIP_Type__c);
                existingTypeMap.put(vip.Contact__c,existingTypes);
            }

        }
    } 
    }


// Query the Accounts
		List<Account> acct = new List<Account>();

// Use the VIP Types to get all the related Types for the Account 
			acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r ORDER BY VIP_Type__c) 
					FROM Account 
					WHERE Id in :acctIds]; 

// Iterate over each Account and VIP record 
			for(Account a : acct){ 
				a.VIP_Types__c = ''; 

				for(VIP_Type__c vip: a.VIP_Types__r){ 

					if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == ''){ // Check if the Type is already in the Account Field. if not add it otherwise skip 

					a.VIP_Types__c += vip.VIP_Type__c + '; '; 
					} 
				} 
			} 
// Update the Account 
		update acct; 
}
}

 
Hello,

I have a custom object called Account_Addresses__c that has a master-detail relationship to the Account object. That object houses address information as each account may have multiple addresses, however, only one of those addresses can be marked "current". I have a field on the custom object called Current__c to capture which address is current.

I created a trigger (below) to mark and unmark the addresses whena user changes the Current__c field and I am trying (in the same trigger) to then update a checkbox field on the Account record (Left_CA__c) if the newly selected current address is not in California and the Left_CA__c field on the Account was not already checked off.  However, this part of my trigger does not seem to be firing properly. From the logs, it looks like my Account map is initially null but then somehow gets populated. What am I doing wrong?

DEBUG|@@@### - parentAcct Map: {}
AcctAddrPrimCurr on Account_Addresses trigger event AfterUpdate|__sfdc_trigger/AcctAddrPrimCurr 0
DEBUG|@@@### - parentAcct Map: {0011h00000lC9vvAAC=Account:{Id=0011h00000lC9vvAAC, Left_NY__c=false}}
 
trigger AcctCurr on Account_Addresses__c(after update,after insert) {


//Update Account Address for Current
    List<Account_Addresses__c> acctAddr2 = new List<Account_Addresses__c>();

// Sets holding Account IDs (unique) and Addresses IDs (unique)
	Set<Id> CurrAcctIds = new Set<Id>();
	Set<Id> acctAddrIds2 = new Set<Id>();

    for(Account_Addresses__c aa2 : trigger.new){
       if(aa2.Current__c == TRUE){
            CurrAcctIds.add(aa2.Account__c);
			acctAddrIds2.add(aa2.id);
        }
    }

// get the records from Account Addresses that are under the Account but not meant to be Current

    acctAddr2 = [SELECT Id,Current__c
                FROM Account_Addresses__c
                WHERE Current__c = TRUE AND Account__c IN:CurrAcctIds AND Id NOT IN:acctAddrIds2];
	for(Account_Addresses__c aa2:acctAddr2)
		aa2.Current__c = FALSE;
    update acctAddr2;

//update related Account to check if new current address is not CA
	Map<ID, Account> parentAcct = new Map<ID, Account>();

    parentAcct = new Map<Id, Account>([SELECT Id, Left_CA__c, Date_Left_CA__c 
                                       FROM Account 
                                       WHERE Id IN :CurrAcctIds AND Left_CA__c != TRUE]);
system.debug('@@@### - parentAcct Map:  '+parentAcct);
    if(parentAcct != null){
    
	for(Account_Addresses__c ca: trigger.new){
    	Account myParentAcct = parentAcct.get(ca.Account__c);
        if(ca.Current__c == TRUE && ca.State__c != 'CA'){
            myParentAcct.Left_CA__C = TRUE;
            myParentAcct.Date_Left_CA__C = system.TODAY();
        }
    }
}
}

 
Hello,

I have a trigger where the 1st part is desiged to loop through custom object records of a Contact and prevent users from entering duplicate records for each account.  I have a statement that checks a map against the record being inserted/changed. When I look at my logs, I see that the IF statement returns a FALSE result, so the trigger should move on, but it is still throwing the addError message.  Does anyone know why this might be hapening?  The line is question is Line 48 below.
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

Set<Id> acctIds = new Set<ID>();
Set<Id> contIds = new Set<ID>();
Set<String> vipTypes = new Set<String>();
    
Map<VIP_Type__c, VIP_Type__c> contactTypeMap = new Map<VIP_Type__c, VIP_Type__c>();
// Get all the Account & Contact Ids in the Set 

	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);
		    VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
		}
	}
	else{

    for(VIP_Type__c vip : Trigger.new) {
    	acctIds.add(vip.Account__c);
    	contIds.add(vip.Contact__c);
        vipTypes.add(vip.VIP_Type__c);
    	VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
system.debug('@@@### - Key Check:  '+key);
system.debug('@@@### - vip Check:  '+vip);
system.debug('@@@### - 1st Map Check:  '+contactTypeMap.put( key, vip ));
system.debug('@@@### - 2nd Map Check:  '+contactTypeMap.get( key ));
system.debug('@@@### - 2nd Map Check:  '+contactTypeMap);

	        if(contactTypeMap.put( key, vip ) != null) {
	       		contactTypeMap.get( key ).addError( 'This type already exits for this Contact' );
    		}
     }
	 }

List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                            FROM VIP_Type__c
                            WHERE Contact__c = :contIds AND Account__c = :acctIds AND ID NOT IN:trigger.new];

//Check for VIP Types already entered for Contact
for(VIP_Type__c vip: vipRecs) {
system.debug('@@@### - Check for Types:  '+vipRecs);
    VIP_Type__c key = new VIP_Type__c(Contact__c=vip.Contact__c, Account__c=vip.Account__c, VIP_Type__c=vip.VIP_Type__c);
system.debug('@@@### - Check for Types-key:  '+key);
system.debug('@@@### - Check contactTypeMap:  '+contactTypeMap);
system.debug('@@@### - Check contactTypeMap (key):  '+contactTypeMap.containsKey(key));

    if(contactTypeMap.containsKey(key)) {
        contactTypeMap.get(key).addError('This Type already exists for this Contact');
    }
}
    

// Query the Accounts
		List<Account> acct = new List<Account>();

// Use the VIP Types to get all the related Types for the Account 
			acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r) 
					FROM Account 
					WHERE Id in :acctIds]; 

// Iterate over each Account and VIP record 
			for(Account a : acct){ 
				a.VIP_Types__c = ''; 

				for(VIP_Type__c vip: a.VIP_Types__r){ 

					if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == ''){ // Check if the Type is already in the Account Field. if not add it otherwise skip 

					a.VIP_Types__c += vip.VIP_Type__c + '; '; 
					} 
				} 
			} 
// Update the Account 
		update acct; 
}

 
Hello,

I have a trigger that is checking a picklist field on a custom object (VIP_Type__c) to make sure duplicate records are not allowed under the parent object (Contact).  I am getting an Apex error message related to the error message line in my trigger. Can anyone help me understand why?
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){

	Set<Id> acctIds = new Set<ID>();
	Set<Id> contIds = new Set<ID>();

	map<Id, set<String>> contact_type_map = new map<Id, set<String>>();

// Get all the Account & Contact Ids in the Set 
	if (Trigger.isDelete) {
		for(VIP_Type__c vip : Trigger.old){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);

			contact_type_map.put(vip.Contact__c , new set<String>());
		}
	}
	else{
        for(VIP_Type__c vip : Trigger.new){
			acctIds.add(vip.Account__c);
            contIds.add(vip.Contact__c);

            contact_type_map.put(vip.Contact__c, new set<String>{vip.VIP_Type__c});
System.Debug('@@@###-contact_Type_Map: '+contact_Type_Map);
	}
    }
		List<VIP_Type__c> vipRecs = [SELECT Id,Account__c,Contact__c,VIP_Type__c
                                    FROM VIP_Type__c
                                    WHERE Contact__c in:contIds];


//Check for VIP Types already entered for Contact
    for(VIP_Type__c objVIP: vipRecs){
		if(contact_type_map.get(objVIP.Contact__c).contains(objVIP.VIP_Type__c)){
system.debug('@@@### - Error message:  '+objVIP.VIP_Type__c);
                trigger.newMap.get(objVIP.Id).addError('This Type already exists for this Contact');
system.debug('@@@### - Error message:  '+trigger.newMap.get(objVIP.Id));
        }
        else{
            contact_type_map.get(objVIP.Contact__c).add(objVIP.VIP_Type__c);
        }
    }

 
Hi,

I have a pretty basic question (I think) about the use of a Set within a map.  I have a trigger with a piece of code:
 
map<Id, set<String>> newMap = new map<Id, set<String>>();

For(Custom_Object__c cust : Trigger.new){
newMap.put(cust.Contact__c, new set<String>());
}

I am trying to create a keyset of Contact ID & Type on a custom object so I can compare to ensure Contact records only allow 1 Type of each related custom object record.  When I run the Debug statements, the map is only populating the Contact ID.  I have 2 questions:

What are the set<string> in my map and new set<string> in my put statement designed to do, and how do I get the set<string> to populate?
I have a trigger that is designed to write unique values of a Picklist from a child object (VIP_Type__c) to the associated Account record. I am having trouble figuring out how to convert the picklist value to a string value to check if the Account field contains the picklist value. The line of code I have is:
if(!a.VIP_Types__r.contains(vip.VIP_Type__c))

Where vip.VIP_Type__c is the picklist field and VIP_Types__r is the text field on the Account.  I am getting an error:

"Method does not exist or incorrect signature: void contains(String) from the type List<VIP_Type__c>"

Any ideas?  My full trigger is below:
 
trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){
        
        Set<Id> acctIds = new Set<ID>();
        
        // Get all the Account Ids in the Set
        for(VIP_Type__c vip : Trigger.new){
            acctIds.add(vip.Account__c);
        }
        // QUery the Accounts
        List<Account> acct = new List<Account>();
        // Use the VIP Types to get all the related Types for the Account
        acct = [SELECT Id, VIP_Types__c
                FROM Account
                WHERE Id in :acctIds];
        
        // Iterate over each Account and VIP record
        for(Account a : acct){
                if(a.Id !=NULL){
                    for(VIP_Type__c vip: a.VIP_Types__r){
                        if(!a.VIP_Types__r.contains(vip.VIP_Type__c)){ // Check if the Type is already in the Account Field. if not add it otherwise skip
                            a.VIP_Types__c += vip.VIP_Type__c + ';';
                        }
                    }
                }
        }
        // Update the Account
        update acct;
    }

 
I have a Visualforce Page that uses the standard Contact controller with a controller extension. The page is embedded on the Contact record layout and displays a related list of a custom object that has a master-detail to the Contact and Account records.

I am trying to create a custom button on the embedded VF page to create a new record that pre-populates the associated Contact and Account (from the Contact) IDs to 2 lookup fields on the custom object record. I am using a CommandButton with !URLFOR($Action attributes to open the new record creation page (in Lightning), however, I cannot figure out how to get the Account pre-populated and then redirect back to the contact record once saved.

The line below opens the pop-up and pre-populated the Contact ID, but I need to select the Account and then it directs to the new record created, not the original Contact record. Is it possible to do what I am trying to do with a CommandButton?
 
<div style="margin-left: 30%;">
<apex:commandButton action="{!URLFOR($Action.Type__c.New)}" value="New Type" oncomplete="window.open('/{ContactId}&retURL=(ContactId}')"/>
</div>