• Joe Brodar
  • NEWBIE
  • 105 Points
  • Member since 2015
  • Internal Development Strategist
  • GNGF

  • Chatter
    Feed
  • 3
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 4
    Questions
  • 16
    Replies
Hello, I am trying to write a trigger to update a lookup field, I don't care if the update happens before or after insert, but best practices point me towards a before insert action. I managed to write a trigger and public class to complement it, but now I have 0% code coverage and I cannot seem to get a Test to run using the @isTest method.

Some backstory: I have a custom object called Plan Agent that includes a User lookup. I have another custom object called
Agent/District Assignment that also contains a User lookup. The goal is to dynamically fill a lookup filled called "Agent District Assignment" on the Plan Agent record, either when the record is being created or after it is created.

So my code currently looks like this:
 
Trigger:

trigger UpdateADA on Plan_Agent__c (before insert) {
    if (trigger.isBefore) 
    {
        if (trigger.isInsert) 
        {
            ADA_PlanAgentUpdateService.findADA(trigger.new);
        }
    }
}

Class:

public with sharing class ADA_PlanAgentUpdateService
{
    public static void findADA (List<Plan_Agent__c> records)
    {
        Set<String> planAgents = new Set<String>();
        for (Plan_Agent__c record : records) planAgents.add(record.Agent__c);
        
        Map<String, Agent_District_Assignment__c> dAssignments = new Map<String, Agent_District_Assignment__c>();
        for (Agent_District_Assignment__c dAssignment : [
            SELECT id FROM Agent_District_Assignment__c
            WHERE User__c IN :planAgents
        ]) dAssignments.put(dAssignment.Id, dAssignment);
        
        for (Plan_Agent__c record : records)
            if (dAssignments.containsKey(record.Agent__c))
                record.Agent_District_Assignment__c = dAssignments.get(record.Agent__c).Id;
    }
 }

Test Class:

@isTest
public with sharing class ADA_PlanAgentUpdateService
{
    public static void findADA (List<Plan_Agent__c> records)
    {
        Set<String> planAgents = new Set<String>();
        for (Plan_Agent__c record : records) planAgents.add(record.Agent__c);
        
        Map<String, Agent_District_Assignment__c> dAssignments = new Map<String, Agent_District_Assignment__c>();
        for (Agent_District_Assignment__c dAssignment : [
            SELECT id FROM Agent_District_Assignment__c
            WHERE User__c IN :planAgents
        ]) dAssignments.put(dAssignment.Id, dAssignment);
        
        for (Plan_Agent__c record : records)
            if (dAssignments.containsKey(record.Agent__c))
                record.Agent_District_Assignment__c = dAssignments.get(record.Agent__c).Id;
    }
    ADA_PlanAgentUpdateService.findADA(Trigger.new);
}

Any help would be greatly appreciated, thanks!
I am trying to update the following 3 custom fields under my Member_Vendor_del__c custom object:

Vendor_ID__c
Member_Account_ID__c
Member_State__c

I have created the code below to update the Vendor_ID__c and Member_Account_ID__c

trigger VendorRepUpdateTrigger on Member_Vendor_del__c (before update) {
// Update the Vendor's ID, Member's ID, and Member's Physical State into the Member Vendor Record.    
    for (Member_Vendor_del__c u : trigger.new){
          if (u.Vendor_ID__c == null)
              u.Vendor_ID__c                 = u.Vendor__c;
              u.Member_Account_ID__c = u.Member__c;
  }
}


My issue is with getting Member_State__c to populate with the Physical State(API Field Name: BillingState) from the related member account. I have createdthe SOQL query below to return the string text value on the account but I keep getting the error "Illegal assignment from List to String"

// Update the Member's Physical State onto the Member Vendor Record.                       
     for (Member_Vendor_del__c u : trigger.new)
        if (u.Member_State__c == null)
                  u.Member_State__c = [Select BillingState
                                     From Account
                                     Where Account.Name = :u.Member__c];}


I can add .Id to the query and the error goes away but then the trigger wants to return a Salesforce ID rather than the 2 letter abbreviation for the State.

Question #1: What can I do to my SOQL query to return the text value rather than an ID?

Question #2: Can I add the SOQL query to the first part of the trigger? Something like:

trigger VendorRepUpdateTrigger on Member_Vendor_del__c (before update) {
// Update the Vendor's ID, Member's ID, and Member's Physical State into the Member Vendor Record.   
    for (Member_Vendor_del__c u : trigger.new){
          if (u.Vendor_ID__c == null)
              u.Vendor_ID__c         = u.Vendor__c;
              u.Member_Account_ID__c = u.Member__c;
              u.Member_State__c      = [Select Id, Account.BillingState
                                        From Account
                                           where Account_ID__c = :u.Member__c].Id;
 }
}
I am only getting the field names, not the data sent to my email.  Please help.

global class BatchSyncErrors implements Database.Batchable<sOBject>, Database.Stateful{
   
    global string excelHeader = 'ApexClassID,  CompletedDate ,  ExtendedStatus,  JobItemsProcessed,  JobType,  MethodName,  NumberOfErrors,  Status,  TotalJobItems \n';
    global string finalstr = '';
    
    //constructor
    global BatchSyncErrors(){
        finalstr = excelHeader;
    }
    //start method
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator('SELECT ApexClassID, CompletedDate, ExtendedStatus, JobItemsProcessed, JobType, MethodName, NumberOfErrors, Status, TotalJobItems FROM AsyncApexJob Limit 10');
    }
 
    //execute
        global void execute(Database.BatchableContext BC, List<sOBject> scope){

            string recordString;
        
            for(sOBject a: scope){
        
                // Type Cast sOBject to AsyncApexJob
                AsyncApexJob asyncApexJobRecord = (AsyncApexJob) a;
                   
                if(recordString == NULL){
                    recordString = AsyncApexJob.ApexClassID +',' + AsyncApexJob.CompletedDate +','+ AsyncApexJob.ExtendedStatus+',' + AsyncApexJob.JobItemsProcessed + ',' + AsyncApexJob.JobType +  ',' + AsyncApexJob.MethodName + ',' + AsyncApexJob.NumberOfErrors + ',' + AsyncApexJob.TotalJobItems + ','+ AsyncApexJob.JobItemsProcessed + ',' +AsyncApexJob.JobType + ',' + AsyncApexJob.TotalJobItems+ '\n';
                } else {
                    recordString += AsyncApexJob.ApexClassID +',' + AsyncApexJob.CompletedDate +','+ AsyncApexJob.ExtendedStatus+',' + AsyncApexJob.JobItemsProcessed + ',' + AsyncApexJob.JobType +  ',' + AsyncApexJob.MethodName + ',' + AsyncApexJob.NumberOfErrors + ',' + AsyncApexJob.TotalJobItems + ','+ AsyncApexJob.JobItemsProcessed + ',' +AsyncApexJob.JobType + ',' + AsyncApexJob.TotalJobItems+ '\n';
                }
        
            }
        
            finalstr += recordString;

}

    
    //finish
    global void finish (Database.BatchableContext BC){
       
        system.debug('**** Final String *** ' + finalstr);
        //TODO: pass this string to create CSV in your CSV Method.
         //   String csvContent = finalstr;
         //       Attachment attachment = new Attachment();
         //       attachment.Body = Blob.valueOf(csvContent);
         //       attachment.Name = 'csvFile.csv';
              
         //       insert attachment;
       
         //TODO: Create an generic method to send emails & pass this attachment.
         
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email,ExtendedStatus,JobType,ApexClassId,MethodName
      FROM AsyncApexJob WHERE Id =
      :BC.getJobId()];
            
        Messaging.Singleemailmessage mail = new Messaging.Singleemailmessage();
            mail.setToAddresses((new String[] {'all60388@adobe.com'}));
            //mail.setReplyTo('noreply@privatebudget.com');
            mail.setSenderDisplayName('Batch Class Errors');
            mail.setSubject('Batch Class Errors');
            mail.setBccSender(false);
            mail.setUseSignature(false);
            mail.setPlainTextBody(finalstr);
            system.debug('@@@@ sendEmail - mail : ' + mail);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
 
    }
}


In my email I get:


ApexClassID,  CompletedDate ,  ExtendedStatus,  JobItemsProcessed,  JobType,  MethodName,  NumberOfErrors,  Status,  TotalJobItems 
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems


