function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
frank2anilfrank2anil 

instead of 3 soql need a method

Hi,

 

Please help me in writing the method instead of writing 3 soql statements.

i will pass the owner id it should return all the reporting to ids from salestree upto three levels.

 

trigger salesnotice on Opportunity (after update) {


map<string,string> stnmap=new map<string,string>();
map<Id,String>Reporting2Ids =new map<ID,String>();

for(Opportunity op:trigger.new) { 

if(Trigger.IsUpdate && op.Stagename!=Trigger.oldMap.get(op.Id).Stagename &&(op.StageName=='Confirmed' || op.StageName==' Application' || op.StageName==' Endorsed Confirmed')){
stnmap.put(op.ownerid,op.id);

}
}
salestree(stnmap);
public static void salestree(map<String,String> x){

list<Sales__c> lstst= [select id,Subordinate__c,Subordinate__r.Email,Repo__c,Repo__r.Email from Sales__c where Subordinate__c IN : x.keyset()];
if(!lstst.isempty()){
for(Sales__c s:lstst){
Reporting2Ids.put(s.repo__c,s.Repo__r.Email);
}
}
list <Sales__c> lstst1= [select id,Repo__c,Repo__r.Email from Sales__c where Subordinate__c IN :Reporting2Ids.keyset()];
if(!lstst1.isempty()){
for(Sales__c s:lstst1){
Reporting2Ids.put(s.repo__c,s.Repo__r.Email);
}
}
list <Sales__c> lstst2= [select id,Repo__c,Repo__r.Email from Sales__c where Subordinate__c IN :Reporting2Ids.keyset()];
if(!lstst2.isempty()){
for(Sales__c s:lstst2){
Reporting2Ids.put(s.repo__c,s.Repo__r.Email);
}
}

}
List<string>s =new List<String>();
s=Reporting2Ids.values();

System.debug('**************************>>'+s);

}

 

Thanks In advance.

 

Best Answer chosen by Admin (Salesforce Developers) 
JohnSchultzJohnSchultz

I'll answer this in two parts:

 

First, to directly answer your question, you could iterate and test like this:

List<string>s =new List<String>();

for(String oppOwnerId : owner_relmailids.keySet()){ 
  if (stnmap.containsKey(oppOwnerId)) {
    s.addAll( owner_relmailids.get(oppOwnerId) );
  }
}

 

Second, I don't think that will be the solution. In the email message area of your code, you are referencing two variables, Appname and stgName, which you haven't declared or assigned anywhere. I think what you might want to do is change your stnmap so that it holds the opportunity, like Map<String, Opportunity> stnmap = new Map<String, Opportunity>(); and stnmap.put(op.OwnerId, op);. That would then allow you to have access to the opportunities' info while you create the mail message in your loop and send the messages after the loop, like so:

trigger salestreenotification on Opportunity (after update) {

  map<string, Opportunity> stnmap=new map<string, Opportunity>();
  map<Id,String>Reporting2Ids =new map<ID,String>();
  map<string,set<string>> owner_relmailids=new map<string,set<string>>();
  map<string,set<string>> sub_owners=new map<string,set<string>>();
  Map<String,String>sub=new map<String,String>();
  List<Id>st=new list<Id>();
  for(Opportunity op:trigger.new) {
    if(Trigger.IsUpdate && op.Stagename!=Trigger.oldMap.get(op.Id).Stagename &&(op.StageName=='Confirmed' || op.StageName=='Partial Application' || op.StageName=='Admissions Endorsed Confirmed')){
      stnmap.put(op.ownerid,op);
      owner_relmailids.put(op.ownerid,new set<string>());

    }
  }
  System.debug('<>>>>'+stnmap);


  if(!stnmap.isEmpty()){

    Set<String> ids = new Set<String>();
    ids.addall(stnmap.keySet());

    for (Integer i = 0; i < 3; i++) {
      if(!ids.IsEmpty())
      {
        list <Sales__c> lstst= [select id,Subordinate__c,Subordinate__r.Email,Reporting_To__c,repo__r.Email from Sales__c where Subordinate__c IN : ids];
        ids.clear();

        for (Sales__c s :lstst) {
          if(s.repo__c!=null){
            Reporting2Ids.put(s.repo__c, s.repo__r.Email);
            sub.put(s.Subordinate__c,s.repo__r.Email);
            System.debug('---)))->'+sub);
            ids.add(s.repo__c);
            set<String> temp=sub_owners.containsKey(s.repo__c)?sub_owners.get(s.repo__c):new set<string>();
            if(i!=0)
            {
              if(sub_owners.containsKey(s.Subordinate__c))
                temp.addAll(sub_owners.get(s.Subordinate__c));
            }
            else
            {
              temp.add(s.Subordinate__c);
            }
            sub_owners.put(s.repo__c,temp);
            for(string onrs:temp)
            {
              set<string> mids=owner_relmailids.containsKey(onrs)?owner_relmailids.get(onrs):new set<string>();
              mids.add(s.repo__r.Email);
              owner_relmailids.put(onrs,mids);

            }
          }
        }
      }
    }
    System.debug('---)))-->'+owner_relmailids);
  }

  List<Messaging.SingleEmailMessage> mailList = new List<Messaging.SingleEmailMessage>();

  for(String oppOwnerId : owner_relmailids.keySet()){ 
    if (stnmap.containsKey(oppOwnerId)) {
      messaging.Singleemailmessage mail=new messaging.Singleemailmessage();
      mail.setToAddresses( owner_relmailids.get(oppOwnerId) );
      mail.setSenderDisplayName('Hult');
      mail.setSubject('Opportunity Stage changed to:'+ stnmap.get(oppOwnerId).OwnerId );
      mail.setPlainTextBody('The Application record '+ stnmap.get(oppOwnerId).Name +'stage name was been changed to:'+ stnmap.get(oppOwnerId).StageName);
      mailList.add(mail);
    }
  }
  
  if (!mailList.isEmpty()) {
    Messaging.sendEmail(mailList);
  }

  System.debug('**************************>>'+s);

  
}

 

