• karol.freeberg
  • NEWBIE
  • 84 Points
  • Member since 2014

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 16
    Questions
  • 34
    Replies
I use the following URL to access our production soap api: https://www.salesforce.com/services/soap/u/18.0 
I would like to know what is the URL to access the soap api in the sandbox. I tried adding the sandbox server to the URL https://cs26.salesforce.com/services/soap/u/18.0 but that did not work. Any suggestions? 
I have a detail button on a lead with the following code. It is set to Execute Javascript.

javascript:window.open("http://www.versodigitalpapers.com" );void(0); 
javascript:window.open("/flow/Verso_Digital_Paper_Request_for_Leads?GetLeadID={!Lead.Id}" );void(0);

The problem is it executes the first line fine but does not do the second line. Is there a way to do this within one button. If I switch the lines around, it will do the flow but not go to the external site. The flow creates a task. Any ideas?
I am trying to run a flow and when it is done, open an external site. The below is what I have:

/flow/Verso_Digital_Paper_Request_for_Leads&returl=%2Fhttp://www.versodigitalpapers.com/

It runs the flow fine but then I get an external url no longer exists message. What can I do to fix this.
I have a very simple trigger to do an update to a field called CTS_Rep__c. It is on a custom object and the trigger updates the field from the account object. The code is below.
trigger TOR_Update_CTS_Rep on Trial_Order_Request__c (before update, before insert) {

    //This trigger updates the CTS_Rep__c field from the Account CTS_Rep__c Field.
    //The lookup to account is based on the TOR field called Consignee_Ship_To_Name__c.
    //Note: By using the "before" trigger to modify the Trigger.new objects, you don't need 
    // to explicitly perform an update DML statement. When the trigger ends, it will implicitly 
    // update the data as you have modified the values 

    For (Trial_Order_Request__c newTOR : Trigger.new)
    {
        Account acc = 
            [Select ID, CTS_Rep__c from Account Where ID =: newTOR.Consignee_Ship_To_Name__c Limit 1];
        newTOR.CTS_Rep__c = acc.CTS_Rep__c;
        System.debug('In Trigger new tor= ' + newTOR.CTS_Rep__c);              
    } //End for Loop
}  //End of trigger
The trigger works fine on inserts and updates but when I wrote my test and ran that I ran into some problems. I am not getting the CTS_Rep__c field filled in. The trigger does not seem to save the data. My test code is below.
@ISTest public class TOR_CTS_Rep_Test {

 testMethod private static void runtests(){
        //In order for this test to work the three users Finance, Test User, and SysAdmin
        //must be opened and saved in prod so agent will get those last modified!!!
        //Also, Finance user contact created must = true and marked as an inactive user. 
        //SysAdmin and Test User contact created field must = false and marked active.        
        
        //create users
        List<User> theusers = Create_Accts_Contacts_From_Users_Test.buildUsers();
        //Use user0 for the account owner
        User User0 = theusers[0];
     	//Use user2 for the CTS Rep
     	User User2 = theusers[2];
     
        //create Account
        Account testacct = NewObjFactory.buildTestAcct(0, 'ABC Company', User0.id);
     	testacct.CTS_Rep__c = user2.id;
     	System.debug('acct CTS Rep = ' + testacct.CTS_Rep__c);
        insert testacct;
     
  		String theTORID;
     Test.startTest();
        // Create the Trial Order Request to test the insert of a new TOR with CTS Rep
        Trial_Order_Request__c TOR = NewObjFactory.buildtestTOR(0, testacct.id);
     	insert TOR;
     	theTORID=TOR.id;
     Test.stopTest();
     
     System.debug('TOR CTS Rep = ' + TOR.CTS_Rep__c);
     	//check to see if cts rep was added
        Trial_Order_Request__c TOR1 = [Select id, name, CTS_Rep__c
                       from Trial_Order_Request__c where ID =: theTORID ];
     System.debug('TOR1                    = ' + TOR1.CTS_Rep__c);
     System.debug('TOR                     = ' + TOR.CTS_Rep__c);
     System.debug('TOR1 Name                    = ' + TOR1.Name);
     System.assertEquals(TOR1.CTS_Rep__c,TOR.CTS_Rep__c);
 } //End runtests
}  //End test
When I run debug does not show the CTS_Rep__c as having any data. Below is the debug log.
User-added image
As you can see by the debug log, the ID for the CTS_Rep__c  is null. It pulls the correct data in name field so I know on my select statement that I am getting the correct record but again the CTS_Rep__c is null. Can anyone explain to me what I am doing wrong and how to correct the problem. Thank you.
I'm trying to test a trigger that runs on a before delete on an account. When I delete the account in the test I thought that the child contacts would be delete as well but that does not seem to be the case. I don't understand what I'd doing wrong here.
String testuser = UserInfo.getUserID();
        //set up the account
         Account testacct = NewObjFactory.buildTestAcct(0, 'Test Account1', testuser);
        insert testacct;
        Account testacct2 = NewObjFactory.buildTestAcct(0, 'Test Account2', testuser);
        insert testacct2;
        String accid = testacct.id;
         // Create the Contacts
        Contact testcontact = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'Joe');
        insert testcontact;
        String cid = testcontact.id;
        Contact testcontact2 = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'John');
        insert testcontact2;
        String c2id = testcontact2.id;
        Contact testcontact3 = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'Paul');
        insert testcontact3;
        
        
        //Create the portal records
        Portal_User_Information__c pu1 = new Portal_User_Information__c();
        pu1.user_Name__c = testcontact.id;
        insert pu1;
        
        Portal_User_Information__c pu2 = new Portal_User_Information__c();
        pu2.user_Name__c = testcontact2.id;
        insert pu2;
        
        Portal_User_Information__c pu3 = new Portal_User_Information__c();
        pu3.user_Name__c = testcontact3.id;
        insert pu3;
        String pu3id = pu3.id;

		
        //run tests
        Account ac = [Select ID from account where id = :accid];
        Contact c1 = [Select ID from contact where id = :cid];
        Test.startTest();
        	Database.deleteResult result = Database.delete(ac, false);  //delete account rec
			Database.deleteResult result2 = Database.delete(c1, false);
        Test.stopTest();
        
        // Check data 
        system.debug('start');      
        System.assert(result.isSuccess());
        System.assert(result2.isSuccess());
        system.debug('acct del2');
        Contact[] c1s = [Select ID from contact where id = :cid];
        System.assertEquals(c1s.size(),0);

Below is my test method. The last assert fails.
I have a custom object (Portal_User__C) with a field called user_name__c. The user_name__c field has a master lookup relationship to the contact record. I have a before delete trigger on the Portal_User__c record that sends an email to the portal administrator. It works fine if I just delete the portal_user__c record. However; if I delete the contact record first, by design it does delete the portal_user__c record but the trigger does not work. Do I have to write two triggers?  (One for the contact record to check for portal_user__c records before it can be deleted. And a second one for the actual Portal_user__c.) Or how does that work?
Could someone help me write the test code for the below class. I am new at this and don't have a clue on how to write the code for emailing and batch process. What I have so far is below.


