Apex Trigger to Update Lookup Field (Contact) - triggers

Need some advise on how to populate a lookup field (contact) via apex trigger
I've created a lookup field called Contact__c on Idea object.
I would like to populate the Contact__c with the createdby User if it was originated from the web (CreatedBy.Contact.Account.Name == "Web Ideas") and leave it empty for internal idea creation.
I have read up and created the following trigger and was able to save and run. However, upon saving the idea record, i am getting an error : UpdateContactonComplaints: data changed by trigger for field Contact: id value of incorrect type: 005N0000000l9iMIAQ
trigger UpdateContactonComplaints on Idea (before insert, before Update) {
list<id> oid = new list<id>();
for(Idea o: trigger.new){
oid.add(o.id);
}
map<id, Idea> ExtendU = new map<id, Idea>(
[select CreatedbyID from Idea where id in: oid]);
for(Idea o: trigger.new){
o.Contact__c = ExtendU.get(o.id).CreatedbyID;
}
}

In the Trigger, the user id(id of the User who created the idea) is assigned to Contact custom lookup field).
So, it throws an error, data changed by trigger for field Contact: id value of incorrect type:

Related

How to merge two leads using an apex Trigger

I'm new to salesforce and I'm trying to learn more. Currently I'm stuck at a point where I don't know what to do further. Kindly point me in the right direction. Any help is appreciated.
So what im trying to do is to compare lastnames to find duplicates when the record is being created and if a duplicate is found then instead of creating it as a new record it should be merged with existing record.
So to achieve the task I have wrote the following trigger handler:
public class LeadTriggerHandler {
public static void duplicateMerge(){
List<Lead> leadList = [SELECT Id,Name, Email, Phone, FirstName, LastName FROM Lead];
List<Lead> leadTrigger = Trigger.new;
for(Lead leadVarTrigger : leadTrigger){
for(Lead leadVar : leadList){
//System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName);
if(leadVarTrigger.LastName == leadVar.LastName)
{
//System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName);
//leadVarTrigger.addError('This is a duplicate record');
Database.merge(leadVar, leadVarTrigger);
System.debug('Trigger Successful');
}
}
}
}
}
the following is my trigger:
trigger LeadTrigger on Lead (after insert) {
if(Trigger.isafter && Trigger.isInsert)
{
LeadTriggerHandler.duplicateMerge();
}
}
And when I try with after insert i get the following error:
LeadTrigger: execution of AfterInsert caused by: System.DmlException: Merge failed. First exception on row 0 with id 00Q5j00000ENUGVEA5; first error: INVALID_FIELD_FOR_INSERT_UPDATE, Unable to create/update fields: Name. Please check the security settings of this field and verify that it is read/write for your profile or permission set.: [Name] Class.LeadTriggerHandler.duplicateMerge: line 18, column 1 Trigger.LeadTrigger: line 5, column 1
And if i try with before trigger i get the following error for the same code:
LeadTrigger: execution of BeforeInsert caused by: System.StringException: Invalid id at index 0: null External entry point Trigger.LeadTrigger: line 5, column 1
Actually, according to your code, you are allowing the record to be created and saved to the database by using after insert. Your before insert failed because your handler class is referencing an Id, however, if you use before logic, the record isn't saved to the database yet, meaning it doesn't have an Id. With that being said, let's try the following. :)
The Trigger (Best practice is to have one trigger with all events):
trigger TestTrigger on Lead (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
if(Trigger.isafter && Trigger.isInsert)
{
//Can't conduct DML operations with trigger.new or trigger.old
//So we will create a set and send this to our handler class
Set<Id> leadIds = Trigger.newMap.keySet();
LeadTriggerHandler.duplicateMerge(leadIds);
}
}
The Handler Class:
public class LeadTriggerHandler {
public static void duplicateMerge(Set<Id> idsFromTrigger){
//Querying the database for the records created during the trigger
List<Lead> leadTrigger = [SELECT Id, LastName FROM Lead WHERE Id IN: idsFromTrigger];
List<String> lastNames = new List<String>();
//This set is important as it prevents duplicates in our dml call later on
Set<Lead> deDupedLeads = new Set<Lead>();
List<Lead> leadsToDelete = new List<Lead>();
for (Lead l : leadTrigger){
//getting all of the Last Names of the records from the trigger
lastNames.add(l.lastName);
}
//We are querying the database for records that have the same last name as
//the records that were created during our trigger
List<Lead> leadList = [SELECT Id, Name, Email, Phone, FirstName, LastName FROM Lead WHERE LastName IN: lastNames];
for(Lead leadInTrigger : leadTrigger){
for(Lead leadInList : leadList){
if(leadInTrigger.LastName == leadInList.LastName){
//if the lead from the trigger has the same last name as a lead that
//already exists, add it to our set
deDupedLeads.add(leadInTrigger);
}
}
}
//add all duplicate leads from our set to our list and delete them
leadsToDelete.addAll(deDupedLeads);
delete leadsToDelete;
}
}
This handler has been bulkified in two ways, we removed the DML operation out of the loop and the code is able to process a scenario where someone mass inserts 1000s of leads at a time. Plus, rather than querying every lead record in your database, we only query for records that have the same last name as the records created during the insert operation. We advise using something more unique than LastName like Email or Phone as many people/leads can have the same Last Name. Hope this helps and have a blessed one.

Copy Product Price into a Custom Field Object using APEX Trigger in Salesforce

