Salesforce Apex - Existing Contact used to create new lead - salesforce

I would like to create after update APEX for salesforce that can take a contact and recreate it as a Lead when a field on the contact is checked true. Any help would be appreciated.
Yeah so I think i need to make a list of the contacts that need to be moved into the lead. I'm forgetting the format to grab the fields from the contact so i can map them into the lead.
public void createLead_Update(List<Contact> oldContacts, List<Contact> newContacts) {
System.debug('createLead_Update: entering trigger');
List<ID> createNewLead = new List<ID>();
Lead lead = new Lead();
Contact aContact = newContacts[i];
for (integer i=0; i<newContacts.size(); i++) {
// find contacts where the create lead checkbox is checked.
// on update, we care if the value is changed
Contact newValues = newContacts[i];
Contact oldValues = oldContacts[i];
if (newValues.createlead__c != oldValues.createlead__c) {
createNewLead.add(new Lead(
lead.firstName = aContact.firstName));
}
insert new lead
}
System.debug('createLead_Update: exiting trigger');
}

List<Lead> newLeadsList= new List<Lead>();
for (integer i=0; i<newContacts.size(); i++) {
if (newContacts[i].createlead__c != oldContacts[i].createlead__c && newContacts[i].createlead__c ) {
newLeadsList.add(new Lead(lead.firstName = newContacts[i].firstName));
}
}
insert newLeadsList;

Related

Apex trigger to display the sum of value from child to parent account