Thank you

I am working on writing a custom Lightning component for use in a Community. What I need it to do is basically recreate the "Articles with this Topic" default component that goes on the Topic Detail page. The default component doesn't allow for custom sorting or custom messaging based on criteria such as the number of articles in the list or if the Topic is linked to another object record, so I am writing my own that will allow for these things.

I am getting stuck on querying the TopicAssignment object in the Apex controller, which I think must be a permissions issue. When I view the component as myself (System Administrator profile) it appears to work, and I get the list of Knowledge articles. When I log in as a Community User (Customer Community User profile), the Apex method returns an empty list. The code for that Apex method is listed below:

public static List<Knowledge__kav> getArticlesForTopic(String topicId)
	{
		try
		{ 
			return [SELECT Id, Title, Subtitle__c, Article_Body__c FROM Knowledge__kav WHERE Id IN (SELECT EntityId FROM TopicAssignment WHERE TopicId = :topicId) AND PublishStatus = 'Online' ORDER BY Sequence__c ASC, LastPublishedDate DESC]; 
		}
		catch(QueryException qe)
		{
			return null;
		}
		catch(Exception e)
		{
			System.debug(JRBRepo.handleError(e,TRUE));
			return null;
		}
	}
I cannot find the Topic or TopicAssignment objects through the Object Manager UI, so I cannot see a way to grant permissions to these objects for the Community User profile. I see under the System Permissions section that there are several permissions related to managing Topics, but not one for just reading Topics. I don't want the Community Users to have control over Topics or the assignment of Topics, I just need them to be able to read them.

Is there a permission that I am missing, or are those objects named something different in the Object Manager UI? 

I am trying to set up Knowledge in a Community, using the Napili template and the Article Detail page template. I am having trouble getting the page to show just the Article body and not all of the administrative fields in the page layout. I am using the Article Content Component, which is displaying the page layout that is used in the regular Salesforce record page (see the screenshot below).

User-added image 

How can I get the Component to just show the Article body, or do I need to create a custom component to do this?

Thank you!
Joe 

I am attempting to match up users coming in from an external POST request to Salesforce users via a SOQL query of the name that returns a user record, then use the ID from the user record to insert a custom object record with a User Lookup field. However I am getting the following error: 
Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, User: id value of incorrect type: 005U0000003GvJKIA0: [User__c]
This error is being thrown because the ID needs to be 15 characters, but is, in practice, coming out as 18 characters. I have tried a few different methods of limiting the string to 15 chars, but to no avail. This is frustrating because it works just fine in the sandbox environment, it is only when deployed to production that this error comes up.

Methods I have tried:

1. No string correction
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String usrId = matchUsr.Id;
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

2. Substring the usrId string to (0,15) 
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String userMatch = matchUsr.Id;
            String usrId = userMatch.subString(0, 15);
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

3. Take one character from the ID string of the user record at a time (0-14), and add to new usrId string
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String userMatch = matchUsr.Id;
            String usrId = '';
            for (Integer xc = 0; xc < 15; xc++) {        
                usrId += userMatch.subString(xc, xc+1);
            }
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

None of these have produced a working result. All three continue to return an 18 character string as the usrId variable. I have found several threads on this forum regarding this topic, but the only solutions that are listed with those questions are either syntax error with the specific code, or someone saying that you have to subString the ID. If anyone has any solutions or ideas beyond that, please let me know.

Thanks,
Joe
I attempted to delpoy code from the sandbox to production, but was met with an error that is persistent, and occurs when I run the test seperately from deployment. The test that fails is ABSI_TEST_MassTaskController, and it fails when it reaches the assertion that pageRef cannot be null. The exact error code is:
ABSI_TEST_MassTaskController.myUnitTest(), Details: System.Exception: Assertion Failed: Same value: null Class.ABSI_TEST_MassTaskController.myUnitTest: line 110, column 1

I am completely unable to edit this test code, nor can I edit the class that it should be testing, in fact they are completely absent from the sandbox environment.

The test class (ABSI_TEST_MassTaskController) is:
/******************************************************
 * Description      : Test Coverage for ABSI_MassTaskController (98%)
 * @author          : Malaka Silva
 * @since           : May 07, 2010  
 * Copyright 2010 ABSI. All rights reserved. 
 ******************************************************/
@isTest
private class ABSI_TEST_MassTaskController {

    static testMethod void myUnitTest() {
        Test.startTest();
        
        //Create Accounts
        Account account1 = new Account();
        account1.Name = 'Test_Account_01';
        insert account1;
        
        Account account2 = new Account();
        account2.Name = 'Test_Account_02';
        insert account2;        
        
        //Create Contacts
        Contact contact1 = new Contact();
        contact1.LastName = 'Test_Contact_01';
        insert contact1;
        
        Contact contact2 = new Contact();
        contact2.LastName = 'Test_Contact_01';
        insert contact2;
        
        //Get a profile from SFDC
        Profile profile = [select Id from Profile limit 1];
        
        //Create a user
        User user = new User();
        user.Username = 'Test_user_name@test.com';
        user.LastName = 'Test_last_name';
        user.ProfileId = profile.Id;
        user.Alias = 'tst';
        user.Email = 'Test_email@email.com';
        user.CommunityNickname = 'Test_nick_name';
        user.TimeZoneSidKey = 'GMT';
        user.LocaleSidKey = 'en_US';
        user.LanguageLocaleKey = 'en_US';
        user.EmailEncodingKey = 'ISO-8859-1';
        insert user;
        
        //Simulate the page for What Id
        PageReference pPageReference = Page.ABSI_Mass_Task_Action;
        pPageReference.getParameters().put('objIds',account1.Id+','+account2.Id);
        pPageReference.getParameters().put('retUrl','');
        Test.setCurrentPage(pPageReference);
        
        ABSI_MassTaskController controler = new ABSI_MassTaskController();
        System.assertEquals(controler.showWhoId, true);
        controler.getTableDisplayNames();
        controler.saveNew();
    controler.save();
    controler.back();

        //Simulate the page for Who Id
        pPageReference = Page.ABSI_Mass_Task_Action;
        pPageReference.getParameters().put('objIds',contact1.Id+','+contact2.Id);
        pPageReference.getParameters().put('retUrl','');
        Test.setCurrentPage(pPageReference);
        controler = new ABSI_MassTaskController();
        System.assertEquals(controler.showWhoId, false);
        controler.getTableDisplayNames();
        controler.getselReminderOptions();
        controler.saveNew();
    Pagereference pageRef = controler.save();
      System.assertEquals(pageRef, null);
    controler.back();
    
    controler.task.OwnerId = user.Id;
    controler.task.Subject = 'Test_Subject';
    controler.task.Status = 'Completed';
    controler.task.Priority = 'High';
    //Set the reminder
    controler.task.IsReminderSet = true;
    controler.contact.Birthdate = Date.today();
    controler.reminderTime = '23:30';
    //Send Email notification
    controler.sendNotificationEmailCheckBox = true;
    
    controler.saveNew();
    pageRef = controler.save();
      System.assertNotEquals(pageRef, null);
    
        Test.stopTest();
    }
}

The class it should be testing (ABSI_MassTaskController) is:
/******************************************************
 * Description      : Apex Controller for ABSI_Mass_Task_Action page
 * @author          : Malaka Silva
 * @since           : May 07, 2010  
 * Copyright 2010 ABSI. All rights reserved. 
 ******************************************************/