All Answers

sushant sussushant sus
ur logic os correct
i think their is no other way
we can get

up to one level of child from parent
JohnSchultzJohnSchultz

If you really want to use a method rather than the way you have it now, you would have to make it a static method and put it into a class (since triggers can't contain methods). Although you'd be making a SOQL query in a loop (albeit only 3 times), you could move it out into a method like so:

 

trigger salesnotice on Opportunity (after update) { 
    map<string,string> stnmap=new map<string,string>();
    map<Id,String>Reporting2Ids =new map<ID,String>();
    for(Opportunity op:trigger.new) { 
        if(Trigger.IsUpdate && op.Stagename!=Trigger.oldMap.get(op.Id).Stagename &&(op.StageName=='Confirmed' || op.StageName==' Application' || op.StageName==' Endorsed Confirmed')){
            stnmap.put(op.ownerid,op.id);

        }
    }

    Reporting2Ids.putAll( SalestreeClass.salestree(stnmap) );

    List<string>s =new List<String>();
    s=Reporting2Ids.values();

    System.debug('**************************>>'+s);
}

public class SalestreeClass {
    public static Map<Id, String> salestree(Map<String, String> x) {
        Set<String> keys = new Set<String>();
        Map<Id, String> results = new Map<Id, String>();
        
        keys.addAll(x.keySet());
        
        for (Integer i = 0; i < 3; i++) {
            for (Sales__c s : [select Id, Subordinate__c, Subordinate__r.Email, Repo__c, Repo__r.Email from Sales__c where Subordinate__c in : keys]) {
                results.put(s.Repo__c, s.Repo__r.Email);
            }
            
            keys.clear();
            keys.addAll(results.keySet());
        }
        
        return results;
    }
}

 

frank2anilfrank2anil

hi John 

 

Thanks for the reply.could you help me in iterating the map.

this is my modified trigger.

 

trigger salestreenotification on Opportunity (after update) {


map<string,string> stnmap=new map<string,string>();
map<Id,String>Reporting2Ids =new map<ID,String>();
map<string,set<string>> owner_relmailids=new map<string,set<string>>();
map<string,set<string>> sub_owners=new map<string,set<string>>();
Map<String,String>sub=new map<String,String>();
List<Id>st=new list<Id>();

for(Opportunity op:trigger.new) {
if(Trigger.IsUpdate && op.Stagename!=Trigger.oldMap.get(op.Id).Stagename &&(op.StageName=='Confirmed' || op.StageName=='Partial Application' || op.StageName=='Admissions Endorsed Confirmed')){
stnmap.put(op.ownerid,op.id);
owner_relmailids.put(op.ownerid,new set<string>());

}
}
System.debug('<>>>>'+stnmap);


if(!stnmap.isEmpty()){

Set<String> ids = new Set<String>();
ids.addall(stnmap.keySet());

for (Integer i = 0; i < 3; i++) {
if(!ids.IsEmpty())
{
list <Sales__c> lstst= [select id,Subordinate__c,Subordinate__r.Email,Reporting_To__c,repo__r.Email from Sales__c where Subordinate__c IN : ids];
ids.clear();

for (Sales__c s :lstst) {
if(s.repo__c!=null){
Reporting2Ids.put(s.repo__c, s.repo__r.Email);
sub.put(s.Subordinate__c,s.repo__r.Email);
System.debug('---)))->'+sub);
ids.add(s.repo__c);
set<String> temp=sub_owners.containsKey(s.repo__c)?sub_owners.get(s.repo__c):new set<string>();
if(i!=0)
{
if(sub_owners.containsKey(s.Subordinate__c))
temp.addAll(sub_owners.get(s.Subordinate__c));
}
else
{
temp.add(s.Subordinate__c);
}
sub_owners.put(s.repo__c,temp);
for(string onrs:temp)
{
set<string> mids=owner_relmailids.containsKey(onrs)?owner_relmailids.get(onrs):new set<string>();
mids.add(s.repo__r.Email);
owner_relmailids.put(onrs,mids);

}
}
}
}
}
System.debug('---)))-->'+owner_relmailids);
}

List<string>s =new List<String>();


for(Integer d=0;d<owner_relmailids.size();d++){


}

System.debug('**************************>>'+s);

messaging.Singleemailmessage mail=new messaging.Singleemailmessage();
mail.setToAddresses(s);
mail.setSenderDisplayName('Hult');
mail.setSubject('Opportunity Stage changed to:'+stgName);
mail.setPlainTextBody('The Application record '+Appname+'stage name was been changed to:'+StgName);
try{
messaging.sendEmail(new messaging.Singleemailmessage[]{mail});
}
catch(DMLException e){
system.debug('ERROR SENDING EMAIL:'+e);
}
}

 

I need to compare the opportunity id which i kept in stnmap with the ids in owner_relmailids.

owner_relmailids is contains opportunity owner id and related emails.

and then if both are same then need to send email to the related emails.

i was getting error incompatiable type in iteration.

Could you help me.

 

 

 

 

JohnSchultzJohnSchultz

I'll answer this in two parts:

 

First, to directly answer your question, you could iterate and test like this:

List<string>s =new List<String>();

for(String oppOwnerId : owner_relmailids.keySet()){ 
  if (stnmap.containsKey(oppOwnerId)) {
    s.addAll( owner_relmailids.get(oppOwnerId) );
  }
}

 

Second, I don't think that will be the solution. In the email message area of your code, you are referencing two variables, Appname and stgName, which you haven't declared or assigned anywhere. I think what you might want to do is change your stnmap so that it holds the opportunity, like Map<String, Opportunity> stnmap = new Map<String, Opportunity>(); and stnmap.put(op.OwnerId, op);. That would then allow you to have access to the opportunities' info while you create the mail message in your loop and send the messages after the loop, like so:

trigger salestreenotification on Opportunity (after update) {

  map<string, Opportunity> stnmap=new map<string, Opportunity>();
  map<Id,String>Reporting2Ids =new map<ID,String>();
  map<string,set<string>> owner_relmailids=new map<string,set<string>>();
  map<string,set<string>> sub_owners=new map<string,set<string>>();
  Map<String,String>sub=new map<String,String>();
  List<Id>st=new list<Id>();
  for(Opportunity op:trigger.new) {
    if(Trigger.IsUpdate && op.Stagename!=Trigger.oldMap.get(op.Id).Stagename &&(op.StageName=='Confirmed' || op.StageName=='Partial Application' || op.StageName=='Admissions Endorsed Confirmed')){
      stnmap.put(op.ownerid,op);
      owner_relmailids.put(op.ownerid,new set<string>());

    }
  }
  System.debug('<>>>>'+stnmap);


  if(!stnmap.isEmpty()){

    Set<String> ids = new Set<String>();
    ids.addall(stnmap.keySet());

    for (Integer i = 0; i < 3; i++) {
      if(!ids.IsEmpty())
      {
        list <Sales__c> lstst= [select id,Subordinate__c,Subordinate__r.Email,Reporting_To__c,repo__r.Email from Sales__c where Subordinate__c IN : ids];
        ids.clear();

        for (Sales__c s :lstst) {
          if(s.repo__c!=null){
            Reporting2Ids.put(s.repo__c, s.repo__r.Email);
            sub.put(s.Subordinate__c,s.repo__r.Email);
            System.debug('---)))->'+sub);
            ids.add(s.repo__c);
            set<String> temp=sub_owners.containsKey(s.repo__c)?sub_owners.get(s.repo__c):new set<string>();
            if(i!=0)
            {
              if(sub_owners.containsKey(s.Subordinate__c))
                temp.addAll(sub_owners.get(s.Subordinate__c));
            }
            else
            {
              temp.add(s.Subordinate__c);
            }
            sub_owners.put(s.repo__c,temp);
            for(string onrs:temp)
            {
              set<string> mids=owner_relmailids.containsKey(onrs)?owner_relmailids.get(onrs):new set<string>();
              mids.add(s.repo__r.Email);
              owner_relmailids.put(onrs,mids);

            }
          }
        }
      }
    }
    System.debug('---)))-->'+owner_relmailids);
  }

  List<Messaging.SingleEmailMessage> mailList = new List<Messaging.SingleEmailMessage>();

  for(String oppOwnerId : owner_relmailids.keySet()){ 
    if (stnmap.containsKey(oppOwnerId)) {
      messaging.Singleemailmessage mail=new messaging.Singleemailmessage();
      mail.setToAddresses( owner_relmailids.get(oppOwnerId) );
      mail.setSenderDisplayName('Hult');
      mail.setSubject('Opportunity Stage changed to:'+ stnmap.get(oppOwnerId).OwnerId );
      mail.setPlainTextBody('The Application record '+ stnmap.get(oppOwnerId).Name +'stage name was been changed to:'+ stnmap.get(oppOwnerId).StageName);
      mailList.add(mail);
    }
  }
  
  if (!mailList.isEmpty()) {
    Messaging.sendEmail(mailList);
  }

  System.debug('**************************>>'+s);

  
}

 

This was selected as the best answer
frank2anilfrank2anil
Thanks john
Thanks a lot for guiding me in right direction and in finding solution.