I have created a trigger on contact object that suppose to sum the amount value from the contact salary fields of the contact object and display the sum in their parent account object Contacts salary. but nothing is getting populated can someone help
When AFTER_INSERT {
for (Contact con : Trigger.new) {
if (String.isBlank(con.AccountId)) {
//Write automation logic here
String accountId = con.AccountId;
List<AggregateResult> results = [Select AccountId, COUNT(Id) ,Sum(Contact_Salary__c) totalSalary FROM CONTACT WHERE AccountId = :accountId GROUP BY AccountID];
for (AggregateResult result : results) {
String accId = String.valueOf(result.get('AccountId'));
System.debug(accId);
Integer totalSalary = Integer.valueOf(result.get('totalSalary'));
Account acc = new Account(Id=accId, Contacts_Salary__c = totalSalary);
update acc;
}
}
}
}
I see that you have given the wrong if check -
if (String.isBlank(con.AccountId)) {
use below one
if(String.isNotBlank(con.AccountId)) {
Also, I suggest please optimize your code as it is not Bulkified, as you are doing DMLs in for loop, that will cause you problem in large amount of data and you will hit the org's Governor limit.
Thanks.

Converting Trigger to Batch Apex: Help needed to make the code work

If possible, could anyone please direct me towards the right direction? The second code (Batch Apex) is just not compiling. Currently the error is,
Error: Compile Error: Invalid type: updateContactOnEmailOptOutChangeScheduler
at line 63 column 73
But I think there are other issues to that I can't seem to make it right.
On a contact update, the trigger updates all duplicate contacts with new value of "Email Opt Out" if this field has been updated. Also, the trigger only updates duplicate contacts that have a HasOptedOutOfEmail value different from one being updated. Now my task is to convert this requirement from trigger (that was written and tested by my colleague) to Batch Apex. First is the original trigger. Second is the code I just wrote in the format of batch apex.
Original Trigger Code
trigger updateContactOnEmailOptOutChange on Contac​t (after update) { ​ ​
//Initialize lists and maps
List<Contact> duplicateContacts = new List<Con​tact>();
Map<String, Contact> contactEmailMap = new Map​<String, Contact>();
Map<Id, Contact> contactIdMap = new Map<Id, Co​ntact>();
//Build a map with contacts to update. Only se​lect the ones that have a different "Email Opt Out​" value from the contact being updated.
for (Integer i = 0; i < Trigger.new.size(); i+​+) {
if (Trigger.old[i].HasOptedOutOfEmail != T​rigger.new[i].HasOptedOutOfEmail) {
contactEmailMap.put(Trigger.old[i].ema​il, Trigger.new[i]);
contactIdMap.put(Trigger.old[i].id, Tr​igger.new[i]);
}
}
//Only go through this process if "Email Opt O​ut" (HasOptedOutofEmail) was updated.
If (contactIdMap.size()>0) {
//Query the database and look for all cont​acts with a duplicate email address (same email as​ the contact currently being updated).
for (Contact dupContact : [SELECT Id, Name​, Email, HasOptedOutOfEmail
FROM Contact
WHERE Email IN ​: contactEmailMap.KeySet()
AND Id NOT IN :​ contactIdMap.KeySet()]) {
Contact contact = contactEmailMap.get(​dupContact.Email);
If (dupContact.HasOptedOutOfEmail <> c​ontact.HasOptedOutOfEmail) {
dupContact.HasOptedOutOfEmail = co​ntact.HasOptedOutOfEmail;
duplicateContacts.add(dupContact);
}
}
//If any duplicate contacts were found, up​date all duplicate contacts with the new HasOptedO​utOfEmail value.
If (duplicateContacts.size()>0) update dupl​icateContacts;
}
}
BATCH APEX
global class updateContactOnEmailOptOutChange implements Database.Batchable<sObject>
{
global string query;
global updateContactOnEmailOptOutChange()
{
query = 'SELECT id,Name, Email, HasOptedOutofEmail from Contact where HasOptedOutofEmail=true';
}
global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List <sObject> duplicateContacts)
{
Map<String, Contact> contactEmailMap = new Map<String, Contact>();
Map <Id, Contact> contactIdMap = new Map<Id, Contact>();
// Build a map with contacts to update. Only select the ones that have a different "Email Opt Out" value from the contact being updated.
if(trigger.isUpdate){
for(Integer i=0; i<Trigger.new.size();i++)
{
if(Trigger.old[i].HasOptedOutOfEmail != Trigger.new[i].HasOptedOutOfEmail)
{
contactEmailMap.put(Trigger.old[i].email, Trigger.new[i]);
contactIdMap.put(Trigger.old[i].id, Trigger.new[i]);
}
}
if(contactidMap.size()>0)
{
//Query the database and look for all contacts with a duplicate email address(same email as the contact currently being updated)
for (Contact dupContact: [SELECT Id, Name, Email, HasOptedOutofEmail
FROM Contact
WHERE Email IN: contactEmailMap.KeySet()
AND Id NOT IN: contactIdMap.KeySet()])
{
Contact contact=contactEmailMap.get(dupContact.Email);
If(dupContact.HasOptedOutOfEmail <> contact.HasOptedOutOfEmail)
{
dupContact.HasOptedOutOfEmail = contact.HasOptedOutOfEmail;
duplicateContacts.add(dupContact);
}
}
// if any duplicate contacts were found, update all duplicate contacts with the new HasOptedOutOFEmail value.
If(duplicateContacts.size<>0) update duplicateContacts;
}
}
}
//The batch process has completed successfully. Schedule next batch.
global void finish(Database.BatchableContext BC){
// //Build the system time of now + 300 seconds to schedule the batch apex.
Datetime sysTime = System.now();
sysTime = sysTime.addSeconds(300);
String chron_exp=''+sysTime.second()+''+sysTime.minute()+​''+sysTime.hour()+''+sysTime.day()+''+sysTime.mont​h()+'?'+sysTime.year();
system.debug(chron_exp);
updateContactOnEmailOptOutChangeScheduler scheduleFieldUpdate = new updateContactOnEmailOptOutChangeScheduler();
//Schedule the next job, and give it the system time so name is unique
System.schedule('New Email Update Job'+sysTime.getTime(),chron_exp,scheduleFieldUpda​te);
}
}
Your batch apex is including references to the Trigger class that is only valid inside a trigger. The compile error message says there is an invalid type on line 63. Check the line numbers but that likely points to the reference to Trigger

Salesforce Account Owner Name on Case Trigger failing

I wrote a trigger that places the Account Owner Name on a Case created for that Account. It works and performs also in my bulk test of 200. Here is the code:
trigger CaseBeforeInsertUpdate on Case (before insert, before update) {
Set<Id> accountIds = new Set<Id>();
Set<Id> accountOwnerIds = new Set<Id>();
for (Case c : Trigger.new) {
if(c.AccountId != null) {
accountIds.add(c.AccountId);
}
}
Map<Id,Account> accountMap = new Map<Id, Account>([select Id, OwnerId from Account where Id IN :accountIds]);
for (Account a : accountMap.values()) {
if(a.OwnerId != null) {
accountOwnerIds.add(a.OwnerId);
}
}
Map<Id, User> userMap = new Map<Id,User>([select Name from User where Id IN :accountOwnerIds]);
if(userMap.size() > 0) {
for(Case c: Trigger.new) {
c.MerchantOwner__c = userMap.get(accountMap.get(c.AccountId).OwnerId).name;
}
}
}
By accident I discovered a bug and I can't figure out what is going wrong. If I go to a Case listview (i.e. My open cases) and select multiple Cases and Close them, I get an error: System.NullPointerException: Attempt to de-reference a null object for the row that updates the MerchantOwner field. When I mass close cases in my testclass everything works fine..
My best guess is I'm trying to do this for a Case that has no Account attached to it but as far as I see I try to not have these Cases updated by not adding them to the accountIds Set in the first place.
Does anyone know what I am doing wrong? Any help would be greatly appreciated.
I would change the following For loop from:
for(Case c: Trigger.new) {
c.MerchantOwner__c = userMap.get(accountMap.get(c.AccountId).OwnerId).name;
}
To
for(Case c: Trigger.new) {
if (c.AccountId != null // Make sure there is an Account linked to the Case
&& accountMap.ContainsKey(c.AccountId) // Make sure our Account query captured it
&& accountMap.get(c.AccountId).OwnerId != null // Make sure that account has an owner
&& usermap.ContainsKey(accountMap.get(c.AccountId).Ownerid) // Finally make sure our User query found the owner
){
c.MerchantOwner__c = userMap.get(accountMap.get(c.AccountId).OwnerId).name;
}
}

FIELD_CUSTOM_VALIDATION_EXCEPTION

I am writing a test class for a trigger. But i am not able to run it properly it only contain 68%.
The error is
System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, This part is not forecastable.
#isTest
private class TestTriggers
{
static testMethod void testService()
{
//Insert part
list<Opportunity> Opportunity = new list<Opportunity>();
Opportunity = [Select id from Opportunity];
list<Product2> Product = new list<Product2>();
Product = [Select id from Product2];
Part__c p = new Part__c(Stage__c = 'idea',Product__c=Product[0].id,Opportunity__c=Opportunity[0].id);
insert p;
//Update part
list<part__c> partlist = new list<part__c>();
partlist = [Select Stage__c from part__c where Stage__c = 'idea'];
partlist[0].Stage__c = 'update';
update partlist;/* */
}
}
thanks
Anuraj
There is a validation rule on the Part object. To view the validation rule(s), go to Setup > Create > Objects > Part > Validation Rules.
You'll need to modify your code to create a Part__c record that complies with the validation rules.

How to write testcase for trigger?

I have a trigger which copies the billing street address from the related Account to the other streets address on the related Contact. I wrote this trigger from reading materials online is this correct? Is there better way to write it?
Public class iTestClass {
public static testmethod void test()
{
Contact objContact1;
Contact objContact2;
objContact1 = New Contact();
objContact1.OtherStreet = '123 lane';
objContact1.OtherCity = 'Washington';
objContact1.OtherState = 'OR';
objContact1.OtherCountry = 'USA';
objContact1.OtherPostalCode = '12122';
objContact2 = New Contact();
objContact2.OtherStreet = '232 st.';
objContact2.OtherCity = 'cleveland';
objContact2.OtherState = 'OH';
objContact2.OtherCountry = 'USA';
objContact2.OtherPostalCode = '166030';
}
}
You're on the right lines, but a) you're not inserting the contact records, and b) you need to insert an account first, then set the account ID on those contacts before you insert them.
// before creating the contacts create an account
Account sAcct = new Account();
sAcct.Name = 'Test Account';
sAcct.BillingStreet = '1 Some Street'; // I forget the name of the field!
// etc.
insert sAcct;
// then on your contacts do this:
objContact1.Account = sAcct.Id;
// then insert them at the end to fire the trigger
insert objContact1;

Resources