public with sharing class ABSI_MassTaskController {

    //Capture the values for the standard Task
    public Task task{set;get;}
    //Capture the value for the reminder date/time
    public Contact contact{set;get;}
    public String reminderTime{set;get;}
    //Other Form fields
    public Boolean sendNotificationEmailCheckBox{set;get;}
    public Map <Id,String> displayNames{set;get;}
    private Map <Id,Id> ownerIds;
    public Boolean showWhoId{set;get;}
    public Boolean showPage{set;get;}
    public Boolean assignToOwner{set;get;}
    //Page processing parameters
    private List <Selectoption> selReminderOptions;
    private String [] arrObjIds;
    private String objName = null;
    private Boolean saveStatus;
    private String objPrefix = null;
    
    /**
    * Constructor
    * Initalize the values & generate the object list(Names)
    */
    public ABSI_MassTaskController(){
        //Initalize the variables
        showPage = false;
        task = new Task();
        contact = new Contact();
        displayNames = new Map<Id,String>();
        ownerIds = new Map<Id,Id>();
        showWhoId = false;
        sendNotificationEmailCheckBox = false;
        saveStatus = false;
        assignToOwner = false;
        
        try{
            //Get the object ids passed as parameter
            Map<String, String> params = ApexPages.currentPage().getParameters();
            String strObjIds = params.get('objIds');
            arrObjIds = strObjIds.split(',');
            
            //Identify the object name/type and get the names
            if(arrObjIds != null && !arrObjIds.isEmpty()){
                //Find the object name
                Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe(); 
                Set<String> keyPrefixSet = gd.keySet();
                String tPrefix = arrObjIds[0].subString(0,3);
                
                for(String sObj : keyPrefixSet){
                    Schema.DescribeSObjectResult r =  gd.get(sObj).getDescribe();
                    if(tPrefix.equals(r.getKeyPrefix())){
                        objName = r.getName();
                        objPrefix = tPrefix;
                        break;
                    }
                }
                //Query the name for all the objects
                if(objName != null){
                    String strFieldName = 'name';
                    //Check if the object is a Contact or Lead
                    if(objName != 'Contact' && objName != 'Lead'){
                        showWhoId = true;
                    }
                    //Handle field that doesn't have a name field
                    if(objName == 'Case'){
                        strFieldName = 'CaseNumber';
                    }
                    
                    String strQuery = 'select id,OwnerId,' + strFieldName + ' from ' + objName + ' ';
                    Boolean bFirst = true;
                    for(String strObjId:arrObjIds){
                        if(bFirst){
                            strQuery += ' where Id in (\'';
                            bFirst = false;
                        }else{
                            strQuery += ',\'';
                        }
                        strQuery += String.escapeSingleQuotes(strObjId) + '\'';
                    }
                    strQuery += ')';
                    try{
                        SObject [] sfdcObjects = Database.query(strQuery);
                        //Generate the name list
                        for(SObject sfdcObject:sfdcObjects){
                            displayNames.put((Id)sfdcObject.get('id'),(String)sfdcObject.get(strFieldName));
                            ownerIds.put((Id)sfdcObject.get('id'), (Id)sfdcObject.get('OwnerId'));
                        }
                    }catch(Exception e){
                        strQuery = strQuery.replace(',' + strFieldName, ' ');
                        SObject [] sfdcObjects = Database.query(strQuery);
                        //Generate the Id list instead of name list
                        for(SObject sfdcObject:sfdcObjects){
                            displayNames.put((Id)sfdcObject.get('id'),(Id)sfdcObject.get('id'));
                        }
                    }
                }
            }
            showPage = true;
        }catch(Exception e){
            //Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, e.getMessage()));
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, 'Unexpected error has occured. Please try again later.'));
            showPage = false;
        }
        
    }
    public void assignToOwnerClick(){
        if(assignToOwner){
            assignToOwner = false;
        }else{
            assignToOwner = true;
        }
    }
    /**
    * Save the new task and keep the existing page
    */
    public void saveNew(){
        //Create the new task list
        List <Task> lTask = new List<Task>();
        //Capture the status for save()
        saveStatus = false;
        try{
            for(String strObjId:arrObjIds){
                Task taskNew = new Task();
                
                if(showWhoId){
                    //If the selected objests are not Contacts/Leads
                    taskNew.WhatId = strObjId;
                }else{
                    //If only Contacts/Leads
                    taskNew.WhoId = strObjId;
                }
                //Assign to the record owner based on selected options
                if(assignToOwner){
                    taskNew.OwnerId = ownerIds.get(strObjId);   
                }else{
                    taskNew.OwnerId = task.OwnerId;
                }
                taskNew.status = task.status;
                taskNew.subject = task.subject;
                taskNew.activityDate = task.activityDate;
                taskNew.priority = task.priority;
                taskNew.description = task.description;
                //If the reminder is set
                if(task.IsReminderSet){
                    taskNew.IsReminderSet = true;
                    String [] arrReminderTimes = reminderTime.split(':');
                    Time tmpTime = Time.newInstance(Integer.valueOf(arrReminderTimes[0]), Integer.valueOf(arrReminderTimes[1]), 0, 0);
                    Datetime reminderDateTime = Datetime.newInstance(contact.Birthdate, tmpTime);
                    taskNew.ReminderDateTime = reminderDateTime;
                }
                lTask.add(taskNew);
            }
            //Insert the new tasks to the SFDC Org
            insert lTask;
        }catch(Exception e){
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, e.getMessage()));
            return;
        }
        
        saveStatus = true;
        Apexpages.addMessage(new Apexpages.Message(Apexpages.Severity.CONFIRM, 'Task(s) successfully created.'));
        //Send email
        if(sendNotificationEmailCheckBox){
            sendMail(lTask);
        }
    }
    /**
    * Save the new task and to back to the previous page 
    * (If no errors)
    */
    public Pagereference save(){
        saveNew();
        if(saveStatus){
            return back();
        }
        return null;
    }   
    /**
    * Send email to the assigned engineer
    */
    private void sendMail(List <Task> lTask){
        try{
            //Set mail parameters
            //Query the assigned user
            User assignedUser = [Select u.Name, u.Email From User u where u.Id =: task.OwnerId];
            //Prepare the mail message
            Messaging.Singleemailmessage singleMail = new Messaging.Singleemailmessage();
            singleMail.setToAddresses(new String[]{ assignedUser.Email });
            singleMail.setSubject(task.subject);
            //Generate the HTML body and the plain text body
            String strText = 'To: ' + assignedUser.Name + '<br/><br/>';
            strText += System.Userinfo.getName() + ' has assigned you the following task(s):<br/><br/>';
            strText += 'Subject: ' + task.subject + '<br/><br/>';
            strText += objName + ':<br/>';
            
            String strPlainText = 'To: ' + assignedUser.Name + '/n/n';
            strPlainText += System.Userinfo.getName() + ' has assigned you the following task(s):/n/n';
            strPlainText += 'Subject: ' + task.subject + '/n/n';
            strPlainText += objName + ':/n';
            
            //Put the tasks with objects ids
            Map <Id,Id> mObjectTask = new Map<Id,Id>();
            for(Task newTasks:lTask){
                if(showWhoId){
                    mObjectTask.put(newTasks.WhatId, newTasks.Id);
                }else{
                    mObjectTask.put(newTasks.WhoId, newTasks.Id);
                }
            }
            for(Id displayKey:displayNames.keySet()){
                String displayName = displayNames.get(displayKey);
                Id taskId = mObjectTask.get(displayKey);
                strText += '-' + displayName;
                strText += ' (<a href=\'http://na1.salesforce.com/' + taskId  + '\'>';
                strText += 'http://na1.salesforce.com/' + taskId  + '</a>)';
                strText += '<br/>';
                
                strPlainText += '-' + displayName;
                strPlainText += ' (http://na1.salesforce.com/' + taskId  + ')';
                strPlainText += '/n';
            }
            strText += '<br/>Priority: ' + task.Priority + '<br/><br/>';
            
            strPlainText += '/nPriority: ' + task.Priority + '/n/n';
            
            //Set the test message to the mail
            singleMail.setHtmlBody(strText);
            singleMail.setPlainTextBody(strPlainText);
            //Send the mail
            Messaging.sendEmail(new Messaging.Singleemailmessage [] { singleMail });
        }catch(Exception e){
            //Capture if unexpected error occurs - such as Salesforce mail limit
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, 'Task(s) added. Mail not sent.'));
        }   
    }
    
    /**
    * Insert in the ReminderDate List the Time : Hours:Min
    */ 
    public List<SelectOption> getselReminderOptions(){
        selReminderOptions = new List<SelectOption>();
        String val = '' ; 
        for (Integer i = 0 ; i < 24 ; i++){
            // Draw the options to add to the reminder picklist 
            val = i+':'+'00';           
            selReminderOptions.add(new SelectOption(val,val));
            val = i+':'+'30';
            selReminderOptions.add(new SelectOption(val,val));
        }
        return selReminderOptions;    
    } 
    /**
    * Go to the previous page
    */
    public Pagereference back(){
        Pagereference pageRef = new Pagereference('/' + objPrefix);
        pageRef.setRedirect(true);
        return pageRef;
    }
    /**
    * Display the selected object names in front end
    */
    public List <String> getTableDisplayNames(){
        List <String> rtnList = new List<String>();
        
        for(String displayName:displayNames.values()){
            rtnList.add('-' + displayName);
        }
        return rtnList;
    }    
    
}