global class OpportunityNotices implements Database.Batchable<sObject>,Database.Stateful  
    {  
        Map<Id , List<Opportunity>> userOppMap {get; set;}
        List<Opportunity> allOppNotices {get; set;}
 
              
       global OpportunityNotices()  
       {  
       
           Date CalDate = date.Today().addDays(10);
           
           //Map to maintain user id and cases logged by them today  
           userOppMap = new Map<Id, List<Opportunity>>() ;  
             
           //All sales rep (System admins)  
           List<User> salesRep = new List<User>() ;  
           salesRep = [select id , name , Email from User where isactive = true] ;  
             
           //All sales rep ids  
           List<Id> salesIds = new List<Id>() ;  
           for(User ur : salesRep)  
           {  
               salesIds.add(ur.Id) ;  
           }  
            
           //find a list of Opportuntities with overdue est decision dates
        allOppNotices = new List<Opportunity>();
        allOppNotices = [SELECT Id, StageName, CloseDate, name, OwnerID
            FROM Opportunity 
            WHERE CloseDate <= : CalDate
            AND StageName != 'Closed Won'
            AND StageName != 'Closed Lost'
            Order By OwnerID, ID
        ]; 
  
       }  
      
       global Database.QueryLocator start(Database.BatchableContext BC)  
       {  
          //Creating map of user id with opportunities that are due or overdue  
          for(opportunity c : allOppNotices)  
          {  
              if(userOppMap.containsKey(c.ownerId))  
              {  
                  //Fetch the list of case and add the new case in it  
                  List<Opportunity> tempList = userOppMap.get(c.ownerId) ;  
                  tempList.add(c);  
                  //Putting the refreshed case list in map  
                  userOppMap.put(c.ownerId , tempList) ;  
              }  
              else  
              {  
                  //Creating a list of case and outting it in map  
                  userOppMap.put(c.ownerId , new List<Opportunity>{c}) ;  
              }  
          }  
      
          //Batch on all system admins (sales rep)  
          String query = 'select id , name , Email from User where isactive = true';  
          return Database.getQueryLocator(query);  
       }  
      
       global void execute(Database.BatchableContext BC, List<sObject> scope)  
       {  
             
          for(Sobject s : scope)  
          {  
              //Type cast sObject in user object  
              User ur = (User)s ;  
                
              //If system admin has logged any case today then only mail will be sent  
              if(userOppMap.containsKey(ur.Id))  
              {  
                  //Fetching all cases logged by sys admin  
                  List<Opportunity> allOppOfSalesRep = userOppMap.get(ur.Id) ;  
                    
                  String body = '' ;  
                  //Creating tabular format for the case details  
                  body = BodyFormat(allOppOfSalesRep) ;  
                    
                  //Sending Mail  
                  Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage() ;  
                    
                 //Setting user email in to address  
                  String[] toAddresses = new String[] {ur.Email} ;  
                    
                  // Assign the addresses for the To and CC lists to the mail object  
                  mail.setToAddresses(toAddresses) ;
                  //String[] ccAddresses = new String[] {'ekfree@wctc.net'}; 
                  //mail.setccaddresses(ccaddresses); 
                  mail.setreplyto('_DL_NP_SFDC_ADMIN@newpagecorp.com');
          
                  //Email subject to be changed  
                  mail.setSubject('Opportunity Due Notice');  
                    
                  //Body of email  
                  mail.setHtmlBody('Please review and update the opportunities listed below by updating the estimated decision date or closing the opportunity if it is no longer active. ' 
                   + '<br/> <br/> ' + body + '<br/> ' + 'Thank you.');  
              
                  //Sending the email  
                  Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });  
              }  
          }  
       }  
         
       public String BodyFormat(List<Opportunity> opps)  
       {  
           String str = '' ;
             
           for(Opportunity cs : opps)  
           {  
               Date dt = cs.closedate;
               String dateStr = DateTime.newInstance(dt.year(),dt.month(),dt.day()).format('MM/dd/yyyy');
             
               str += '<tr><td colspan="2">'+ cs.Name +'</td>'+'<td colspan="2">'+ dateStr +'</td>'+'<td>'+ '</td>'+'<td>'+ '</td>'+'</tr>' ;  
           }  
           str = str.replace('null' , '') ;  
           String finalStr = '' ;  
           finalStr = '<table border="  "> <td colspan="2">Name </td> <td colspan="2">Est. Decision Date  </td> '+'<td>'+ '</td>'+'<td>'+ '</td>'+ str +'</table>' ;  
           return finalStr ;  
       }  
      
       global void finish(Database.BatchableContext BC)  
       {  
           AsyncApexJob a = [Select id, status, numberoferrors, jobitemsprocessed,
               totaljobitems, createdby.email from AsyncApexJob where id = :BC.getjobid()];
           
           //send email
           Messaging.singleemailmessage mail = new messaging.singleemailmessage();
           string[] toadd = new string[] {'karol.freeberg@newpagecorp.com'};
           mail.settoaddresses(toadd);
           mail.setsubject('Opportunity Notices Job Completed ' + a.status);
           mail.setplaintextbody
               ('The batch apex job processed ' + a.totaljobitems + ' batches with ' + a.numberoferrors + ' failures.');
           messaging.sendemail (new messaging.singleemailmessage[] {mail});
       
       
       }  
      
    }



@isTest class OpportunityNoticesTest {

    Static testmethod void test() {
    
    //query used by the batch job
     String query = 'select id , name , Email from User where isactive = true';  
     
     //Test data
     Opportunity[] op = new List<opportunity>();
     For (integer i=0; i < 5;i++) {
     
        Opportunity o = new opportunity(
        Closedate  = date.Today().addDays(-16),
        StageName  = 'Target',
        Name = '2014-AARP' + i,
        reason_won_lost__C = 'Freight;History',
        annual_volume__c = 3,
        type = 'New Business',
        tons_won__c = 15,
        frequency__c = 'Spot',
        End_Use__c = 'This is the end use',
        start_Date__c = date.today());
        op.add(o);
     
     } //End for loop
     
     Test.starttest();
     Integer batchSize = 1;
     OpportunityNotices OppN = new OpportunityNotices();
     if(!Test.isRunningTest()){
         Database.executeBatch(OppN, batchSize);
     }
     
     Test.StopTest();
     
     
    
    
    } //End testmethod
    
}  //End


I have a nested list issue. I have two lists of IDs and I'm trying to combine them into one list so I can return the list and then split it back out after it is returned. This is what I have.

List<List<ID>> AllIDLists = New List<List<ID>>();
AllIDLists.add(mailToIds);
AllIdLists.add(WhatOppIDs);
Return AllIdLists;

So first I'm not sure that the list definition is correct. The definition should accomodate basically one list that contains 2 lists. 
My second question is then what is the best way to split the lists back out. My code for that is below.

List<ID> oppIdsList = New List<ID>{AllIdLists.get(0)};
List<ID> whatIdsList = New List<ID>{AllIdLists.get(1)};

Any help on what I am doing wrong here is appreciated. 
Below is my original code and the test code. The test code only has 59% coverage. Is there anyone that can help me get that coverage up please. I know I could use some system assets but don't know for what since there are no data updates, only an email gets sent.

/**************************************************************************/
//The Opportunity Overdue Notice Emailer
//
//This class can be scheduled to run nightly to send emails to opportunity
//owners when the Est. Decision Date (CloseDate) is overdue by 14 days
//
//Emails will only be sent to opp owners that meet the following conditions:
// The opp stagename is not Closed Won or Closed Lost
// The Est. Decision Date is overdue by 14 days or more
//
/***************************************************************************/

