Trying to write a trigger on contentdocumentlink, which fires on insert and check a check box to true on account, but code doesn't seems to work.
Also getting compile error.
public with sharing class contentDocumentLinkTriggerHandler {
public static void processOnInsert(list<ContentDocumentLink> newList) {
list<ContentDocumentLink> contentList = new list<ContentDocumentLink>();
set<id> accId = new set<id>();
map<id,list<ContentDocumentLink>> parentContentMap = new map<id,list<ContentDocumentLink>>();
set<id> contId = new set<id>();
for(ContentDocumentLink nt : newList){
if(nt.linkedentityid.getSobjectType() == Account.SObjectType){
accId.add(nt.linkedentityid);
}
if(nt.linkedentityid.getSobjectType() == Contact.SObjectType){
contId.add(nt.linkedentityid);
}
if(parentContentMap.containsKey(nt.linkedentityid))
parentContentMap.get(nt.linkedentityid).add(nt);
else
parentContentMap.put(nt.linkedentityid,new list<ContentDocumentLink>{nt});
}
if(!accId.isEmpty()){
//login for acc
for(Account acc : [SELECT id,checkFiles__c FROM Account WHERE id IN : accId]){
if(parentContentMap.containsKey(acc.id)){
acc.checkFiles__c == true;// compile error
}
}
}
}
}
Related
Using an Apex Trigger, I am attempting to update the Company field, during the creation of a new lead, with the value which the user selected from a custom lookup field on the same object. So, the user clicks new on the lead tab to create a new lead. enters the first name, last name and other details. Instead of typing in the company name, the user then searches for the company name in the lookup field, compName__c, and selects it from the list. What I would like to accomplish is when the the user clicks save, the value in the compName field is copied to the Company field on the new record, then the new record is created.
Here is what I have done thus far;...
trigger UpdateLeadCompany on Lead (before insert) {
Set<Id> AN = New Set<Id>();
For (Lead LeadComp : Trigger.New)
{
IF(LeadComp.compName__c != null)
{
AN.add(LeadComp.compName__c);
}
}
Map<Id, Agency__c> y = [SELECT Name, compName__c FROM compName__c WHERE Id IN :AN];
For(Lead CompNameUpdate : Trigger.New)
{
Company a = y get(CompNameUpdate.compName__c);
IF(a != null)
{
CompNameUpdate = a.compName__c;
}
}
}
Updated
Then your code should be like -
trigger UpdateLeadCompany on Lead (before insert) {
Set<Id> AN = New Set<Id>();
for(Lead leadObj : Trigger.New) {
IF(leadObj.compName__c != null) {
AN.add(leadObj.compName__c);
}
}
Map<Id, compName__c> y = [SELECT Name, compName__c FROM compName__c WHERE Id IN :AN];
For(Lead leadObj : Trigger.New) {
compName__c a = y.get(leadObj.compName__c);
IF(a != null) {
leadObj.Company = a.Name;
}
}
}
issue in re parenting, In this question i have to find the largest opportunity by amount and put into the Account lookup field which is working but when i am changing the account of an opportunity then it remains in the account look up field. can someone please correct it, if i am wrong
public class TopOpportunityClass{
public static boolean flag = true;
public static void onTopOpportunity(List<Opportunity> opport){
if(flag==true){
List<Opportunity> uptOpp = new List<Opportunity>();
Set<Id> accIds = new Set<Id>();
for(Opportunity opp : opport){
if(opp.AccountId != null){
accIds.add(opp.AccountId);
}
}
Map<Id, List<Opportunity>> accOpportMap = new Map<Id, List<Opportunity>>();
List<Account> accUpdateList = new List<Account>();
for(Opportunity obj : [SELECT id,name, amount,accountId
FROM Opportunity
WHERE accountId IN :accIds ORDER BY amount DESC nulls last]){
List<Opportunity> oppList;
if(accOpportMap.containsKey(obj.accountId)){
oppList = accOpportMap.get(obj.accountId);
}else{
oppList = new List<Opportunity>();
}
oppList.add(obj);
accOpportMap.put(obj.accountId, oppList);
}
for(Id accId : accOpportMap.keySet()){
if(accOpportMap.get(accId).size() > 1 ){
opportunity opp1 = new opportunity(id = accOpportMap.get(accId)[1].id , isTopOpportunityCheck__c = false);
uptOpp.add(opp1);
accUpdateList.add(new Account(id = accId, isTopOpportunity__c = accOpportMap.get(accId)[0].id));
opportunity opp = new opportunity(id = accOpportMap.get(accId)[0].id , isTopOpportunityCheck__c = true);
uptOpp.add(opp);
}else if(accOpportMap.get(accId).size() == 1 ){
accUpdateList.add(new Account(id = accId, isTopOpportunity__c = accOpportMap.get(accId)[0].id));
opportunity opp = new opportunity(id = accOpportMap.get(accId)[0].id , isTopOpportunityCheck__c = true);
uptOpp.add(opp);
}else if(accOpportMap.get(accId).size() == 0){
accUpdateList.add(new Account(isTopOpportunity__c = NULL, id = NULL));
}
flag = false;
}
if(!accUpdateList.isEmpty()){
update accUpdateList;
update uptOpp;
}
}
}
}
//trigger
trigger OpportunityTrigger on Opportunity (after insert, after update){
if(Trigger.isAfter){
TopOpportunityClass.onTopOpportunity(Trigger.new);
}
}
You are running after update, so you're getting the new values in each sObject. If you want to affect the old Account assigned to some reparented Opportunity, you need to also look at the value in Trigger.old or Trigger.oldMap.
The way to do this would be to add a check here:
for(Opportunity opp : opport){
if(opp.AccountId != null){
accIds.add(opp.AccountId);
}
}
to find a reparented Opportunity (opp.AccountId != Trigger.oldMap.get(opp.Id).AccountId) and affect that Account as well.
There's a separate issue further below: this logical branch is clearly wrong.
}else if(accOpportMap.get(accId).size() == 0){
accUpdateList.add(new Account(isTopOpportunity__c = NULL, id = NULL));
}
You can't update an Account whose Id is null, and that will produce an exception.
You also need to reset flag to true after performing updates, or your trigger will have some very confusing and difficult-to-debug edge cases when multiple DML operations are performed in a single transaction.
So i have written a trigger that works perfectly fine and does exactly what i want it to do, but the thing is that it does the job on all the account, and i want it to work only on one record type of the accounts.
Can someone tell me what to add to my trigger so i can make it work only on one record type?
The following is my handler class:
public class AP03_OpportunityLineItem {
public static void preventmultipleOpportunityLineItems(List<OpportunityLineItem> listOppLineItems){
Set<Id>opportunityIds = new Set<Id>();
// get all parent IDs
for(OpportunityLineItem oli : listOppLineItems)
{
//Condition to pick certain records
opportunityIds.add(oli.OpportunityId);
}
// query for related Opportunity Line Items
Map<Id, Opportunity> mapOpportunities = new Map<Id, Opportunity>([SELECT ID,
(SELECT ID
FROM OpportunityLineItems)
FROM Opportunity
WHERE ID IN :opportunityIds]);
// opp counter of new records
Map<Id, Integer> mapOppCounter = new Map<Id, Integer>();
for(OpportunityLineItem oli : listOppLineItems)
{
if(mapOppCounter.containsKey(oli.OpportunityId))
{
mapOppCounter.put(oli.OpportunityId, mapOppCounter.get(oli.OpportunityId)+1);
}
else
{
mapOppCounter.put(oli.OpportunityId, 1);
}
}
//loop to add error if condition violated
for(OpportunityLineItem olitems : listOppLineItems)
{
if(mapOpportunities.get(olitems.OpportunityId).OpportunityLineItems.size()+mapOppCounter.get(olitems.OpportunityId)>1 || olitems.Quantity > 1)
{
olitems.addError('Ce client peut seulement loué un seul véhicule.');
}
}
}
}
The following is my PAD class:
public class PAD
{
public static String bypassTrigger; //List of bypassed triggers
public static final User user;
static {
user = [Select BypassApex__c
from User
where Id=:UserInfo.getUserId()];
bypassTrigger = ';'+ user.BypassApex__c+ ';';
System.debug('>>>>> PAD constructor : END <<<<<'+bypassTrigger);
}
/**
* Method used for the class PAD
* #param c object of type JonctionServicePrestation__c
* #return boolean
*/
public static boolean canTrigger(string Name){
return (bypassTrigger.indexof(';' + Name + ';') == -1);
}
}
And the following is my Trigger:
trigger OpportunityLineItemBeforeInsert on OpportunityLineItem (before insert) {
if(PAD.canTrigger('AP03_OpportunityLineItem')){
AP03_OpportunityLineItem.preventmultipleOpportunityLineItems(Trigger.new);
}
}
You would need to loop through your opportunitiesproducts and build a list of opportunity Id, then query the Opportunity whose Accounts in the list with the record type you want to match, and build a set of the ids that match the specified record type then check if the set contains the accountId of the opportunity being process to know if the skip or process it.
Set<Id> recordTypeOpp = new Set<ID>();
SET<Id> opportunityIds = new Set<Id>();
Id recordTypeIdYouWant = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Record Type Name').getRecordTypeId();
for(OpportunityLineItem item : listOppLineItems){
opportunityIds.add(item.OpportunityId);
}
for(Opportunity item : [SELECT Id FROM Opportunity WHERE opportunityIds IN :opportunityIds and Account.RecordTypeId = :recordTypeIdYouWant]){
recordTypeOpp.add(item.Id);
}
for(OpportunityLineItem olitems : listOppLineItems)
{
if(recordTypeOpp.contains(olitems.OpportunityId)){
//do processing
}
else {
continue;
}
}
Account and Contact both have Billing_Address__c field. Contact also have checkbox called active__c. If active__c is true and Account Billing_Address__c is update, then Contact's Billing_Address__c is updated . Here is the trigger. It is working fine. But I want to know if there is any problem or how can I optimize this in the terms of memory?
public static void updateContactBillingAddress(List<Account> lstNew, Map<Id,Account> mapOld){
Set<Id> accIds = new Set<Id>();
for(Account acc : lstNew){
if(acc.Billing_Address__c != mapOld.get(acc.Id).Billing_Address__c && acc.Billing_Address__c !=null){
accIds.add(acc.Id);
}
}
if(!accIds.isEmpty()){
List<Contact> lstContact = new List<Contact>([Select ID,active__c, Account.Billing_Address__c,Billing_Address__c FROM Contact where AccountID IN :accIds]);
List<Contact> lstUpdateCon = new List<Contact>();
for(Contact con : lstContact){
if(con.active__c == true){
if(con.Billing_Address__c != con.Account.Billing_Address__c){
con.Billing_Address__c = con.Account.Billing_Address__c;
lstUpdateCon.add(con);
}
}
else{
con.Billing_Address__c =null;
lstUpdateCon.add(con);
}
}
if(!lstUpdateCon.isEmpty()){
update lstUpdateCon;
}
}
}
Not really, it's semantics but i'd return a contact, 1 method, 1 thing. You're processing accounts and updating them, I'd return the List of contacts and not update them in the same method. If you need to update contacts down the road you will end up doing unnecessary DML statements, you also don't need to create a List just for that loop.
public static List<Contact> updateContactBillingAddress(List<Account> lstNew, Map<ID,Account> mapOld)
{
List<Contact> result = new List<Contact>();
Set<Id> accIds = new Set<Id>();
for(Account acc : lstNew)
{
if(acc.Billing_Address__c != null && acc.Billing_Address__c != mapOld.get(acc.Id).Billing_Address__c)
{
accIds.add(acc.Id);
}
}
if(!accIds.isEmpty())
{
for(Contact con : [Select ID,Active__c, Account.Billing_Address__c,Billing_Address__c FROM Contact where AccountID IN :accIds])
{
if(con.Active__c == true){
if(con.Billing_Address__c != con.Account.Billing_Address__c)
{
con.Billing_Address__c = con.Account.Billing_Address__c;
result.add(con);
}
}
else
{
con.Billing_Address__c = null;
result.add(con);
}
}
}
return result;
}
I need to transfer the below trigger logic to an apex class. But in apex class I cant use Trigger.New as it will give error. Once I give the logic in apex call, I can call the method in trigger so, Can anybody please tell me that how can I convert this trigger to an apex class?
trigger updatecontactrolecount on Opportunity(before insert, before update) {
Boolean isPrimary;
Integer iCount;
Map < String, Opportunity > oppty_con = new Map < String, Opportunity > (); //check if the contact role is needed and add it to the oppty_con map
for (Integer i = 0; i < Trigger.new.size(); i++) {
oppty_con.put(Trigger.new[i].id,
Trigger.new[i]);
}
isPrimary = False;
for (List < OpportunityContactRole > oppcntctrle: [select OpportunityId from OpportunityContactRole where(OpportunityContactRole.IsPrimary = True and OpportunityContactRole.OpportunityId in : oppty_con.keySet())]) {
if (oppcntctrle.Size() > 0) {
isPrimary = True;
}
}
iCount = 0;
for (List < OpportunityContactRole > oppcntctrle2: [select OpportunityId from OpportunityContactRole where(OpportunityContactRole.OpportunityId in : oppty_con.keySet())]) //Query for Contact Roles
{
if (oppcntctrle2.Size() > 0) {
iCount = oppcntctrle2.Size();
}
}
for (Opportunity Oppty: system.trigger.new) //Check if roles exist in the map or contact role isn't required
{
Oppty.Number_of_Contacts_Roles_Assigned__c = iCount;
Oppty.Primary_Contact_Assigned__c = isPrimary;
}
}
You can use a TriggerHandler Class to manage your all your triggerred events in the same place:
https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices
In your trigger call your unique class :
trigger OpportunityTrigger on Opportunity (before insert,after insert,before update,after update, before delete,after delete) {
try {
new OpportunityTriggerHandler().run();
}
catch(Exception e) {
System.debug(e);
}
Then do all the logic in the TriggerHandler :
public with sharing class OpportunityTriggerHandler extends TriggerHandler {
private Map<Id, Opportunity> newOpportunityMap;
private Map<Id, Opportunity> oldOpportunityMap;
private List<Opportunity> newOpportunity;
private List<Opportunity> oldOpportunity;
public OpportunityTriggerHandler() {
this.newOpportunityMap = (Map<Id, Opportunity>) Trigger.newMap;
this.oldOpportunityMap = (Map<Id, Opportunity>) Trigger.oldMap;
this.newOpportunity = (List<Opportunity>) Trigger.new;
this.oldOpportunity = (List<Opportunity>) Trigger.old;
}
public override void beforeInsert() {
for (Opportunity o : this.newOpportunity) {
if (o.Name == '...') {
//do your stuff
}
}
}
public override void afterInsert() {
//...
}
}