After searching this forum, I was only able to find one reference to this issue, and the suggested solution was to edit the test code. I am unable to deploy any code to production, and so far I have been unsuccessful in finding any documentation on successfully solving the issue here or on third party forums like StackExchange. Any suggestions are welcome.

Thanks,

Joe

I am trying to set up Knowledge in a Community, using the Napili template and the Article Detail page template. I am having trouble getting the page to show just the Article body and not all of the administrative fields in the page layout. I am using the Article Content Component, which is displaying the page layout that is used in the regular Salesforce record page (see the screenshot below).

User-added image 

How can I get the Component to just show the Article body, or do I need to create a custom component to do this?

Thank you!
Joe 

I am working on writing a custom Lightning component for use in a Community. What I need it to do is basically recreate the "Articles with this Topic" default component that goes on the Topic Detail page. The default component doesn't allow for custom sorting or custom messaging based on criteria such as the number of articles in the list or if the Topic is linked to another object record, so I am writing my own that will allow for these things.

I am getting stuck on querying the TopicAssignment object in the Apex controller, which I think must be a permissions issue. When I view the component as myself (System Administrator profile) it appears to work, and I get the list of Knowledge articles. When I log in as a Community User (Customer Community User profile), the Apex method returns an empty list. The code for that Apex method is listed below:

public static List<Knowledge__kav> getArticlesForTopic(String topicId)
	{
		try
		{ 
			return [SELECT Id, Title, Subtitle__c, Article_Body__c FROM Knowledge__kav WHERE Id IN (SELECT EntityId FROM TopicAssignment WHERE TopicId = :topicId) AND PublishStatus = 'Online' ORDER BY Sequence__c ASC, LastPublishedDate DESC]; 
		}
		catch(QueryException qe)
		{
			return null;
		}
		catch(Exception e)
		{
			System.debug(JRBRepo.handleError(e,TRUE));
			return null;
		}
	}
I cannot find the Topic or TopicAssignment objects through the Object Manager UI, so I cannot see a way to grant permissions to these objects for the Community User profile. I see under the System Permissions section that there are several permissions related to managing Topics, but not one for just reading Topics. I don't want the Community Users to have control over Topics or the assignment of Topics, I just need them to be able to read them.

Is there a permission that I am missing, or are those objects named something different in the Object Manager UI? 

I am trying to set up Knowledge in a Community, using the Napili template and the Article Detail page template. I am having trouble getting the page to show just the Article body and not all of the administrative fields in the page layout. I am using the Article Content Component, which is displaying the page layout that is used in the regular Salesforce record page (see the screenshot below).

User-added image 

How can I get the Component to just show the Article body, or do I need to create a custom component to do this?

Thank you!
Joe 

Hello, I am trying to write a trigger to update a lookup field, I don't care if the update happens before or after insert, but best practices point me towards a before insert action. I managed to write a trigger and public class to complement it, but now I have 0% code coverage and I cannot seem to get a Test to run using the @isTest method.

Some backstory: I have a custom object called Plan Agent that includes a User lookup. I have another custom object called
Agent/District Assignment that also contains a User lookup. The goal is to dynamically fill a lookup filled called "Agent District Assignment" on the Plan Agent record, either when the record is being created or after it is created.

So my code currently looks like this:
 
Trigger:

trigger UpdateADA on Plan_Agent__c (before insert) {
    if (trigger.isBefore) 
    {
        if (trigger.isInsert) 
        {
            ADA_PlanAgentUpdateService.findADA(trigger.new);
        }
    }
}

Class:

public with sharing class ADA_PlanAgentUpdateService
{
    public static void findADA (List<Plan_Agent__c> records)
    {
        Set<String> planAgents = new Set<String>();
        for (Plan_Agent__c record : records) planAgents.add(record.Agent__c);
        
        Map<String, Agent_District_Assignment__c> dAssignments = new Map<String, Agent_District_Assignment__c>();
        for (Agent_District_Assignment__c dAssignment : [
            SELECT id FROM Agent_District_Assignment__c
            WHERE User__c IN :planAgents
        ]) dAssignments.put(dAssignment.Id, dAssignment);
        
        for (Plan_Agent__c record : records)
            if (dAssignments.containsKey(record.Agent__c))
                record.Agent_District_Assignment__c = dAssignments.get(record.Agent__c).Id;
    }
 }

Test Class:

@isTest
public with sharing class ADA_PlanAgentUpdateService
{
    public static void findADA (List<Plan_Agent__c> records)
    {
        Set<String> planAgents = new Set<String>();
        for (Plan_Agent__c record : records) planAgents.add(record.Agent__c);
        
        Map<String, Agent_District_Assignment__c> dAssignments = new Map<String, Agent_District_Assignment__c>();
        for (Agent_District_Assignment__c dAssignment : [
            SELECT id FROM Agent_District_Assignment__c
            WHERE User__c IN :planAgents
        ]) dAssignments.put(dAssignment.Id, dAssignment);
        
        for (Plan_Agent__c record : records)
            if (dAssignments.containsKey(record.Agent__c))
                record.Agent_District_Assignment__c = dAssignments.get(record.Agent__c).Id;
    }
    ADA_PlanAgentUpdateService.findADA(Trigger.new);
}

Any help would be greatly appreciated, thanks!
I have a working Visualforce page and controller, that searches both Leads & Opportunities for a specific email address, and displays fields if there are any results.

I have been asked by our business department to make a change, adding checkboxes and radio buttons to the page.

I have no idea how I might begin doing this.  Does anyone have any ideas?

Here is the controller:

Public with sharing class AllOppsearchClass{
 Public List<Lead>leadList{get;set;}
 Public List<Opportunity>optyList{get;set;}
   Public String searchStr{get;set;}
   Public AllOppsearchClass(){
   }
     public AllOppsearchClass(ApexPages.StandardController stdController){}
 
    Public void soslDemo_method(){
       leadList = New List<Lead>();
   optyList = New List<Opportunity>();

        
   
   if(searchStr.length() > 1){
   String searchStr1 = '*'+searchStr+'*';
   String searchQuery = 'FIND \'' + searchStr1 + '\' IN ALL FIELDS RETURNING  Lead (Id,Name,Owner_Name__c,Email,metro__c,Last_Comment__c,statusname__c,Listing_MLS__c,last_update_date__c,date_entered_into_Lead_router__c,listing_amount__c,listing_agent__c,referral_fee__c,last_activity_subject__c),Opportunity(Id,Name,Account_Email__c,Opportunity_EMail__c,metro__c,Last_Comment__c,statusname__c,Owner_Name__c,last_update_date__c,date_entered_into_Lead_router__c,listing_amount__c,listing_agent__c,agent__c,referral_fee__c,last_activity_subject__c)';
   List<List <sObject>> searchList = search.query(searchQuery);
   leadList = ((List<Lead>)searchList[0]);
      optyList = ((List<Opportunity>)searchList[1]);
   if(leadList.size() == 0 && optyList.size() == 0){
       apexPages.addmessage(new apexpages.message(apexpages.severity.Error, 'Sorry, no results returned with matching string..'));
       return;
   }
   }
   else{
   apexPages.addmessage(new apexpages.message(apexpages.severity.Error, 'Please enter at least two characters..'));
   return;
   }
  }
}

And the Visualforce page:

<apex:page standardcontroller="Lead" extensions="AllOppsearchClass">
  <apex:form >
  <apex:inputText value="{!searchStr}"/>
    <apex:commandButton value="Search in Lead, Opportunity" action="{!soslDemo_method}"                reRender="lead,error,oppt" status="actStatusId"/>
    <apex:actionStatus id="actStatusId">
                <apex:facet name="start" >
                    <img src="/img/loading.gif"/>                    
                </apex:facet>
    </apex:actionStatus>
  </apex:form>
 
    <apex:outputPanel title="" id="error">
     <apex:pageMessages ></apex:pageMessages>
     </apex:outputPanel>

     <apex:pageBlock title="Opportunities" id="oppt">
    <apex:pageblockTable value="{!optyList}" var="opty">
     <apex:column headervalue="Name"><apex:outputLink value="/{!opty.ID}" target="_blank">{!opty.name}</apex:outputLink></apex:column>
     <apex:column value="{!opty.Account_Email__c}"/>
     <apex:column value="{!opty.Metro__c}"/>
     <apex:column value="{!opty.Owner_Name__c}"/>
     <apex:column value="{!opty.StatusName__c}"/>
     <apex:column value="{!opty.Date_Entered_Into_Lead_Router__c}"/>
     <apex:column value="{!opty.Last_Update_Date__c}"/>     
     <apex:column value="{!opty.Listing_Amount__c}"/>
     <apex:column value="{!opty.Listing_Agent__c}"/>
     <apex:column value="{!opty.Agent__c}"/>
     <apex:column value="{!opty.Referral_Fee__c}"/>
     <apex:column value="{!opty.Last_Comment__c}"/>


       </apex:pageblockTable>
    </apex:pageBlock>
 
    <apex:pageBlock title="Leads" id="lead">
    <apex:pageblockTable value="{!leadList }" var="lead">
     <apex:column headervalue="Name"><apex:outputLink value="/{!lead.ID}" target="_blank">{!lead.name}</apex:outputLink></apex:column>
     <apex:column value="{!lead.email}"/>
     <apex:column value="{!lead.Metro__c}"/>
     <apex:column value="{!lead.Owner_Name__c}"/>
     <apex:column value="{!lead.StatusName__c}"/>
     <apex:column value="{!lead.Date_Entered_Into_Lead_Router__c}"/>
     <apex:column value="{!lead.Last_Update_Date__c}"/>
     <apex:column value="{!lead.Listing_Amount__c}"/>
     <apex:column value="{!lead.Listing_MLS__c}"/>
     <apex:column value="{!lead.Listing_Agent__c}"/>
     <apex:column value="{!lead.Referral_Fee__c}"/>
     <apex:column value="{!lead.Last_Comment__c}"/>


 </apex:pageblockTable>
    </apex:pageBlock>
</apex:page>
I've got a method called from the after update of my opportunity trigger.  I'll paste it below.  Somewhere in here there's a too many soql queries error I get when updating a particular opportunity.  The debug log shows the error at the line with this map:

 
Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id, (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Customer_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Account WHERE Id IN: accIds]);





Here's the full code with that in it:
 
public static void createUpdateAssets(Map<ID, OpportunityLineItem> qualifiedOLIsMap){
        if(qualifiedOLIsMap.size() > 0){
          //get all the product ids from the OLIs
          Set<Id> prodIds = new Set<Id>();
          Set<Id> contractIds = new Set<Id>();
          Set<Id> accIds = new Set<Id>();
          Opportunity thisOpp;
          for(OpportunityLineItem oli : qualifiedOLIsMap.values()){
            if(thisOpp == null){
                thisOpp = oli.Opportunity;
            }
            if(oli.PriceBookEntry.Product2Id != null){
              prodIds.add(oli.PriceBookEntry.Product2Id);
            }
            if(oli.Opportunity.Contract__c != null){
              contractIds.add(oli.Opportunity.Contract__c);
            }
            if(oli.Opportunity.Contract__r.MLSA__c != null){
              contractIds.add(oli.Opportunity.Contract__r.MLSA__c);
            }
            accIds.add(oli.Opportunity.AccountId);
          }
          
          Map<Id, Product2> prodMap = new Map<Id, Product2>([SELECT Id, (SELECT Id, Name FROM Versions_Product_Junctions__r)
                                      FROM Product2 WHERE Id IN: prodIds]);
          
          //added Term_Date__c to SOQL query
          Opportunity test = [SELECT Id, RecordTypeId FROM Opportunity WHERE Id =: thisOpp.Id];
          Map<Id, Contract> contractMap = new Map<Id, Contract>([SELECT Id, StartDate, EndDate, Term_Date__c,
                                          (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Taxware_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Contract WHERE Id IN: contractIds]);
            
          for(Contact_Contract_Junction__c ccj : [SELECT Contact__c, Contract__c FROM Contact_Contract_Junction__c WHERE Contract__c IN: contractIds]){
            Set<Id> contactIds = contractContactMap.get(ccj.Contract__c);
            if(contactIds == null){
              contactIds = new Set<Id>(); 
            }
            contactIds.add(ccj.Contact__c);
            contractContactMap.put(ccj.Contract__c, contactIds);
          }
            
            List<OLIAssetWrapper> allOLIAssets = getOLIAssets(qualifiedOLIsMap, prodMap, contractMap);
            
            List<Customer_Asset__c> allAssetsToInsert = new List<Customer_Asset__c>();
            List<Customer_Asset__c> allAssetsToUpdate = new List<Customer_Asset__c>();
            Customer_Asset__c thisOLIAsset;
            for(OLIAssetWrapper oliAst: allOLIAssets){
                thisOLIasset = oliAst.ast;
                if(thisOLIasset.Id == null){
                    allAssetsToInsert.add(thisOLIasset);
                }else{
                    allAssetsToUpdate.add(thisOLIasset);
                }
            }
            
            update allAssetsToUpdate;
            //IR-1357
            insert allAssetsToInsert;
            Set<Id> newAssetIds = new Set<Id>();
            for(Customer_Asset__c thisAsset : allAssetsToInsert){
                newAssetIds.add(thisAsset.Id);
            }
            List<Customer_Asset__c> newAssets = new List<Customer_Asset__c>();
            newAssets = [SELECT Id, Account__c FROM Customer_Asset__c WHERE Id =: newAssetIds];
            if(test.RecordTypeId != '012f0000000D9H9'){
                List<Contract_Asset_Connection__c> conns = new List<Contract_Asset_Connection__c>();
                Contract_Asset_Connection__c thisConn;
                for(Customer_Asset__c thisAsset : newAssets){
                    thisConn = new Contract_Asset_Connection__c();
                    thisConn.Contract__c = thisOpp.Contract__c;
                    thisConn.Asset__c = thisAsset.Id;
                 thisConn.Account__c = thisAsset.Account__c;
                  if(thisConn != null)
                    conns.add(thisConn);
                }
                if(!conns.isEmpty() && test.RecordTypeId != '012i0000001AgIY' && test.RecordTypeId != '012i000000129Hi' && test.RecordTypeId != '012i0000001AgId'){
                    insert conns;
                }
            }   
            Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id, (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Customer_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Account WHERE Id IN: accIds]);
            
            Map<Id, Entitlement> entMap = new Map<Id, Entitlement>();
            for(OpportunityLineItem oli: qualifiedOLIsMap.values()){
            //if it's an update and the order type is renewal, update the Entitlement dates
                if(oli.Opportunity.Order_Type__c == Constants.ORDER_TYPE_RENEWAL || oli.Opportunity.Order_Type__c == Constants.ORDER_TYPE_ADD_ON || oli.Opportunity.Division__c == 'Taxify'){
                  if(oli.Opportunity.Entitlement__c != null && !entMap.containsKey(oli.Opportunity.Entitlement__c)){
                    Entitlement e = new Entitlement(Id = oli.Opportunity.Entitlement__c);
                    Date oldEntStart = oli.Opportunity.Entitlement__r.StartDate;
                    
                    if(oli.Opportunity.Contract_Paper_Type__c == 'New Paper'){
                        if(oldEntStart != null){//e.StartDate == null
                            e.StartDate = oldEntStart;
                        }else{
                            e.StartDate = oli.Opportunity.Contract__r.StartDate;
                        }
                        //changed EndDate to Term_Date
                        //e.EndDate = oli.Opportunity.Contract__r.Term_Date__c;
                        Account acc = accMap.get(oli.Opportunity.AccountId);
                        Date furthest = Date.today().addYears(-1);
                        if(acc != null && acc.Customer_Assets__r != null && acc.Customer_Assets__r.size() > 0){
                            for(Customer_Asset__c ass : acc.Customer_Assets__r){
                                if(ass.Term_End_Date__c > furthest){
                                    furthest = ass.Term_End_Date__c;
                                }
                            }
                            if(furthest > Date.today()){
                                e.EndDate = furthest;
                            }
                        }
                    }else if(oli.Opportunity.Contract_Paper_Type__c == 'Old Paper'){
                        Account acc = accMap.get(oli.Opportunity.AccountId);
                        Date furthest = Date.today().addYears(-1);
                        if(acc != null && acc.Customer_Assets__r != null && acc.Customer_Assets__r.size() > 0){
                            if(oldEntStart != null){//e.StartDate == null
                                e.StartDate = oldEntStart;
                            }else{
                                e.StartDate = oli.Opportunity.Contract__r.StartDate;
                            }
                            for(Customer_Asset__c ass : acc.Customer_Assets__r){
                                if(ass.Term_End_Date__c > furthest){
                                    furthest = ass.Term_End_Date__c;
                                }
                            }
                            if(furthest > Date.today()){
                                e.EndDate = furthest;
                            }
                        }
                    }
                    //check if finance grace period applies, update entitlement end date
                    Date latestGraceDate = null;
                    Customer_Asset__c thisAsset;
                    Account thisAcc = accMap.get(oli.Opportunity.AccountId);
                    integer numAssets = thisAcc.Customer_Assets__r.size();
                    for(integer i = 0; i < numAssets; i++){
                        thisAsset = thisAcc.Customer_Assets__r.get(i);
                        if(thisAsset.Finance_Grace_Period_Date__c > latestGraceDate){
                            latestGraceDate = thisAsset.Finance_Grace_Period_Date__c;
                        }
                    }
                    if(latestGraceDate > e.endDate){
                        e.endDate = latestGraceDate;
                    }
                    entMap.put(e.Id, e);
                  }
                }
            }
            update entMap.values();
            
            
            List<OpportunityLineItem> allOLIsToUpdate = new List<OpportunityLineItem>();
            Set<ID> opptyIDs = new Set<ID>();
            for(OLIAssetWrapper oliAst: allOLIAssets){
                OpportunityLineItem oli = oliAst.oli;
                oli.Asset__c = oliAst.ast.id;
                
                allOLIsToUpdate.add(oli);
                
                opptyIDs.add(oli.OpportunityID);
            }
            update allOLIsToUpdate;
            
            List<Opportunity> allOpptysToUpdate = new List<Opportunity>();
            for(ID opptyid : opptyIDs){
                Opportunity oppty = new Opportunity(id = opptyid);
                oppty.Fulfillment_Date__c = Date.Today();
                allOpptysToUpdate.add(oppty);
            }
            update allOpptysToUpdate;
        }
    }