global class OppOverdueNotice implements Schedulable{
               
              
            //mandataory function called by the Apex Scheduler
    global void execute(SchedulableContext SC) {
        sendmail(); // our main function that does the email sending
    }       //end global void execute(SchedulableContext SC

   
            //Get email addresses of people overdue opportunities by 14 days
    public List<List<ID>> getOppEmailAddresses(Date CalDate){      //(optional Integer Month, Integer Day, Integer Year)
        List<Id> mailToIds = new List<Id>();
        List<ID> WhatOppIDs = new List<ID>();
                
            //find a list of Opportuntities with overdue est decision dates
        Opportunity[] c = [SELECT Id, StageName, CloseDate, name, OwnerID
            FROM Opportunity
            WHERE CloseDate <= : CalDate
            AND StageName != 'Closed Won'
            AND StageName != 'Closed Lost'
            Limit 3
        ];
           
           
            //Loop opportunities that are overdue      
        for(Opportunity recipient : c) {
            
           
            // Take the ID of the Opp owner                                                                                   
            if (recipient.name != '') {
               
                //Check to find user record of the opp owner and get their corresponding contact record ID
                User u = [Select contact_ID__c, lastname, firstname from User where ID = : recipient.ownerID];              
               
                List <Contact> ContactRec = [Select ID, name from Contact where ID = : u.contact_id__c];
                    If (ContactRec.size() == 1) {  //We got Contact record
                        mailToIds.add(ContactRec[0].Id);   // add to email contact array
                        WhatOppIDs.add(recipient.Id);    //opportuntiy record ID
                    } Else {
                        //See if you can find the contact record using the contact name
                        List <Contact> CRec = [Select ID, name from Contact
                                where lastname = :u.lastname and firstname = :u.firstname and contact_status__c = 'User'];
                        If (CRec.size() == 1) { 
                            mailToIds.add(CRec[0].Id);   // add to email contact array
                            WhatOppIDs.add(recipient.Id);    //opportuntiy record ID
                        } //end if
                    }//end if
                             
            } else {
                System.Debug('\n*******NO Recipient');
            }  //end if else
                               
        }   //end for loop
       
        List<List<ID>> AllIDLists = New List<List<ID>>();
        AllIDLists.add(mailToIds);
        AllIdLists.add(WhatOppIDs);
            //return the list
        return AllIdLists;
           
    }//end getOppEmailAddresses()

    public void sendMail() {
            //define variables                           
        String debugAddress = 'Karol.Freeberg@newpagecorp.com';
        String OppEmailTemplateName = 'Opportunity_Past_Due_Notice';                                        
        String debugMessage;
        String[] toAddresses;

        Date CalDate = date.Today().addDays(14);
             // build the Overdue list

            //get the list of people with overdue oppotunities - this can justifiably come back empty.
        List<List<ID>> OppLists = getOppEmailAddresses(CalDate);
        If (OppLists[0].size() > 0){
           List<ID> oppIdsList = New List<ID>{OppLists.get(0).get(0)};
            List<ID> whatIdsList = New List<ID>{OppLists.get(1).get(0)};
           

            //Set the templates
            EmailTemplate oppTemplate = [select Id,Name,Subject,body
                                     from EmailTemplate where DeveloperName = :OppEmailTemplateName];
                               
            if(oppTemplate != null && oppIdsList.isEmpty() == false){
                Messaging.MassEmailMessage oppMail = new Messaging.MassEmailMessage();
                oppMail.setTargetObjectIds(oppIdsList);
                oppMail.setTemplateId(oppTemplate.Id);
                oppMail.setWhatIDs(whatIdsList);
                oppMail.setUseSignature(false);
                oppMail.setSaveAsActivity(false);

                // Send the email
                try {
                    Messaging.sendEmail(new Messaging.MassEmailMessage[] { oppMail });
                    System.Debug('Mail sent');
                }catch(Exception e){
                    System.Debug(e);
                }   // end of try catch
          
            } else {
           
                System.Debug('OppCronJob:sendMail(): Either an email template could not be found, or no opportunities are overdue');
            }//end if
        } // end If for opplists.size check

    }//end sendMail()
} // end class OppCronJob


The test code that needs help:

@isTest class OppOverdueNotice_Test {

    static testmethod void test() {
        Test.startTest();
       

       
         Date CalDate = date.Today().addDays(14);
            //Integer testday   = CalDate.day();
            //Integer testmonth = CalDate.month();
            //Integer testyear = CalDate.Year();
        OppOverdueNotice BCJ = new OppOverdueNotice();
       
        //run the test once, without ensuring that a overdue opportunity exists;
        BCJ.sendMail();
        system.debug('No email');
        
        Opportunity testOpportunity = new Opportunity();
        testOpportunity.Closedate  = date.Today().addDays(-16);
        testOpportunity.StageName  = 'Target';
        testOpportunity.Name = '2014-AARP';
        testOpportunity.reason_won_lost__C = 'Freight;History';
        testOpportunity.annual_volume__c = 3;
        testOpportunity.type = 'New Business';
        testOpportunity.tons_won__c = 15;
        testOpportunity.frequency__c = 'Spot';
        testOpportunity.End_Use__c = 'This is the end use';
        testOpportunity.start_Date__c = date.today();
       
        Contact testcontact = new contact();
        testcontact.lastname = 'Freeberg';
        testcontact.firstname = 'Karol';
        testcontact.email = 'Karol.Freeberg@newpagecorp.com';
        insert testcontact;
        Contact Crec = [Select ID from Contact where lastname = 'Freeberg'];
           
       
        //run the test again, now that a contact with an overdue opportunity existing
        insert testOpportunity;
        BCJ.sendMail();
        system.debug('Good opp email');
       
        // Schedule the test job 
   
        String CRON_EXP = '0 0 0 3 9 ? 2022';
        String jobId = System.schedule('testBasicScheduledApex', CRON_EXP, new OppOverdueNotice());
       
        // Get the information from the CronTrigger API object 
   
        CronTrigger ct = [SELECT id, CronExpression, TimesTriggered, NextFireTime
                            FROM CronTrigger
                            WHERE id = :jobId];
       
        // Verify the expressions are the same 
        System.assertEquals(CRON_EXP, ct.CronExpression);
   
        // Verify the job has not run 
        System.assertEquals(0, ct.TimesTriggered);
       
        // Verify the next time the job will run 
   
        System.assertEquals('2022-09-03 00:00:00', String.valueOf(ct.NextFireTime));
       

        Test.stopTest();
       
       

        //Clean up
        delete testOpportunity;
        delete testcontact;
       
    }
}
I am getting the following error and I am at a loss on what is wrong. Can anyone please help? The line of code with the error is underlined below.

11:00:01.063 (63040986)|USER_DEBUG|[23]|DEBUG|---------------------------------rows 3
11:00:01.063 (63047571)|SYSTEM_METHOD_EXIT|[23]|System.debug(ANY)
11:00:01.063 (63058551)|SYSTEM_METHOD_ENTRY|[26]|LIST<User>.iterator()
11:00:01.063 (63228660)|SYSTEM_METHOD_EXIT|[26]|LIST<User>.iterator()
11:00:01.063 (63259893)|SYSTEM_METHOD_ENTRY|[26]|system.ListIterator.hasNext()
11:00:01.063 (63295436)|SYSTEM_METHOD_EXIT|[26]|system.ListIterator.hasNext()
11:00:01.063 (63545352)|FATAL_ERROR|System.StringException: Invalid id:

List<String> userAcctNames = new List <String>();
       
        // Get all users modified in the last 3 days  
        User[] upusers = [Select ID, Department, Account_Name__c, contact_created__c,
                    LastModifiedDate From User Where LastModifiedDate >= :ckdt ];

        system.debug('---------------------------------rows ' + upusers.size());
       
       
        for (User theuser : upusers) {
             
            // Collect the IDs                                                                                 
            if (theuser.id != '') {
                userids.add(theuser.id);
                userAcctNames.add(theuser.Account_Name__c);
                system.debug('--------------------------------added ' + theuser.id + theuser.account_name__c);            
            }  //End if for collection of ids
         }  // end for loop
I want to restrict all read access to attachments on some contracts to the contract owner. This is only for a few contracts, not all contracts: System admins can view and edit the data. Is there a way to do this without creating a profile for the one person? (One thought was to just put a password on the attached Word document but I was really hoping for something better.) 
I am really new at apex code and worse at trying to do the test coverage. My code is only at 65% and I'm at a loss at what else do to. Can anyone help please.