Trying to just copy the Cost_Price__c field of a product into a custom object when it is updated (if possible inserted too) using an APEX trigger.
I'm so close but the error I am getting at the moment is: Illegal assignment from PricebookEntry to String
trigger updateAccount on Account (after update) {
for (Account oAccount : trigger.new) {
//create variable to store product ID
string productId = oAccount.Product__c;
//SQL statement to lookup price of product using productID
PricebookEntry sqlResult = [SELECT Cost_Price__c
FROM PricebookEntry
WHERE Product2Id =: productId];
//save the returned SQL result inside the field of Industry - Illegal assignment from PricebookEntry to String
oAccount.Industry = sqlResult;
}
}
Am I right in thinking it's because its returning a collective group of results from the SOQL call? I've tried using the sqlResult[0] which still doesn't seem to work.
The Illegal Assignmnet because you are assigning a whole Object i.e PriceBook Entry to a string type of field i.e Industry on Account.
Please use the following code for assignment.
oAccount.Industry = sqlResult[0].Cost_Price__c;
Please mark the answer if this works for you.
Thanks,
Tushar

Trigger to prevent User From Adding more than one product to an opportunity

So i have written a trigger to prevent user from entering more than one opportunity product to the same opportunity, but the problem is when he adds more than one opportunity product at the same time, my trigger does not fire, salesforce takes it as one product.
What can i add to my trigger to fix this ?
My trigger :
trigger OpportunityLineItemBeforeInsert on OpportunityLineItem (before insert) {
Set<Id>opportunityIds = new Set<Id>();
// get all parent IDs
for(OpportunityLineItem i : trigger.new)
{
opportunityIds.add(i.OpportunityId);
}
// query for related Olis (Opportunity Line Items)
Map<Id, Opportunity> opps = new Map<Id, Opportunity>([SELECT ID,
(SELECT ID
FROM OpportunityLineItems)
FROM Opportunity
WHERE ID IN :opportunityIds]);
for(OpportunityLineItem i : trigger.new)
{
if(opps.get(i.OpportunityId).OpportunityLineItems.size()>0)
{
i.addError('Your Message');
}
}
}
Thank you in advance.
I would probably ignore anything related to the Oppty.
You want only one product created, so on creation, either the number of LI is 0 and you can create exactly one, or it' snot 0 and you can't create any.
I would just create a rollup field on the Oppty, count the products. If the count != 0, then fail the validation. If count = 0, then count the Olis in trigger.new and if !=1, fail.
Instead of writing code to do this you should instead create a field on products that stores the id of the parent opportunity, make that field unique, and populate the value via workflow or process builder with the id of the parent opportunity. That way if a second product gets added the unique constraint would fire and prevent the record from being inserted.
Another option would be to create a rollup on opportunity to count the number of opportunity products, then add a validation rule that show an error if the number of products > 1. The advantage of doing it this way is that you get to set the error message as opposed to the generic duplicate error message with the first option.

Apex code to update new Opportunity with values from related object

What would be the proper method to update a list of new Opportunities with the values from a related record.
for (Opportunity opps:Trigger.new){
[SELECT Id, CorpOwner__r, Contact__r,(SELECT Id, AccountLocation from Account)]
o.CorpOwner__r =Account.Id; o.AccountLocation = opps.Account.AccountLocation;
insert opps
Do you call the lookup fields by the __r suffix? Could you do a before insert operation and still look up the Opportunity.CorpOwner__r relationship to values in the CorpOwner__r Account record, or does that relationship not exist since the record has not been created? What would be a proper batchified way to go about it?
Here's a possibility that demonstrates a number of concepts:
trigger UpdateOpptyWithAccountInfo on Opportunity (before insert) {
// Keep this SOQL query out of the FOR loop for better efficiency/batching
Map<Id, Account> relatedAccounts = new Map<Id, Account>(
[SELECT Id, AccountLocation__c
FROM Account
WHERE Id IN
(SELECT AccountId
FROM Opportunity
WHERE Id = :Trigger.new)
]
);
for (Opportunity o : Trigger.new) {
/* Find each opportunity's Account in the map we queried for earlier
* Note: there's probably a more efficient way to use a Map of Opportunity IDs to Account objects...
* This works fine and could be more readable.
*/
for (Account a : relatedAccounts.values()) {
if (a.Id == o.AccountId) {
// Once you've found the account related to this opportunity, update the values
o.CorpOwner__c = a.Id;
o.AccountLocation__c = a.AccountLocation__c;
}
}
}
// We're still inside an `insert` trigger, so no need to call `insert` again.
// The new fields will be inserted along with everything else.
}
If you're establishing the relationship between objects, use the __c suffix:
o.CorpOwner__c = a.Id; // Associate Account `a` as Opportunity `o`'s CorpOwner
If you're looking up a field on a related object, then you would use __r:
System.debug(o.CorpOwner__r.Name); // Print Opportunity `o`'s CorpOwner's name

Trigger to update a custom lookup field on opportunity

I created a custom object XtendedUser which has an id and Name.
I created a custom lookupfield on Opportunity called "XtendedUser__c" which links the opportunity to the corresponding XtendedUser record.
Now I made it so that the name of an opportunityowner corresponds to the name of an XtendedUser-record, so I want the trigger to autopopulate the custom lookup field "XtendedUser__c" on the opportunity with the id of the corresponding XtendedUser-record of which the name matches the name of the opportunityowner.
I never wrote a trigger, always worked with workflows and fieldupdates, but I've got to make this work. So if you could please help me with this? I would be extremely greatfull!
Thanks in advance
You should use a map to link the records and retrieve the value before the insert of a new record and before the update of an existing record. This technique will also allow you to bulk update all your records. It should be something like:
trigger ExtendedUser__c on Opportunity (before insert, before Update) {
list<id> oid = new list<id>();
for(opportunity o: trigger.new){
oid.add(o.id);
}
map<id, ExtendedUser__c> ExtendU = new map<id, ExtendedUser__c>(
[select name from ExtendedUser__c where id in: oid]);
for(opportunity o: trigger.new){
o.name = ExtendU.get(o.id).name;
}
}