I don't see any queries in for loops so I'm not sure how this can be re-written to eliminate the error.  Anyone see anything wrong here?  This is really old code that never really has a problem so this seems to be an edge case/bug in the code, I just can't find it.
I am trying to update the following 3 custom fields under my Member_Vendor_del__c custom object:

Vendor_ID__c
Member_Account_ID__c
Member_State__c

I have created the code below to update the Vendor_ID__c and Member_Account_ID__c

trigger VendorRepUpdateTrigger on Member_Vendor_del__c (before update) {
// Update the Vendor's ID, Member's ID, and Member's Physical State into the Member Vendor Record.    
    for (Member_Vendor_del__c u : trigger.new){
          if (u.Vendor_ID__c == null)
              u.Vendor_ID__c                 = u.Vendor__c;
              u.Member_Account_ID__c = u.Member__c;
  }
}


My issue is with getting Member_State__c to populate with the Physical State(API Field Name: BillingState) from the related member account. I have createdthe SOQL query below to return the string text value on the account but I keep getting the error "Illegal assignment from List to String"

// Update the Member's Physical State onto the Member Vendor Record.                       
     for (Member_Vendor_del__c u : trigger.new)
        if (u.Member_State__c == null)
                  u.Member_State__c = [Select BillingState
                                     From Account
                                     Where Account.Name = :u.Member__c];}


I can add .Id to the query and the error goes away but then the trigger wants to return a Salesforce ID rather than the 2 letter abbreviation for the State.

Question #1: What can I do to my SOQL query to return the text value rather than an ID?

Question #2: Can I add the SOQL query to the first part of the trigger? Something like:

trigger VendorRepUpdateTrigger on Member_Vendor_del__c (before update) {
// Update the Vendor's ID, Member's ID, and Member's Physical State into the Member Vendor Record.   
    for (Member_Vendor_del__c u : trigger.new){
          if (u.Vendor_ID__c == null)
              u.Vendor_ID__c         = u.Vendor__c;
              u.Member_Account_ID__c = u.Member__c;
              u.Member_State__c      = [Select Id, Account.BillingState
                                        From Account
                                           where Account_ID__c = :u.Member__c].Id;
 }
}
I am only getting the field names, not the data sent to my email.  Please help.

global class BatchSyncErrors implements Database.Batchable<sOBject>, Database.Stateful{
   
    global string excelHeader = 'ApexClassID,  CompletedDate ,  ExtendedStatus,  JobItemsProcessed,  JobType,  MethodName,  NumberOfErrors,  Status,  TotalJobItems \n';
    global string finalstr = '';
    
    //constructor
    global BatchSyncErrors(){
        finalstr = excelHeader;
    }
    //start method
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator('SELECT ApexClassID, CompletedDate, ExtendedStatus, JobItemsProcessed, JobType, MethodName, NumberOfErrors, Status, TotalJobItems FROM AsyncApexJob Limit 10');
    }
 
    //execute
        global void execute(Database.BatchableContext BC, List<sOBject> scope){

            string recordString;
        
            for(sOBject a: scope){
        
                // Type Cast sOBject to AsyncApexJob
                AsyncApexJob asyncApexJobRecord = (AsyncApexJob) a;
                   
                if(recordString == NULL){
                    recordString = AsyncApexJob.ApexClassID +',' + AsyncApexJob.CompletedDate +','+ AsyncApexJob.ExtendedStatus+',' + AsyncApexJob.JobItemsProcessed + ',' + AsyncApexJob.JobType +  ',' + AsyncApexJob.MethodName + ',' + AsyncApexJob.NumberOfErrors + ',' + AsyncApexJob.TotalJobItems + ','+ AsyncApexJob.JobItemsProcessed + ',' +AsyncApexJob.JobType + ',' + AsyncApexJob.TotalJobItems+ '\n';
                } else {
                    recordString += AsyncApexJob.ApexClassID +',' + AsyncApexJob.CompletedDate +','+ AsyncApexJob.ExtendedStatus+',' + AsyncApexJob.JobItemsProcessed + ',' + AsyncApexJob.JobType +  ',' + AsyncApexJob.MethodName + ',' + AsyncApexJob.NumberOfErrors + ',' + AsyncApexJob.TotalJobItems + ','+ AsyncApexJob.JobItemsProcessed + ',' +AsyncApexJob.JobType + ',' + AsyncApexJob.TotalJobItems+ '\n';
                }
        
            }
        
            finalstr += recordString;

}

    
    //finish
    global void finish (Database.BatchableContext BC){
       
        system.debug('**** Final String *** ' + finalstr);
        //TODO: pass this string to create CSV in your CSV Method.
         //   String csvContent = finalstr;
         //       Attachment attachment = new Attachment();
         //       attachment.Body = Blob.valueOf(csvContent);
         //       attachment.Name = 'csvFile.csv';
              
         //       insert attachment;
       
         //TODO: Create an generic method to send emails & pass this attachment.
         
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email,ExtendedStatus,JobType,ApexClassId,MethodName
      FROM AsyncApexJob WHERE Id =
      :BC.getJobId()];
            
        Messaging.Singleemailmessage mail = new Messaging.Singleemailmessage();
            mail.setToAddresses((new String[] {'all60388@adobe.com'}));
            //mail.setReplyTo('noreply@privatebudget.com');
            mail.setSenderDisplayName('Batch Class Errors');
            mail.setSubject('Batch Class Errors');
            mail.setBccSender(false);
            mail.setUseSignature(false);
            mail.setPlainTextBody(finalstr);
            system.debug('@@@@ sendEmail - mail : ' + mail);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
 
    }
}


In my email I get:


ApexClassID,  CompletedDate ,  ExtendedStatus,  JobItemsProcessed,  JobType,  MethodName,  NumberOfErrors,  Status,  TotalJobItems 
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems
ApexClassId,CompletedDate,ExtendedStatus,JobItemsProcessed,JobType,MethodName,NumberOfErrors,TotalJobItems,JobItemsProcessed,JobType,TotalJobItems


Thank you
Hi everybody, 
I've just acquired Salesforce Sales Cloud for my company and trying to customize some of the objects. 
I'm trying to understand how to create a similar one to Campaigns for this purpose: 
I have a list of boutiques (accounts) that have many different brands (customized objects), what i would like is to add a related list in both objects, interlinked to each other so I can "add a brand" to a specific account from the account, or "add account" to a specificic brand from the brand.
Exactly like campaigns I can see the members, and on each contact (but in this case it has to be account) the list of campaigns to which it participates. 

Any help?
I am attempting to match up users coming in from an external POST request to Salesforce users via a SOQL query of the name that returns a user record, then use the ID from the user record to insert a custom object record with a User Lookup field. However I am getting the following error: 
Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, User: id value of incorrect type: 005U0000003GvJKIA0: [User__c]
This error is being thrown because the ID needs to be 15 characters, but is, in practice, coming out as 18 characters. I have tried a few different methods of limiting the string to 15 chars, but to no avail. This is frustrating because it works just fine in the sandbox environment, it is only when deployed to production that this error comes up.

Methods I have tried:

1. No string correction
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String usrId = matchUsr.Id;
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

2. Substring the usrId string to (0,15) 
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String userMatch = matchUsr.Id;
            String usrId = userMatch.subString(0, 15);
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

3. Take one character from the ID string of the user record at a time (0-14), and add to new usrId string
// match names list to users and create records for each user
        finalCount = names.size();
        for (Integer j = 0; j < finalCount; j++) {
        
            User matchUsr = [SELECT Id, Name
                                FROM User
                                WHERE Name = :names[j]
                                LIMIT 1];
            String userMatch = matchUsr.Id;
            String usrId = '';
            for (Integer xc = 0; xc < 15; xc++) {        
                usrId += userMatch.subString(xc, xc+1);
            }
            
            indivs.add(new Late_Tasks_by_User__c(User__c=usrId,Dependent_Tasks__c=deps[j],Actual_Late_Tasks__c=lates[j],Date__c=datej));
            usrId = '';
            echoOut += names[j] + ', ';
        }

None of these have produced a working result. All three continue to return an 18 character string as the usrId variable. I have found several threads on this forum regarding this topic, but the only solutions that are listed with those questions are either syntax error with the specific code, or someone saying that you have to subString the ID. If anyone has any solutions or ideas beyond that, please let me know.

Thanks,
Joe
I attempted to delpoy code from the sandbox to production, but was met with an error that is persistent, and occurs when I run the test seperately from deployment. The test that fails is ABSI_TEST_MassTaskController, and it fails when it reaches the assertion that pageRef cannot be null. The exact error code is:
ABSI_TEST_MassTaskController.myUnitTest(), Details: System.Exception: Assertion Failed: Same value: null Class.ABSI_TEST_MassTaskController.myUnitTest: line 110, column 1

I am completely unable to edit this test code, nor can I edit the class that it should be testing, in fact they are completely absent from the sandbox environment.

The test class (ABSI_TEST_MassTaskController) is:
/******************************************************
 * Description      : Test Coverage for ABSI_MassTaskController (98%)
 * @author          : Malaka Silva
 * @since           : May 07, 2010  
 * Copyright 2010 ABSI. All rights reserved. 
 ******************************************************/
@isTest
private class ABSI_TEST_MassTaskController {

    static testMethod void myUnitTest() {
        Test.startTest();
        
        //Create Accounts
        Account account1 = new Account();
        account1.Name = 'Test_Account_01';
        insert account1;
        
        Account account2 = new Account();
        account2.Name = 'Test_Account_02';
        insert account2;        
        
        //Create Contacts
        Contact contact1 = new Contact();
        contact1.LastName = 'Test_Contact_01';
        insert contact1;
        
        Contact contact2 = new Contact();
        contact2.LastName = 'Test_Contact_01';
        insert contact2;
        
        //Get a profile from SFDC
        Profile profile = [select Id from Profile limit 1];
        
        //Create a user
        User user = new User();
        user.Username = 'Test_user_name@test.com';
        user.LastName = 'Test_last_name';
        user.ProfileId = profile.Id;
        user.Alias = 'tst';
        user.Email = 'Test_email@email.com';
        user.CommunityNickname = 'Test_nick_name';
        user.TimeZoneSidKey = 'GMT';
        user.LocaleSidKey = 'en_US';
        user.LanguageLocaleKey = 'en_US';
        user.EmailEncodingKey = 'ISO-8859-1';
        insert user;
        
        //Simulate the page for What Id
        PageReference pPageReference = Page.ABSI_Mass_Task_Action;
        pPageReference.getParameters().put('objIds',account1.Id+','+account2.Id);
        pPageReference.getParameters().put('retUrl','');
        Test.setCurrentPage(pPageReference);
        
        ABSI_MassTaskController controler = new ABSI_MassTaskController();
        System.assertEquals(controler.showWhoId, true);
        controler.getTableDisplayNames();
        controler.saveNew();
    controler.save();
    controler.back();

        //Simulate the page for Who Id
        pPageReference = Page.ABSI_Mass_Task_Action;
        pPageReference.getParameters().put('objIds',contact1.Id+','+contact2.Id);
        pPageReference.getParameters().put('retUrl','');
        Test.setCurrentPage(pPageReference);
        controler = new ABSI_MassTaskController();
        System.assertEquals(controler.showWhoId, false);
        controler.getTableDisplayNames();
        controler.getselReminderOptions();
        controler.saveNew();
    Pagereference pageRef = controler.save();
      System.assertEquals(pageRef, null);
    controler.back();
    
    controler.task.OwnerId = user.Id;
    controler.task.Subject = 'Test_Subject';
    controler.task.Status = 'Completed';
    controler.task.Priority = 'High';
    //Set the reminder
    controler.task.IsReminderSet = true;
    controler.contact.Birthdate = Date.today();
    controler.reminderTime = '23:30';
    //Send Email notification
    controler.sendNotificationEmailCheckBox = true;
    
    controler.saveNew();
    pageRef = controler.save();
      System.assertNotEquals(pageRef, null);
    
        Test.stopTest();
    }
}

The class it should be testing (ABSI_MassTaskController) is:
/******************************************************
 * Description      : Apex Controller for ABSI_Mass_Task_Action page
 * @author          : Malaka Silva
 * @since           : May 07, 2010  
 * Copyright 2010 ABSI. All rights reserved. 
 ******************************************************/