Here is my current test code and my trigger is below that.
The Test Code: Coverage only at 65%
@IsTest Private class TestSRProducts {
   
    testMethod private static void getthedata() {
        // Create the user
       // User testUser = NewObjFactory.buildTestUser(0, 'Pipo', 'Tanya');
       // insert testuser;
        String PM7 = 'Tanya Pipo';
        User testuser = [Select ID, Name
                     From User
                     Where Name = :PM7];
        system.debug('User ' +testuser.id);
      
      
   
        // Create the Account
        Account testacct = NewObjFactory.buildTestAcct(0, 'User - IT', testuser.id);
        insert testacct;
       
       
        // Create the Contact
        Contact testcontact = NewObjFactory.buildTestContact(0, testacct.id, testuser.id);
        insert testcontact;
      
       
        // Create a product
        Product2 testprod = NewObjFactory.buildTestProducts(0);
        insert testprod;
        Product2 testprod2 = NewObjFactory.buildTestProd2(0);
        insert testprod2;
      
       
        // Create a Stocking Request
        Stocking_Request__c testSR = NewObjFactory.buildTestStockingReq(0, testacct.id, testuser.id, testcontact.id);
        insert testSr;
        system.debug('SR ' +testsr.id);
       
        // Create a SR Product and envokes the trigger
        SR_Products__C testsrprod = NewObjFactory.buildtestSRProducts(0, testSR.id);
        SR_Products__C testsrprod2 = NewObjFactory.buildtestSRProducts(0, testSR.id);
        testsrprod2.Product__c = [Select ID from Product2 where name = :'CLS2PAP SHEET SECONDS GLOSS'].id;
        Test.startTest();
        insert testsrprod;
        insert testsrprod2;
        Test.stopTest();
       
        Stocking_Request__c SR1 = [Select ID, Name, product_manager_1__c,
                     product_manager_2__c, product_manager_3__c, product_manager_4__c,
                     product_manager_5__c, product_manager_6__c, product_manager_7__c, product_manager_8__c
                     From Stocking_Request__c
                     Where ID = :testsr.id];           
            If (SR1 != null){
       
         system.debug('product manager is '+SR1.name);
         system.debug('product manager7 is '+ SR1.product_manager_7__c);
          }
        System.assertEquals (SR1.product_manager_7__c, testuser.id);
        System.assertNotEquals (SR1.product_manager_6__c, testuser.id);
        System.assertNotEquals (SR1.product_manager_5__c, testuser.id);
        System.assertNotEquals (SR1.product_manager_4__c, testuser.id);
        System.assertNOtEquals (SR1.product_manager_3__c, testuser.id);
        System.assertNotEquals (SR1.product_manager_2__c, testuser.id);
        System.assertNotEquals (SR1.product_manager_1__c, testuser.id);
       
   
    }    //End getthedata
       
       
} //End Class TestSRProducts
The trigger:

trigger SR_Set_Approvers on SR_Products__c (After insert, After Update) {
   
    // This trigger sets all the product managers from the Stocking Request records
    // With the data from the SR - Product Details records
   
    // Loop all product records that have changed
    for (SR_Products__c prod : Trigger.new) {
       
        // system.debug('product name1 = ' + prod.Stocking_Request__c);
        // Get all the product records related to the SR
        SR_Products__c[] allproducts = [SELECT product_manager__c, PM_Type__C,
                                        stocking_request__c
                            FROM SR_Products__c
                            WHERE stocking_request__c = :Prod.stocking_request__c 
                            ];
        String Pm1 = '';
        String Pm2 = '';
        String Pm3 = '';
        String Pm4 = '';
        String Pm5 = '';
        String Pm6 = '';
        String Pm7 = '';
        String Pm8 = '';
            //Set the PM variables with the PM from the SR-Products records       
        for(SR_Products__c p : allproducts) {
       
            If (p.PM_Type__c == 'PM1')
                pm1 = p.product_manager__c;
            If (p.PM_Type__c == 'PM2')
                pm2 = p.product_manager__c;
            If (p.PM_Type__c == 'PM3')
                pm3 = p.product_manager__c;
            If (p.PM_Type__c == 'PM4')
                pm4 = p.product_manager__c;
            If (p.PM_Type__c == 'PM5')
                pm5 = p.product_manager__c;
            If (p.PM_Type__c == 'PM6')
                pm6 = p.product_manager__c;
            If (p.PM_Type__c == 'PM7')
                pm7 = p.product_manager__c;
            If (p.PM_Type__c == 'PM8')
                pm8 = p.product_manager__c;                   
        } //end loop products
       
        // Get the Stocking Request record
        //system.debug('product name = ' + prod.Stocking_Request__c);
        Stocking_Request__c sr = [Select ID, Name,
                               Product_Manager_1__c, Product_Manager_2__c,
                               Product_Manager_3__c, Product_Manager_4__c,
                               Product_Manager_5__c, Product_Manager_6__c,
                               Product_Manager_7__c, Product_Manager_8__c
                     From Stocking_Request__c
                     Where ID = :prod.Stocking_Request__c];
       
        // Reset all PM fields to blank to start out with
        sr.Product_Manager_1__c = null;
        sr.Product_Manager_2__c = null;
        sr.Product_Manager_3__c = null;
        sr.Product_Manager_4__c = null;
        sr.Product_Manager_5__c = null;
        sr.Product_Manager_6__c = null;
        sr.Product_Manager_7__c = null;
        sr.Product_Manager_8__c = null;
        // Get the user record IDs for the PM variable fields
        // And set the PM fields in the stocking request record
     
        If (PM1 != '' ){
            User u1 = [Select ID, Name
                     From User
                     Where Name = :PM1];           
            If (u1 != null)sr.Product_Manager_1__c = u1.ID;
        } //End PM1 if
       
      
        If (PM2 != '' ){
            User u2 = [Select ID, Name
                     From User
                     Where Name = :PM2];
            If (u2 != null)sr.Product_Manager_2__c = u2.id;
        } //End PM2 if       
      
        If (PM3 != '' ){
            User u3 = [Select ID, Name
                     From User
                     Where Name = :PM3];
            If (u3 != null)sr.Product_Manager_3__c = u3.id;
        } //End PM3 if
       
        If (PM4 != ''){
            User u4 = [Select ID, Name
                     From User
                     Where Name = :PM4];
            If (u4 != null)sr.Product_Manager_4__c = u4.id;
        } //End PM4 if       
      
        If (PM5 != '' ){
            User u5 = [Select ID, Name
                     From User
                     Where Name = :PM5];
            If (u5 != null)sr.Product_Manager_5__c = u5.id;
        } //End PM5 if       
       
        If (PM6 != ''){
            User u6 = [Select ID, Name
                     From User
                     Where Name = :PM6];
            If (u6 != null)sr.Product_Manager_6__c = u6.id;
        } //End PM6 if       
 
        If (PM7 != '' ){
            User u7 = [Select ID, Name
                     From User
                     Where Name = :PM7];
           
            If (u7 != null)sr.Product_Manager_7__c = u7.id;
        } //End PM7 if       
           
        If (PM8 != '' ){
            User u8 = [Select ID, Name
                     From User
                     Where Name = :PM8];
            If (u8 != null)sr.Product_Manager_8__c = u8.id;
        } //End PM8 if
              
       Update sr;
      
    }  // End for looping of changed product records
}
I am totally new at coding apex. I managed to write the code but I have a lot of unanswered questions about how to write the test. Below is the code I need to write the test for and below that is what I have written so far for the test. What is happening in the code is I have a Dedicated Stock (DS) parent object (It contains 8 product manager fields used for an approval process). The DS parent object has a relationship to the SR_Products child objects (0-many). The product child records contain one product manager field and it is filled depending on who the product manager is for the product selected. When an insert or update is done to the SR_Products record the trigger runs to fill in the corresponding product manager field on the parent DS object. The trouble I am having with writing the test is (basically I don't know much here): 1) In the test what happens with formula fields? The child object contains formula fields that are key to the test. Don't know how to fill those. 2)Do you have to put test data in for the parent, child, and user objects. 3) Do I use real Id numbers or how do I set that up? What would I do the assert on? Any help to get me going is appreciated.

trigger SR_Set_Approvers on SR_Products__c (After insert, After Update) {

    // This trigger sets all the product managers from the Stocking Request records
    // With the data from the SR - Product Details records
   
    // Loop all product records that have changed
    for (SR_Products__c prod : Trigger.new) {
       
     system.debug('product name1 = ' + prod.Stocking_Request__c);
        // Get all the product records related to the SR
        SR_Products__c[] allproducts = [SELECT product_manager__c, PM_Type__C,
                                        stocking_request__c
             FROM SR_Products__c
             WHERE stocking_request__c = :Prod.stocking_request__c 
             ];
        String Pm1 = '';
        String Pm2 = '';
        String Pm3 = '';
        String Pm4 = '';
        String Pm5 = '';
        String Pm6 = '';
        String Pm7 = '';
        String Pm8 = '';
   //Set the PM variables with the PM from the SR-Products records       
     for(SR_Products__c p : allproducts) {
       
   If (p.PM_Type__c == 'PM1')
                pm1 = p.product_manager__c;
            If (p.PM_Type__c == 'PM2')
                pm2 = p.product_manager__c;
            If (p.PM_Type__c == 'PM3')
                pm3 = p.product_manager__c;
            If (p.PM_Type__c == 'PM4')
                pm4 = p.product_manager__c;
            If (p.PM_Type__c == 'PM5')
                pm5 = p.product_manager__c;
            If (p.PM_Type__c == 'PM6')
                pm6 = p.product_manager__c;
            If (p.PM_Type__c == 'PM7')
                pm7 = p.product_manager__c;
            If (p.PM_Type__c == 'PM8')
                pm8 = p.product_manager__c;                   
        } //end loop products
       
        // Get the Stocking Request record
        system.debug('product name = ' + prod.Stocking_Request__c);
        Stocking_Request__c sr = [Select ID, Name,
                               Product_Manager_1__c, Product_Manager_2__c,
                               Product_Manager_3__c, Product_Manager_4__c,
                               Product_Manager_5__c, Product_Manager_6__c,
                               Product_Manager_7__c, Product_Manager_8__c
                     From Stocking_Request__c
                     Where ID = :prod.Stocking_Request__c];
       
      // Reset all PM fields to blank to start out with
      sr.Product_Manager_1__c = null;
        sr.Product_Manager_2__c = null;
        sr.Product_Manager_3__c = null;
        sr.Product_Manager_4__c = null;
        sr.Product_Manager_5__c = null;
        sr.Product_Manager_6__c = null;
        sr.Product_Manager_7__c = null;
        sr.Product_Manager_8__c = null;
        // Get the user record IDs for the PM variable fields
        // And set the PM fields in the stocking request record
       system.debug('pm1 ID using =  ' + pm1 + pm2);
        If (PM1 != '' ){
         User u1 = [Select ID, Name
                     From User
                     Where Name = :PM1];           
            If (u1 != null)sr.Product_Manager_1__c = u1.ID;
        } //End PM1 if
       
  system.debug('pm2 ID using =  ' + pm2);
        If (PM2 != '' ){
         User u2 = [Select ID, Name
                     From User
                     Where Name = :PM2];
            If (u2 != null)sr.Product_Manager_2__c = u2.id;
        } //End PM2 if       
  system.debug('pm3 ID using =  ' + pm3);
        If (PM3 != '' ){
         User u3 = [Select ID, Name
                     From User
                     Where Name = :PM3];
            If (u3 != null)sr.Product_Manager_3__c = u3.id;
        } //End PM3 if
        system.debug('pm4 ID using =  ' + pm4);
        If (PM4 != ''){
         User u4 = [Select ID, Name
                     From User
                     Where Name = :PM4];
            If (u4 != null)sr.Product_Manager_4__c = u4.id;
        } //End PM4 if       
        system.debug('pm5 ID using =  ' + pm5);
        If (PM5 != '' ){
         User u5 = [Select ID, Name
                     From User
                     Where Name = :PM5];
            If (u5 != null)sr.Product_Manager_5__c = u5.id;
        } //End PM5 if       
       
        If (PM6 != ''){
         User u6 = [Select ID, Name
                     From User
                     Where Name = :PM6];
            If (u6 != null)sr.Product_Manager_6__c = u6.id;
        } //End PM6 if       
 
        If (PM7 != '' ){
         User u7 = [Select ID, Name
                     From User
                     Where Name = :PM7];
            If (u7 != null)sr.Product_Manager_7__c = u7.id;
        } //End PM7 if       

        If (PM8 != '' ){
         User u8 = [Select ID, Name
                     From User
                     Where Name = :PM8];
            If (u8 != null)sr.Product_Manager_8__c = u8.id;
        } //End PM8 if       
       Update sr;
      
}  // End for looping of changed product records
}


My test so far:

@IsTest

Private class TestSRProducts {
   
    static TestMethod void AddProduct() {
        //Setup new Stocking Request
        Stocking_Request__c AR = new Stocking_Request__c();
        AR.Sold_To__c = 'ABC Company';
        AR.Business_Case__c = 'Bus';
       
       
        //Setup new product
        SR_Products__c testAddP = new SR_Products__c();
        testAddp.Stocking_Request__c = 'ABC Company';
        testAddp.Product__c = '01td00000035nAg';
        testAddp.Form__c = 'Web';
        testAddp.Certification__c = 'FSC';
        testAddp.Pounds__c = 10;
        testAddp.Selling_Price__c = 45.00;
        testAddp.New_or_Existing__c = 'New';
        testAddp.width__c = 12;
        testAddp.Diameter__c = 12;
        testAddp.length__c = 24;
        testaddp.Core_Size__c = 24;
        testaddp.Grain__C = 'Long';
        testaddp.Pounds_Per__c = 'Month';
        Test.startTest();
        insert testaddp;
        Test.stoptest();
       System.assertnotEquals(testaddp.id, null);
      
    } //End AddProduct
       
       
       
} //End Class TestSRProducts
I'm having trouble with the following. I have a custom object and in that custom object I have a product manager field. The field needs to be filled with the product manager's name/ID from the user object. I have successfully retrieved the user record but I am unsure how to fill the custom object's product manager field. The code is below. The u1.ID does contain the correct ID for the product manager and I do successfully get the user record. The problem is how do I correctly fill the product_manager_1__c field so it maintains the lookup relationship to the user record. Product_manager_1__C is a lookup field to the user object.

If (PM1 != null ){
         User u1 = [Select ID, Name
                     From User
                     Where Name = :PM1];
            system.debug('pm1 ID =  ' + u1.id);
            If (u1.Id != '')sr.Product_Manager_1__c = u1.ID;
            Update sr;
            
        } //End PM1 if
I have the following code that sends a mass email out based on a end date being past due. Being a very new apex developer I need some help with the following task. The main list of people receiving the mass email is setup in the getSPEEmailAddresses module. The problem I am having is that there is a public group defined in the getpublicgroupaddresse module that I need to cc on each email going out in the getSPEEmailaddresses module and I don't know how to go about doing that. Can anyone adjust the below code to accomplish that task?

/**************************************************************************/
//The SPEs past due Notice Emailer
//
//This class can be scheduled to run nightly to send emails to SPE
//owners, and the public group called SPE_Pastdue_Notification
// when the End DAte (End_Date__c) is within 14 days of being past due
// and the routing status = approved.
//
/***************************************************************************/