public with sharing class ABSI_MassTaskController {

    //Capture the values for the standard Task
    public Task task{set;get;}
    //Capture the value for the reminder date/time
    public Contact contact{set;get;}
    public String reminderTime{set;get;}
    //Other Form fields
    public Boolean sendNotificationEmailCheckBox{set;get;}
    public Map <Id,String> displayNames{set;get;}
    private Map <Id,Id> ownerIds;
    public Boolean showWhoId{set;get;}
    public Boolean showPage{set;get;}
    public Boolean assignToOwner{set;get;}
    //Page processing parameters
    private List <Selectoption> selReminderOptions;
    private String [] arrObjIds;
    private String objName = null;
    private Boolean saveStatus;
    private String objPrefix = null;
    
    /**
    * Constructor
    * Initalize the values & generate the object list(Names)
    */
    public ABSI_MassTaskController(){
        //Initalize the variables
        showPage = false;
        task = new Task();
        contact = new Contact();
        displayNames = new Map<Id,String>();
        ownerIds = new Map<Id,Id>();
        showWhoId = false;
        sendNotificationEmailCheckBox = false;
        saveStatus = false;
        assignToOwner = false;
        
        try{
            //Get the object ids passed as parameter
            Map<String, String> params = ApexPages.currentPage().getParameters();
            String strObjIds = params.get('objIds');
            arrObjIds = strObjIds.split(',');
            
            //Identify the object name/type and get the names
            if(arrObjIds != null && !arrObjIds.isEmpty()){
                //Find the object name
                Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe(); 
                Set<String> keyPrefixSet = gd.keySet();
                String tPrefix = arrObjIds[0].subString(0,3);
                
                for(String sObj : keyPrefixSet){
                    Schema.DescribeSObjectResult r =  gd.get(sObj).getDescribe();
                    if(tPrefix.equals(r.getKeyPrefix())){
                        objName = r.getName();
                        objPrefix = tPrefix;
                        break;
                    }
                }
                //Query the name for all the objects
                if(objName != null){
                    String strFieldName = 'name';
                    //Check if the object is a Contact or Lead
                    if(objName != 'Contact' && objName != 'Lead'){
                        showWhoId = true;
                    }
                    //Handle field that doesn't have a name field
                    if(objName == 'Case'){
                        strFieldName = 'CaseNumber';
                    }
                    
                    String strQuery = 'select id,OwnerId,' + strFieldName + ' from ' + objName + ' ';
                    Boolean bFirst = true;
                    for(String strObjId:arrObjIds){
                        if(bFirst){
                            strQuery += ' where Id in (\'';
                            bFirst = false;
                        }else{
                            strQuery += ',\'';
                        }
                        strQuery += String.escapeSingleQuotes(strObjId) + '\'';
                    }
                    strQuery += ')';
                    try{
                        SObject [] sfdcObjects = Database.query(strQuery);
                        //Generate the name list
                        for(SObject sfdcObject:sfdcObjects){
                            displayNames.put((Id)sfdcObject.get('id'),(String)sfdcObject.get(strFieldName));
                            ownerIds.put((Id)sfdcObject.get('id'), (Id)sfdcObject.get('OwnerId'));
                        }
                    }catch(Exception e){
                        strQuery = strQuery.replace(',' + strFieldName, ' ');
                        SObject [] sfdcObjects = Database.query(strQuery);
                        //Generate the Id list instead of name list
                        for(SObject sfdcObject:sfdcObjects){
                            displayNames.put((Id)sfdcObject.get('id'),(Id)sfdcObject.get('id'));
                        }
                    }
                }
            }
            showPage = true;
        }catch(Exception e){
            //Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, e.getMessage()));
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, 'Unexpected error has occured. Please try again later.'));
            showPage = false;
        }
        
    }
    public void assignToOwnerClick(){
        if(assignToOwner){
            assignToOwner = false;
        }else{
            assignToOwner = true;
        }
    }
    /**
    * Save the new task and keep the existing page
    */
    public void saveNew(){
        //Create the new task list
        List <Task> lTask = new List<Task>();
        //Capture the status for save()
        saveStatus = false;
        try{
            for(String strObjId:arrObjIds){
                Task taskNew = new Task();
                
                if(showWhoId){
                    //If the selected objests are not Contacts/Leads
                    taskNew.WhatId = strObjId;
                }else{
                    //If only Contacts/Leads
                    taskNew.WhoId = strObjId;
                }
                //Assign to the record owner based on selected options
                if(assignToOwner){
                    taskNew.OwnerId = ownerIds.get(strObjId);   
                }else{
                    taskNew.OwnerId = task.OwnerId;
                }
                taskNew.status = task.status;
                taskNew.subject = task.subject;
                taskNew.activityDate = task.activityDate;
                taskNew.priority = task.priority;
                taskNew.description = task.description;
                //If the reminder is set
                if(task.IsReminderSet){
                    taskNew.IsReminderSet = true;
                    String [] arrReminderTimes = reminderTime.split(':');
                    Time tmpTime = Time.newInstance(Integer.valueOf(arrReminderTimes[0]), Integer.valueOf(arrReminderTimes[1]), 0, 0);
                    Datetime reminderDateTime = Datetime.newInstance(contact.Birthdate, tmpTime);
                    taskNew.ReminderDateTime = reminderDateTime;
                }
                lTask.add(taskNew);
            }
            //Insert the new tasks to the SFDC Org
            insert lTask;
        }catch(Exception e){
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, e.getMessage()));
            return;
        }
        
        saveStatus = true;
        Apexpages.addMessage(new Apexpages.Message(Apexpages.Severity.CONFIRM, 'Task(s) successfully created.'));
        //Send email
        if(sendNotificationEmailCheckBox){
            sendMail(lTask);
        }
    }
    /**
    * Save the new task and to back to the previous page 
    * (If no errors)
    */
    public Pagereference save(){
        saveNew();
        if(saveStatus){
            return back();
        }
        return null;
    }   
    /**
    * Send email to the assigned engineer
    */
    private void sendMail(List <Task> lTask){
        try{
            //Set mail parameters
            //Query the assigned user
            User assignedUser = [Select u.Name, u.Email From User u where u.Id =: task.OwnerId];
            //Prepare the mail message
            Messaging.Singleemailmessage singleMail = new Messaging.Singleemailmessage();
            singleMail.setToAddresses(new String[]{ assignedUser.Email });
            singleMail.setSubject(task.subject);
            //Generate the HTML body and the plain text body
            String strText = 'To: ' + assignedUser.Name + '<br/><br/>';
            strText += System.Userinfo.getName() + ' has assigned you the following task(s):<br/><br/>';
            strText += 'Subject: ' + task.subject + '<br/><br/>';
            strText += objName + ':<br/>';
            
            String strPlainText = 'To: ' + assignedUser.Name + '/n/n';
            strPlainText += System.Userinfo.getName() + ' has assigned you the following task(s):/n/n';
            strPlainText += 'Subject: ' + task.subject + '/n/n';
            strPlainText += objName + ':/n';
            
            //Put the tasks with objects ids
            Map <Id,Id> mObjectTask = new Map<Id,Id>();
            for(Task newTasks:lTask){
                if(showWhoId){
                    mObjectTask.put(newTasks.WhatId, newTasks.Id);
                }else{
                    mObjectTask.put(newTasks.WhoId, newTasks.Id);
                }
            }
            for(Id displayKey:displayNames.keySet()){
                String displayName = displayNames.get(displayKey);
                Id taskId = mObjectTask.get(displayKey);
                strText += '-' + displayName;
                strText += ' (<a href=\'http://na1.salesforce.com/' + taskId  + '\'>';
                strText += 'http://na1.salesforce.com/' + taskId  + '</a>)';
                strText += '<br/>';
                
                strPlainText += '-' + displayName;
                strPlainText += ' (http://na1.salesforce.com/' + taskId  + ')';
                strPlainText += '/n';
            }
            strText += '<br/>Priority: ' + task.Priority + '<br/><br/>';
            
            strPlainText += '/nPriority: ' + task.Priority + '/n/n';
            
            //Set the test message to the mail
            singleMail.setHtmlBody(strText);
            singleMail.setPlainTextBody(strPlainText);
            //Send the mail
            Messaging.sendEmail(new Messaging.Singleemailmessage [] { singleMail });
        }catch(Exception e){
            //Capture if unexpected error occurs - such as Salesforce mail limit
            Apexpages.addMessage(new Apexpages.Message(ApexPages.severity.ERROR, 'Task(s) added. Mail not sent.'));
        }   
    }
    
    /**
    * Insert in the ReminderDate List the Time : Hours:Min
    */ 
    public List<SelectOption> getselReminderOptions(){
        selReminderOptions = new List<SelectOption>();
        String val = '' ; 
        for (Integer i = 0 ; i < 24 ; i++){
            // Draw the options to add to the reminder picklist 
            val = i+':'+'00';           
            selReminderOptions.add(new SelectOption(val,val));
            val = i+':'+'30';
            selReminderOptions.add(new SelectOption(val,val));
        }
        return selReminderOptions;    
    } 
    /**
    * Go to the previous page
    */
    public Pagereference back(){
        Pagereference pageRef = new Pagereference('/' + objPrefix);
        pageRef.setRedirect(true);
        return pageRef;
    }
    /**
    * Display the selected object names in front end
    */
    public List <String> getTableDisplayNames(){
        List <String> rtnList = new List<String>();
        
        for(String displayName:displayNames.values()){
            rtnList.add('-' + displayName);
        }
        return rtnList;
    }    
    
}

After searching this forum, I was only able to find one reference to this issue, and the suggested solution was to edit the test code. I am unable to deploy any code to production, and so far I have been unsuccessful in finding any documentation on successfully solving the issue here or on third party forums like StackExchange. Any suggestions are welcome.

Thanks,

Joe