global class SPEs_Pastdue implements Schedulable{


     //mandataory function called by the Apex Scheduler
  //**************************************************
  global void execute(SchedulableContext SC) {
        //**************************************************
        sendmail(); // our main function that does the email sending
     }//end execute

  //Get email addresses of people pastdue SPEs by 14 days
//**************************************************
    public List<Id> getSPEEmailAddresses(Date CalDate) {     
    //**************************************************
         List<Id> mailToIds = new List<Id>();
         
         //find a list of SPEs with overdue end dates
         Sales_Policy_Exceptions__c[] c = [SELECT Id, End_Date__C, Routing_Status__c, owner_email__c
             FROM Sales_Policy_Exceptions__c
             WHERE End_Date__c <= : CalDate
                            AND Routing_Status__c = 'Approved'
             ];                
                         // Old Date samples 
          // DAY_IN_MONTH(CloseDate) = : Day
      // AND CALENDAR_MONTH(CloseDate) = : Month
                        //  AND CALENDAR_Year(CloseDate) = : Year
           
           
   //add the list of Sales_Policy_Exceptions__c to a list       
         for(Sales_Policy_Exceptions__c recipient : c) {
         
          
           System.Debug('\n*******Found Sales_Policy_Exceptions__c Recipient');
                     
           if (recipient.owner_Email__c != '')
           {
            mailToIds.add(recipient.Id); // add to email SPE array
            System.Debug('\n*******Recipient: '+ recipient.owner_email__c); 
           } else {
            //Just add to chatter array
            System.Debug('\n*******NO Recipient');
           } //end if        
         } //end for loop

         return mailToIds;   //return the list
      } //end getSPEEmailAddresses()
   
    //**************************************************
    public List<String> getPublicGroupAddresses() {
    //**************************************************
  List<String> idList = new List<String>();
  List<String> mailCCAddresses = new List<String>();
        List<ID> mailCCAddressesID = new List<ID>();
  Group g = [SELECT (select userOrGroupId from groupMembers) FROM group WHERE name = 'SPE_Pastdue_Notification'];
   for (GroupMember gm : g.groupMembers) {
   idList.add(gm.userOrGroupId);
  } //End group
  User[] usr = [SELECT email FROM user WHERE id IN :idList];
  for(User u : usr) {
   mailCCAddresses.add(u.email);
            mailCCAddressesID.add(u.id);
  } //end for loop
return mailCCAddresses;      
}   //End getPublicGroupAddresses

//**************************************************
    public void sendMail() {
    //**************************************************
   //define variables     
   String debugAddress = 'xxx@newpagecorp.com';
   String SPEEmailTemplateName = 'Opportunity_Past_Due_Notice';  
   String debugMessage;
         String[] toAddresses;

            Date CalDate = date.Today().addDays(14);

            System.Debug('Date '+CalDate);


   // build the Overdue list

   //get the list of people with overdue Sales_Policy_Exceptions__c - this can justifiably come back empty.
         List<Id> SPEIdsList = getSPEEmailAddresses(CalDate);
            List<Id> SPEgroupList = getPublicGroupAddresses();

   //Set the templates
         EmailTemplate SPETemplate = [select Id,Name,Subject,body from EmailTemplate where DeveloperName = :SPEEmailTemplateName];
 
         if(SPETemplate != null && SPEIdsList.isEmpty() == false)
         {

             Messaging.MassEmailMessage SPEMail = new Messaging.MassEmailMessage();
       
             SPEMail.setTargetObjectIds(SPEIdsList);
             SPEMail.setTemplateId(SPETemplate.Id);
             SPEMail.setUseSignature(false);
             SPEMail.setSaveAsActivity(true);

             // Send the email
             try {
              Messaging.sendEmail(new Messaging.MassEmailMessage[] { SPEMail });
                    System.Debug('Mail sent');
             }catch(Exception e)
             {
              System.Debug(e);
             }
          
         }
         else
         {
             System.Debug('SPECronJob:sendMail(): Either an email template could not be found, or no opportunities are overdue');
         }//end if

               
  }//end sendMail()
}   //SPEs_Pastdue end
I am very new to Apex. This is the first thing I'm attempting and of course, they want it yesterday. I am trying to update some user name fields on a custom oject from name fields that are on the account form. Below is my code. I am having trouble because the Customer Service Rep field is sending the ID instead of the name. I'm not sure how to copy a name field from one object to another. Please help. Once I get this field, then I need to proceed to get the owner of the account and get the project manager field from the user record.

trigger FillApprovers on Sales_Policy_Exceptions__c (before insert) {
    Set<ID>AccIDset = new Set<ID>();
    For (Sales_Policy_Exceptions__c SalesPol : Trigger.new) {
        AccIDSet.add(SalesPol.Account_Name__c);
        List<Account> Accts = [SELECT ID,Pricing_Lead__c,Customer_Service_Rep_Primary__C from Account WHERE ID  IN :accIdSet];
        SalesPol.Primary_Customer_Service_Rep__c = Accts.Get(0).Customer_Service_Rep_Primary__c;
    }
}
I have a very simple trigger to do an update to a field called CTS_Rep__c. It is on a custom object and the trigger updates the field from the account object. The code is below.
trigger TOR_Update_CTS_Rep on Trial_Order_Request__c (before update, before insert) {

    //This trigger updates the CTS_Rep__c field from the Account CTS_Rep__c Field.
    //The lookup to account is based on the TOR field called Consignee_Ship_To_Name__c.
    //Note: By using the "before" trigger to modify the Trigger.new objects, you don't need 
    // to explicitly perform an update DML statement. When the trigger ends, it will implicitly 
    // update the data as you have modified the values 

    For (Trial_Order_Request__c newTOR : Trigger.new)
    {
        Account acc = 
            [Select ID, CTS_Rep__c from Account Where ID =: newTOR.Consignee_Ship_To_Name__c Limit 1];
        newTOR.CTS_Rep__c = acc.CTS_Rep__c;
        System.debug('In Trigger new tor= ' + newTOR.CTS_Rep__c);              
    } //End for Loop
}  //End of trigger
The trigger works fine on inserts and updates but when I wrote my test and ran that I ran into some problems. I am not getting the CTS_Rep__c field filled in. The trigger does not seem to save the data. My test code is below.
@ISTest public class TOR_CTS_Rep_Test {

 testMethod private static void runtests(){
        //In order for this test to work the three users Finance, Test User, and SysAdmin
        //must be opened and saved in prod so agent will get those last modified!!!
        //Also, Finance user contact created must = true and marked as an inactive user. 
        //SysAdmin and Test User contact created field must = false and marked active.        
        
        //create users
        List<User> theusers = Create_Accts_Contacts_From_Users_Test.buildUsers();
        //Use user0 for the account owner
        User User0 = theusers[0];
     	//Use user2 for the CTS Rep
     	User User2 = theusers[2];
     
        //create Account
        Account testacct = NewObjFactory.buildTestAcct(0, 'ABC Company', User0.id);
     	testacct.CTS_Rep__c = user2.id;
     	System.debug('acct CTS Rep = ' + testacct.CTS_Rep__c);
        insert testacct;
     
  		String theTORID;
     Test.startTest();
        // Create the Trial Order Request to test the insert of a new TOR with CTS Rep
        Trial_Order_Request__c TOR = NewObjFactory.buildtestTOR(0, testacct.id);
     	insert TOR;
     	theTORID=TOR.id;
     Test.stopTest();
     
     System.debug('TOR CTS Rep = ' + TOR.CTS_Rep__c);
     	//check to see if cts rep was added
        Trial_Order_Request__c TOR1 = [Select id, name, CTS_Rep__c
                       from Trial_Order_Request__c where ID =: theTORID ];
     System.debug('TOR1                    = ' + TOR1.CTS_Rep__c);
     System.debug('TOR                     = ' + TOR.CTS_Rep__c);
     System.debug('TOR1 Name                    = ' + TOR1.Name);
     System.assertEquals(TOR1.CTS_Rep__c,TOR.CTS_Rep__c);
 } //End runtests
}  //End test
When I run debug does not show the CTS_Rep__c as having any data. Below is the debug log.
User-added image
As you can see by the debug log, the ID for the CTS_Rep__c  is null. It pulls the correct data in name field so I know on my select statement that I am getting the correct record but again the CTS_Rep__c is null. Can anyone explain to me what I am doing wrong and how to correct the problem. Thank you.
I'm trying to test a trigger that runs on a before delete on an account. When I delete the account in the test I thought that the child contacts would be delete as well but that does not seem to be the case. I don't understand what I'd doing wrong here.
String testuser = UserInfo.getUserID();
        //set up the account
         Account testacct = NewObjFactory.buildTestAcct(0, 'Test Account1', testuser);
        insert testacct;
        Account testacct2 = NewObjFactory.buildTestAcct(0, 'Test Account2', testuser);
        insert testacct2;
        String accid = testacct.id;
         // Create the Contacts
        Contact testcontact = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'Joe');
        insert testcontact;
        String cid = testcontact.id;
        Contact testcontact2 = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'John');
        insert testcontact2;
        String c2id = testcontact2.id;
        Contact testcontact3 = NewObjFactory.buildTestContact(0, testacct.id, testuser, 'Cool', 'Paul');
        insert testcontact3;
        
        
        //Create the portal records
        Portal_User_Information__c pu1 = new Portal_User_Information__c();
        pu1.user_Name__c = testcontact.id;
        insert pu1;
        
        Portal_User_Information__c pu2 = new Portal_User_Information__c();
        pu2.user_Name__c = testcontact2.id;
        insert pu2;
        
        Portal_User_Information__c pu3 = new Portal_User_Information__c();
        pu3.user_Name__c = testcontact3.id;
        insert pu3;
        String pu3id = pu3.id;

		
        //run tests
        Account ac = [Select ID from account where id = :accid];
        Contact c1 = [Select ID from contact where id = :cid];
        Test.startTest();
        	Database.deleteResult result = Database.delete(ac, false);  //delete account rec
			Database.deleteResult result2 = Database.delete(c1, false);
        Test.stopTest();
        
        // Check data 
        system.debug('start');      
        System.assert(result.isSuccess());
        System.assert(result2.isSuccess());
        system.debug('acct del2');
        Contact[] c1s = [Select ID from contact where id = :cid];
        System.assertEquals(c1s.size(),0);

Below is my test method. The last assert fails.
I have a custom object (Portal_User__C) with a field called user_name__c. The user_name__c field has a master lookup relationship to the contact record. I have a before delete trigger on the Portal_User__c record that sends an email to the portal administrator. It works fine if I just delete the portal_user__c record. However; if I delete the contact record first, by design it does delete the portal_user__c record but the trigger does not work. Do I have to write two triggers?  (One for the contact record to check for portal_user__c records before it can be deleted. And a second one for the actual Portal_user__c.) Or how does that work?
Could someone help me write the test code for the below class. I am new at this and don't have a clue on how to write the code for emailing and batch process. What I have so far is below.


global class OpportunityNotices implements Database.Batchable<sObject>,Database.Stateful  
    {  
        Map<Id , List<Opportunity>> userOppMap {get; set;}
        List<Opportunity> allOppNotices {get; set;}
 
              
       global OpportunityNotices()  
       {  
       
           Date CalDate = date.Today().addDays(10);
           
           //Map to maintain user id and cases logged by them today  
           userOppMap = new Map<Id, List<Opportunity>>() ;  
             
           //All sales rep (System admins)  
           List<User> salesRep = new List<User>() ;  
           salesRep = [select id , name , Email from User where isactive = true] ;  
             
           //All sales rep ids  
           List<Id> salesIds = new List<Id>() ;  
           for(User ur : salesRep)  
           {  
               salesIds.add(ur.Id) ;  
           }  
            
           //find a list of Opportuntities with overdue est decision dates
        allOppNotices = new List<Opportunity>();
        allOppNotices = [SELECT Id, StageName, CloseDate, name, OwnerID
            FROM Opportunity 
            WHERE CloseDate <= : CalDate
            AND StageName != 'Closed Won'
            AND StageName != 'Closed Lost'
            Order By OwnerID, ID
        ]; 
  
       }  
      
       global Database.QueryLocator start(Database.BatchableContext BC)  
       {  
          //Creating map of user id with opportunities that are due or overdue  
          for(opportunity c : allOppNotices)  
          {  
              if(userOppMap.containsKey(c.ownerId))  
              {  
                  //Fetch the list of case and add the new case in it  
                  List<Opportunity> tempList = userOppMap.get(c.ownerId) ;  
                  tempList.add(c);  
                  //Putting the refreshed case list in map  
                  userOppMap.put(c.ownerId , tempList) ;  
              }  
              else  
              {  
                  //Creating a list of case and outting it in map  
                  userOppMap.put(c.ownerId , new List<Opportunity>{c}) ;  
              }  
          }  
      
          //Batch on all system admins (sales rep)  
          String query = 'select id , name , Email from User where isactive = true';  
          return Database.getQueryLocator(query);  
       }  
      
       global void execute(Database.BatchableContext BC, List<sObject> scope)  
       {  
             
          for(Sobject s : scope)  
          {  
              //Type cast sObject in user object  
              User ur = (User)s ;  
                
              //If system admin has logged any case today then only mail will be sent  
              if(userOppMap.containsKey(ur.Id))  
              {  
                  //Fetching all cases logged by sys admin  
                  List<Opportunity> allOppOfSalesRep = userOppMap.get(ur.Id) ;  
                    
                  String body = '' ;  
                  //Creating tabular format for the case details  
                  body = BodyFormat(allOppOfSalesRep) ;  
                    
                  //Sending Mail  
                  Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage() ;  
                    
                 //Setting user email in to address  
                  String[] toAddresses = new String[] {ur.Email} ;  
                    
                  // Assign the addresses for the To and CC lists to the mail object  
                  mail.setToAddresses(toAddresses) ;
                  //String[] ccAddresses = new String[] {'ekfree@wctc.net'}; 
                  //mail.setccaddresses(ccaddresses); 
                  mail.setreplyto('_DL_NP_SFDC_ADMIN@newpagecorp.com');
          
                  //Email subject to be changed  
                  mail.setSubject('Opportunity Due Notice');  
                    
                  //Body of email  
                  mail.setHtmlBody('Please review and update the opportunities listed below by updating the estimated decision date or closing the opportunity if it is no longer active. ' 
                   + '<br/> <br/> ' + body + '<br/> ' + 'Thank you.');  
              
                  //Sending the email  
                  Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });  
              }  
          }  
       }  
         
       public String BodyFormat(List<Opportunity> opps)  
       {  
           String str = '' ;
             
           for(Opportunity cs : opps)  
           {  
               Date dt = cs.closedate;
               String dateStr = DateTime.newInstance(dt.year(),dt.month(),dt.day()).format('MM/dd/yyyy');
             
               str += '<tr><td colspan="2">'+ cs.Name +'</td>'+'<td colspan="2">'+ dateStr +'</td>'+'<td>'+ '</td>'+'<td>'+ '</td>'+'</tr>' ;  
           }  
           str = str.replace('null' , '') ;  
           String finalStr = '' ;  
           finalStr = '<table border="  "> <td colspan="2">Name </td> <td colspan="2">Est. Decision Date  </td> '+'<td>'+ '</td>'+'<td>'+ '</td>'+ str +'</table>' ;  
           return finalStr ;  
       }  
      
       global void finish(Database.BatchableContext BC)  
       {  
           AsyncApexJob a = [Select id, status, numberoferrors, jobitemsprocessed,
               totaljobitems, createdby.email from AsyncApexJob where id = :BC.getjobid()];
           
           //send email
           Messaging.singleemailmessage mail = new messaging.singleemailmessage();
           string[] toadd = new string[] {'karol.freeberg@newpagecorp.com'};
           mail.settoaddresses(toadd);
           mail.setsubject('Opportunity Notices Job Completed ' + a.status);
           mail.setplaintextbody
               ('The batch apex job processed ' + a.totaljobitems + ' batches with ' + a.numberoferrors + ' failures.');
           messaging.sendemail (new messaging.singleemailmessage[] {mail});
       
       
       }  
      
    }



@isTest class OpportunityNoticesTest {

    Static testmethod void test() {
    
    //query used by the batch job
     String query = 'select id , name , Email from User where isactive = true';  
     
     //Test data
     Opportunity[] op = new List<opportunity>();
     For (integer i=0; i < 5;i++) {
     
        Opportunity o = new opportunity(
        Closedate  = date.Today().addDays(-16),
        StageName  = 'Target',
        Name = '2014-AARP' + i,
        reason_won_lost__C = 'Freight;History',
        annual_volume__c = 3,
        type = 'New Business',
        tons_won__c = 15,
        frequency__c = 'Spot',
        End_Use__c = 'This is the end use',
        start_Date__c = date.today());
        op.add(o);
     
     } //End for loop
     
     Test.starttest();
     Integer batchSize = 1;
     OpportunityNotices OppN = new OpportunityNotices();
     if(!Test.isRunningTest()){
         Database.executeBatch(OppN, batchSize);
     }
     
     Test.StopTest();
     
     
    
    
    } //End testmethod
    
}  //End


I have a nested list issue. I have two lists of IDs and I'm trying to combine them into one list so I can return the list and then split it back out after it is returned. This is what I have.

List<List<ID>> AllIDLists = New List<List<ID>>();
AllIDLists.add(mailToIds);
AllIdLists.add(WhatOppIDs);
Return AllIdLists;

So first I'm not sure that the list definition is correct. The definition should accomodate basically one list that contains 2 lists. 
My second question is then what is the best way to split the lists back out. My code for that is below.

List<ID> oppIdsList = New List<ID>{AllIdLists.get(0)};
List<ID> whatIdsList = New List<ID>{AllIdLists.get(1)};

Any help on what I am doing wrong here is appreciated. 
I am getting the following error and I am at a loss on what is wrong. Can anyone please help? The line of code with the error is underlined below.

11:00:01.063 (63040986)|USER_DEBUG|[23]|DEBUG|---------------------------------rows 3
11:00:01.063 (63047571)|SYSTEM_METHOD_EXIT|[23]|System.debug(ANY)
11:00:01.063 (63058551)|SYSTEM_METHOD_ENTRY|[26]|LIST<User>.iterator()
11:00:01.063 (63228660)|SYSTEM_METHOD_EXIT|[26]|LIST<User>.iterator()
11:00:01.063 (63259893)|SYSTEM_METHOD_ENTRY|[26]|system.ListIterator.hasNext()
11:00:01.063 (63295436)|SYSTEM_METHOD_EXIT|[26]|system.ListIterator.hasNext()
11:00:01.063 (63545352)|FATAL_ERROR|System.StringException: Invalid id:

List<String> userAcctNames = new List <String>();
       
        // Get all users modified in the last 3 days  
        User[] upusers = [Select ID, Department, Account_Name__c, contact_created__c,
                    LastModifiedDate From User Where LastModifiedDate >= :ckdt ];

        system.debug('---------------------------------rows ' + upusers.size());
       
       
        for (User theuser : upusers) {
             
            // Collect the IDs                                                                                 
            if (theuser.id != '') {
                userids.add(theuser.id);
                userAcctNames.add(theuser.Account_Name__c);
                system.debug('--------------------------------added ' + theuser.id + theuser.account_name__c);            
            }  //End if for collection of ids
         }  // end for loop

I'm trying to copy a new user as contact by using a trigger but I'm getting the following error

 

MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): Contact, original object: User

 

trigger Acceleration_User_Copyto_Contact on User (after insert, after update) {
    
   // Map<String,User> newLead = new Map <String, User>();
    
    system.debug('Acceleration_User_Copyto_Contact Trigger....');
 
    for ( User user : System.Trigger.new)
    {
        if  (user.Email.contains('acceleration'))
        {
            system.debug('Acceleration_User_Copyto_Contact Trigger..2.');
            Integer RecordCount = [select count() from Contact c where c.Email = : user.Email];
            
            system.debug('Acceleration_User_Copyto_Contact Trigger..2a .' + RecordCount);
            
            if (RecordCount == 0)
            {
                String AccountId = '';
                for ( Account a : [Select a.Id From Account a where Name = 'Acceleration']) 
                {
                    system.debug('Acceleration_User_Copyto_Contact Trigger..3.');
                     
                    AccountId = a.Id;
                
                    Contact con = New Contact();
                    con.AccountId = AccountId ;
                    con.Email = user.Email;
                    con.Firstname = User.Firstname;
                    con.Lastname = User.Lastname ;
                    con.User__c = User.Id;
                    insert con;
                }          
            }                   
        }
        
     }
    
    
}

 

Since I get very little satisifcation from asking for another 'feature request' let me outline my problems with the current mass emailer in salesforce.com, the world's leading CRM.
 
The mass emailer in salesforce is very weak and a big disappointment to me.   While I can live with the 1000 day restriciton (barely) I find the work flow process for keeping within that limit below par and not in keeping with costs of maintianing a salesforce account and its reputation as the #1 online CRM.
 
I am posting this message to help other newbies and those considering coming to the salesforce platform to help identify this issues earlier rather than later because they may not be immediately clear to you:
 
Problem #1:  1000 a day email limit; 30 000 per month.  Thus, if you have 50.000 contacts you will be forced to use a addon such as vertical response which exponentially increases your monthly costs.
 
Problem #2:  For some reason salesforce has made it unbelievably difficult to actaully define your views in order to meet the 250 limit. I will give you some examples of this strange situation:
 
A.  Suppose you generate a report showing all you all customers interested in a certain product between two price ranges.   The report neatly spits out the list and gives you a total.  You would think there would be a way to simply 'mass email'. But no, no such feature. And, anyway, if your results were over 250 you would not be able to filter them into the mass email feature anyway.
 
B. Ok, so know you have to use the mass email feature found under leads, contacts and accounts.  However, if you attempt to add it to an existing campaign which has exceed 250 you will not be able to do anything.
 
C. Your only option is to now create a 'view' and do a filtered search outlined in A. Fair enough.  However, if you will first notice that salesforce provides absolutely no TOTAL at the end of the view. Thus, you have no idea if you have exceeded your total. 
 
D. Ok, so now you create view and you hit mass email and go through the steps.  At step five it tells you oops sorry you have exceeded your limit but you have no idea by how much.
 
E. So now you think to yourself how do I actually meet this limit in a way that makes sense to me and my multiple users? So this is what support tells me:
 
"Create your view and then add a condition which only brings back first names with the letter 'a'."
 
Ok, so this may or may not keep you under 250 for this view. But remember, if you have a 5000 contacts you wish to send a notification to you will have to create views for just about every batch of three later alphabetic letters. 
 
Can you picture the mess of views that would entail? Can you imagine trying to maintain these cluster of views for each and every user and then trying to do a follow up campaign?  Virtually impossible.
 
F:  Additionally, if you try to use their so-called great 'campaign' feature to tie in the mass email you will be faced with a whole bunch of manual procedures require to 'update' the progress of the campaign.   I almost call this section unusable.
 
Conclusion #1: Salesforce have made it virtually impossible to use the mass email feature in terms of their restrictions. It is cumbersome, confusing and extremely limitiing. They do not easily give you mechanisms to meet the criteria or adjust the criteria or even provide a simple total in the adjusted views.
 
Conclusion #2: You are forced to now use a third party to get out of this mess. But before you do  this consider that every time you send a 250 emails through vertical response you will be charged 100 dollars.
 
Conclusion #3:  On the face of it, the on-demand solution appears very promising and elegant. But once you start using the salesforce system you realise you could spend a fortune trying do simple little things like elegantly manage a small mailing or even control duplicates in the system.
 
While I understand that salesforce  have built a business model around on-demand they should be obligated to allow fundamental features in the system such as easy to use and understand basic mass emailer and additionally control 'duplicates' in the system.
 
Surely any CRM worth its salt should have this capability built in.
 
And, please, do not talk to me about controlling spam and the problems of a blacklist.  I am very aware of this issue.   At the moment I cannot even do one newletter to my entire database which currently numbers 50,000. 
 
This is the way I see things.  A company should use a third party such as vertical response or client house to do the mass corporate mailings. However, an individual user should be able to quickly and easily do a small maling to some of his clients. At the moment there is no reporting or adjusting mechanism to meet this 250 limit. It is quite simply ridicolous, clunky and messy.
 
I would be interested to hear other points of views on this.
 
Edgline
 
 
 
 
 
 
 
 
 

Message Edited by EdgeLine on 08-28-2006 08:08 AM