• Kenneth Kimbrell
  • NEWBIE
  • 40 Points
  • Member since 2017

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 6
    Questions
  • 13
    Replies

I am working on trying to group my Event data with maps. What I am trying to accomplish is to group my Events in weeks > bookers > roll up count for booked appt for each week. My logic so far is:

map<string,list<Event>> Date2Event = new map<string,list<Event>>();
for(Event e: eventLst){
    if(!Date2Event.containsKey(dateMapKey(e.CreatedDate))){
         Date2Event.put(dateMapKey(e.CreatedDate), new list<Event>());
     }
     Date2Event.get(dateMapKey(e.CreatedDate)).add(e);
}

public string dateMapKey(datetime dt){
    	datetime myDt = dt;
    	date myDate = myDt.date();
    	date StartOfWeekDate = myDate.toStartOfWeek();
    	string mapKey = StartOfWeekDate.format() + '-' + StartOfWeekDate.addDays(6).format();
    	return mapKey;
}

So I have a function that is basically setting the map's key with a string of start date to end date. So far what I have accomplished is to group the events by week. Now I need to nest the grouping more and group by week and by bookers, then roll up count for each booked appt for that week. Any ideas would be greatly appreciated. Thanks.
public pageReference getData(){
    	date sd = date.parse(sDate).toStartOfWeek();
    	date ed = date.parse(eDate);
    	hList = new list<Hours__c>([SELECT Name,Employee__r.Id,Date_worked__c,Employee__r.Offshore__c,Employee__r.Name,Employee__r.Department__c,Employee_Name__c,hours__c,Minutes__c,Hours_Decimal__c FROM Hours__c WHERE Type_of_Hours__c = 'Work' AND Date_worked__c >= :sd AND Date_worked__c <= :ed AND Employee__r.Department__c IN :selected ORDER BY Employee__r.Department__c,Date_worked__c,Employee__r.Name LIMIT 3000]);
    	wrap = new list<wrapper>();
    	string tempDepartment;
    	string tempEmpName;
    	date tempWorkDate;
    	date tempStart = sd;
    	decimal offshore = 0;
    	decimal onshore = 0;
    	decimal totalOffshore = 0;
    	decimal totalOnShore = 0;
    	decimal dateCount = 0;
    	decimal aggreagteTotal = 0;
    	integer hitLimit = 3000;
    	integer rpwp = 0;
    	integer compareRPWP = 0;
    	boolean fired = false;
    	boolean dateChanged = false;
    	boolean dateCountis13 = false;
    	map<date,integer> mapDateCount = new map<date,integer>();
    	if(hList.size() > 0 && hList.size() < hitLimit){
        	noResults = false;
    		for(Hours__c h: hList){
	    		//initiate a new wrapper for each department as a primary header
	    		if( (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
	    			fired = true;
	    			tempDepartment = h.Employee__r.Department__c;
	    			wrap.add(new wrapper(null,null,null,null,null,tempDepartment,'','','',null,'',''));
	    		}else{
	    			fired = false;
	    		}
	    		if(fired || dateCountis13){
    				dateCountis13 = false;
    				dateCount = 0;
    				totalOffshore = 0;
    				totalOnShore = 0;
    			}
	    		//initiate a new wrapper for each new week period, total employee hours for each week period for each department
	    		if(fired || (h.Date_worked__c != null && ((tempWorkDate != null && tempWorkDate != h.Date_worked__c) || ( tempWorkDate == null)) ) || (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
	    			dateChanged = true;
	    			tempWorkDate = h.Date_worked__c;
	    			offshore = 0;
	    			onshore = 0;
	    			rpwp = 0;
	    			dateCount++;
	    			for(Hours__c h1: hList){
	    				//get count of each record that is inside a given week period
	    				if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Department__c == tempDepartment){
	    					rpwp++;
	    				}
	    				//logic for totaling offshore hours by date and department
	    				if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Offshore__c && h1.Employee__r.Department__c == tempDepartment){
	    					offshore += h1.Hours_Decimal__c != null ? h1.Hours_Decimal__c : 0;
	    				}
	    				//logic for totaling onshore hours by date and department
	    				if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Offshore__c == false && h1.Employee__r.Department__c == tempDepartment){
	    					onshore += h1.Hours_Decimal__c != null ? h1.Hours_Decimal__c : 0;
	    				}
	    			}
	    			system.debug('rpwp: ' + rpwp);
					wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,onshore,offshore,null,'total','','','',null,'',''));
					totalOffshore += offshore;
				    totalOnShore += onshore;
				    system.debug('OffShore: ' +  offshore + '  ' + tempWorkDate.format());
				    system.debug('OnShore: ' + onshore + '  ' + tempWorkDate.format());
    			}else{
    				dateChanged = false;
    			}
	    		//initiate a new wrapper for each record and give the ability to open and collapse all records under a given total week period
	    		// functionality now does an aggregate total of employee's that have multiple hour entrees for each week period.
	    		if( dateChanged || (h.Employee__r.Name != null && ((tempEmpName != null && tempEmpName != h.Employee__r.Name) || ( tempEmpName == null)) ) ){
	    			tempEmpName = h.Employee__r.Name;
	    			aggreagteTotal = 0;
	    			for(Hours__c h2: hList){
	    				if(tempEmpName == h2.Employee__r.Name && tempWorkDate == h2.Date_worked__c){
	    					aggreagteTotal += h2.Hours_Decimal__c;
	    				}
	    			}
	    			if(h.Employee__r.Offshore__c){
						wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,0,h.hours__c,aggreagteTotal,'collapse',h.Employee__r.Name,h.Employee__r.Id,h.Name,h.Employee__r.Offshore__c,h.Employee__r.Department__c,h.Date_worked__c.format() ));
					}else{
						wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,h.hours__c,0,aggreagteTotal,'collapse',h.Employee__r.Name,h.Employee__r.Id,h.Name,h.Employee__r.Offshore__c,h.Employee__r.Department__c,h.Date_worked__c.format() ));
					}
	    		}
				//compare record count on the outside loop to record count on the inner loop and set compare iterator to 0 if the date changes
				if(dateChanged){
					compareRPWP = 0;
				}
				compareRPWP++;
				system.debug('compareRPWP: ' +  compareRPWP );
				//if on the 13th week -- initiate a new wrapper and get quarterly totals -- compare record count so that inner loop matches outer loop
	    		if( (dateCount == 13 && compareRPWP == rpwp) ){
	    			system.debug('totalOffshore: ' +  totalOffshore );
		    		system.debug('totalOnShore: ' + totalOnShore );
	    			dateCountis13 = true;
	    			wrap.add(new wrapper(null,null,totalOnShore,totalOffshore,null,'quarter',tempDepartment,'','',null,'',''));
				}
	    	}
    	}else if(hList.size() <= 0){
    		noResults = true;
    		bannerMessage = 'Oops! No record found.';
    	}else if(hList.size() >= hitLimit){
    		noResults = true;
    		bannerMessage = 'Oops! 3000 Record limit hit.';
    	}else{
    		noResults = true;
    		bannerMessage = 'Oops! 50000 record limit hit.';
    	}
    	
    	system.debug('wrap: ' + wrap);
    	system.debug('hList: ' + hList);
    	return null;
    }


Here is my working method inside my class. Essentially I am doing a query on a custom object Hours__c. What I want to do is have the output on the table be first nested by each employee department. Then Nested by each work period, with all hours worked by that department for each work period. I essentially achieved this from the start by ordering the query that way. Now it was about how to make the logic grab it at the time I needed. But it also needed to aggregate the total hours if employees had more than one hour record per week period. I also finally after every 13 weeks output a total of hours for that quarter.

Here is a screencast of my custom report if you are interested in seeing what I achieved on the front-end but what I want to achieve on the backend and in a more effecient manner. The problem with my logic, is while it works, if there is a lot of data being queried. This logic is pretty slow. Because first it loops the query results once. but inside the first for loop I loop the same query 2 different times... ::slaps head:: ...I know it is terrible. 

So I want to see maybe if there is a more effecient way of achieving this with potentially a map or another wrapper class? Because it is all in one wrapper class too. I use front end logic to sort out the table based on results in the wrapper class. I just hide and show rows. Like i said, it works just not as effecient as I would like my logic to run.

here is the screen cast:

https://screencast-o-matic.com/watch/cF60cwYAiB

My goal is to query a list of Employee Hours. I need to order by both the department the Employee works for and the Work Date. Which is the ending date for the work week. I am trying to count hours for all employees that worked within a department and during the same week period. So In other words I will have a header of each department, and under that header will be a secondary header that seperates each work date. Nested within each secondary header would be each employee that worked during that work date.

I will attach an example of what I have so far and what I am trying to accomplish.User-added image
Here is my backend logic. I can figure out the front-end for collapsing the rows. I just want to know what are some best practices people use for grouping and counting rows based on specific groupings. e.g. grouped by department and dates, then getting totals of all hours within that specific grouped date.
 
public class CLS_managerReportOfEmployeeHours {	
	public string sDate {get;set;}
	public string eDate {get;set;}
	public string bannerMessage {get;set;}
	public list<string> primary {get;set;}
	public list<string> unselected {get;set;}
	public list<string> selected {get;set;}
	public list<Hours__c> hlist {get;set;}
	public list<wrapper> wrap {get;set;}
	public boolean validError {get;set;}
	public boolean noResults {get;set;}
	
	public class wrapper{
		public date startOfWeek {get;set;}
		public date dateWorked {get;set;}
		public decimal onShoreHours {get;set;}
		public decimal offShoreHours {get;set;}
		public string department {get;set;}
		public string empName {get;set;}
		
		public wrapper(date startOfWeek,date dateWorked,decimal onShoreHours,decimal offShoreHours,string department,string empName){
			this.startOfWeek = startOfWeek;
			this.dateWorked = dateWorked;
			this.onShoreHours = onShoreHours;
			this.offShoreHours = offShoreHours;
			this.department = department;
			this.empName = empName;
		}	
	}
	
	//constructor
    public CLS_managerReportOfEmployeeHours() {
    	validError = false;
    	unselected = new list<string>(getEmployeeDepartmentList());
		selected = new list<string>();
		primary = new list<string>(getEmployeeDepartmentList());
		noResults = true;
    }
    
    public pageReference updateFormValues(){
    	getdata();
    	return null;
    }
    public void getData(){
    	date sd = date.parse(sDate).toStartOfWeek();
    	date ed = date.parse(eDate);
    	hList = new list<Hours__c>([SELECT Date_worked__c,Employee__r.Offshore__c,Employee__r.Name,Employee__r.Department__c,Employee_Name__c,hours__c,Minutes__c FROM Hours__c WHERE Date_worked__c >= :sd AND Date_worked__c <= :ed AND Employee__r.Department__c IN :selected ORDER BY Employee__r.Department__c,Date_worked__c]);
    	wrap = new list<wrapper>();
    	string tempDepartment;
    	date tempWorkDate;
    	date tempStart = sd;
    	decimal offshore = 0;
    	decimal onshore = 0;
    	for(Hours__c h: hList){
    		//count hours of both offshore and onshore
    		if(Employee__r.Offshore__c){
    			offshore += offshore;
    		}else{
    			onshore += onshore;
    		}
    		
    		//initiate a new wrapper for each department as a primary header
    		if( (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
    			tempDepartment = h.Employee__r.Department__c;
    			wrap.add(new wrapper(null,null,null,null,tempDepartment,''));
    		}
    		//initiate a new wrapper for each new week period, total employee hours for each week period for each department
    		if( (h.Date_worked__c != null && ((tempWorkDate != null && tempWorkDate != h.Date_worked__c) || ( tempWorkDate == null)) ) || (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
    			system.debug('isfiring');
    			tempWorkDate = h.Date_worked__c;
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,onshore,offshore,'total',''));
    		}
    		//initiate a new wrapper for each record and give the ability to open and collapse all records under a given total week period
			if(h.Employee__r.Offshore__c){
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,0,h.hours__c,'collapse',h.Employee__r.Name));
			}else{
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,h.hours__c,0,'collapse',h.Employee__r.Name));
			}
    	}
    	if(wrap.size() <= 0){
    		noResults = true;
    	}else{
    		noResults = false;
    	}
    	system.debug('wrap: ' + wrap);
    	system.debug('hList: ' + hList);
    }
}

Any help would be appreciated thanks.

My issue: I built a trigger that assumed a 1:1 relationship with Student Accounts:AAC Accounts. The problem is now that we have discovered that AAC has multiple AAC accounts per student, why? Who knows it is the craziest thing I heard. So what I did is built a trigger that adds the additional AAC Customer Numbers to a long text area field called AAC_Additional_Customer_Numbers__c. This field now has data similar to this: 

6535965716,6535965736,6535966326

My existing trigger before discovering that I would need to look at multiple AAC numbers looks like this:

trigger TGR_Payment on Payment__c (before insert, before update) {
  set<string> aac = new set<string>();
  set<id> students = new set<id>();
  map<string,id> aacStudent = new map<string,id>();
  map<id,id> studentQuote = new map<id,id>();
  for(Payment__c p : trigger.New){
    if(p.AAC_Customer_Number__c != '' && p.AAC_Customer_Number__c != null){
      aac.add(p.AAC_Customer_Number__c);
    }
  }
  if(aac.size() > 0){
    for(Contact c : [SELECT Id, AAC_Customer_Number__c FROM Contact WHERE AAC_Customer_Number__c IN :aac]){
      students.add(c.Id);
      aacStudent.put(c.AAC_Customer_Number__c,c.Id);
    }
    if(students.size() > 0){
      map<id,date> latestDate = new map<id,date>();
      for(Quote__c q : [SELECT Id, Student__c, Sales_Reporting_Date__c FROM Quote__c WHERE Student__c IN :students AND Active__c = true AND Sales_Reporting_Date__c != null]){
        if(latestDate.get(q.Student__c) != null){
          if(q.Sales_Reporting_Date__c > latestDate.get(q.Student__c)){
            studentQuote.put(q.Student__c,q.Id);
            latestDate.put(q.Student__c,q.Sales_Reporting_Date__c);
          }
        }else{
          studentQuote.put(q.Student__c,q.Id);
          latestDate.put(q.Student__c,q.Sales_Reporting_Date__c);
        }
      }
    }
  }
  for(Payment__c p : trigger.New){
    if(p.AAC_Customer_Number__c != '' && p.AAC_Customer_Number__c != null){
      if(p.Student__c == null && aacStudent.get(p.AAC_Customer_Number__c) != null){
        p.Student__c = aacStudent.get(p.AAC_Customer_Number__c);
      }
      if(p.Quote__c == null && aacStudent.get(p.AAC_Customer_Number__c) != null && studentQuote.get(aacStudent.get(p.AAC_Customer_Number__c)) != null){
        p.Quote__c = studentQuote.get(aacStudent.get(p.AAC_Customer_Number__c));
      }
    }
  }
}

Can someone please help me with how I might integrate looking at multiple AAC numbers from a comma seperated list into this existing trigger. Before, I just mapped the Contact ID to the one AAC Customer Number. So when importing payments I just got the ID of the AAC Customer Number being imported because the AAC Customer Number was the key, and that is how I created the lookup for the student record. Problem is now, I can't just look for one, I need to look for many and then still be able to determine what Contact ID the AAC Customer Number is associated with. Any ideas? Thanks!

Here is what I am trying to accomplish:

Not sure the best way to ask this. But essentially I have a survey for instructors that a student submits during the mid-term. Each survey submission is of course a different record but the instructor and class would be the same. When querying results I only want to show one record for that teacher and class not multiple records from the same teacher and class. Also I want to count records that have a yes or no answer within a specific custom field. An example:

//Instrustor             //Registered                   //NumofYes      //NumOfNo    //total response
Course Becky         Gosky English Composition              1                5               6
Bobbie Strother      Developmental Psychology               1                6               7
Bobbie Strother      Anatomy & Physiology                   1                6               7
Bruce Priddy         Developmental Psychology               1                8               9
Christy Saladino     Developmental Psychology               3                7               10 
Christy Saladino     NCLEX Preparation                      1                9               10

Righ now my current code works, but only counts all responses. I was wondering what would be the best way to go about this without having to do multiple queries. My current method looks like this:

//Start a survey wrapper class
    public class SurveyWrapper{ 
        public End_Of_Class_Survey__c surveyObj {get;set;}
        public integer responseCount {get;set;}
        
        public SurveyWrapper(){
            surveyObj = new End_Of_Class_Survey__c();
            responseCount = 0;
        }
    }
    //Constructor Method
    public CLS_InstructorMidSurvey(){
        instructorName = '';
        courseName = '';
        getListOfInstructorAndCourses();
    }
    //main wrapper class method to getListOfInstructorAndCoursest
    public list<SurveyWrapper> getListOfInstructorAndCourses(){
   listOfSurveyData = new list<End_Of_Class_Survey__c>([SELECT Id, Question_1_Mid_Survey__c, Question_1B_Mid_Survey__c, Question_1A_MidSurvey__c, Instructor__c, Registered_Course__c 
                                                             FROM End_Of_Class_Survey__c 
                                                             WHERE Registered_Course__c != null AND Instructor__c != null 
                                                             ORDER BY Instructor__c]);
        listOfInstructorAndCourses = new list<SurveyWrapper>();
        mapOfSurveyData = new map<string, list<End_Of_Class_Survey__c>>();
        
        /*loop through list and find key values that contain both the instructor and the registered course.
         If map does contains(key) then get the key and add it to the lstSurveyData.
         Add the entire listOfSurveyData to the lstSurveyData
         Finally make the string a unique key in the map and add the lstSurveyData as its value.
         This will allow for a unique list and no repeat of records pertaining to the same course and instructor*/
        for(End_Of_Class_Survey__c e: listOfSurveyData){
            lstSurveyData = new list<End_Of_Class_Survey__c>();
            string key = e.Instructor__c + '-' + e.Registered_Course__c;
            
            if(mapOfSurveyData.containsKey(key)){
                lstSurveyData = mapOfSurveyData.get(key);
            }
            
            lstSurveyData.add(e);
            mapOfSurveyData.put(key,lstSurveyData);
        }
        //loop through the map's keyset
        for(string key: mapOfSurveyData.keySet()){
            //create a new wrapper object and add the values to the wrapper class
            SurveyWrapper wrapperObj = new SurveyWrapper();
            wrapperObj.surveyObj = mapOfSurveyData.get(key)[0];
            wrapperObj.responseCount = mapOfSurveyData.get(key).size();
            listOfInstructorAndCourses.add(wrapperObj);  
        }
        return listOfinstructorAndCourses;
    }
Any help would be greatly appreciated :)
Not sure the best way to ask this. But essentially I have a survey for instructors that a student submits during the mid-term. Each survey submission is of course a different record but the instructor and class would be the same. When querying results I only want to show one record for that teacher and class not multiple records from the same teacher and class. Here is an example:
 
    //Instrustor        //Registered Course
    Becky Gosky         English Composition                                            
    Bobbie Strother     Developmental Psychology                                            
    Bobbie Strother     Anatomy & Physiology                                            
    Bruce Priddy        Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    NCLEX Preparation



As you can see Bobbie teaches a class in Developmental Psychology and also in Anatomy and Physiology -- he has also received a survey review from a student in each.

Bruce Priddy teaches Developmental Psychology as well. 

Christy teaches Developmental Psychology too and has received 3 survey reviews and all 3 records are visible. I only want to output one record not multiple records that have the same instructor name and registered course. The reason why is for report user ability. I want to then add into a wrapper class the total response count for a specific instructor and and specific course.

I tried using a set, map, wrapper, etc... But the issue is instructor's names will be used more than once and so will the courses. So a set would not help. Unless I create a list, add the set to the new list, then make conditional statements and add to the list only when conditions are met. That way seems promising but I have not been able to completely make it work. Mostly because there is a time when both the instuctor and the course are in the set so I can no longer make a condition. I am convinced there has to be an easy way to just only output a record once if there are specified field names the same. I just can't seem to find a way. So I am reaching out to my community. Here is the method I am using:
 
public list<wrapper> getlistWrap(){
        wrap = new list<wrapper>();
        listSurveyData = new list<End_Of_Class_Survey__c>([SELECT        Id,Question_1_Mid_Survey__c,Question_1B_Mid_Survey__c,Question_1A_MidSurvey__c,Instructor__c,Registered_Course__c from End_Of_Class_Survey__c]);
        listInstructors = new list<Instructor__c>([SELECT Id, Name FROM Instructor__c]);
        getClassName  = new set<string>();
        getInstructorName = new set<string>();
        count = 0;
        for(integer i = 0; listSurveyData.size() > i; i++){
            if(listSurveyData[i].Instructor__c != '' && listSurveyData[i].Instructor__c != null){
                 getInstructorName.add(listSurveyData[i].Instructor__c);
            }
            if(listSurveyData[i].Registered_Course__c != '' && listSurveyData[i].Registered_Course__c != null){
                getClassName.add(listSurveyData[i].Registered_Course__c);
            }
        }
        listClassName = new list<string>(getClassName);
        instructorName = new list<string>(getInstructorName);   
        for(count = 0; listClassName.size() > count; count++ ){
            wrap.add(new wrapper(instructorName[count], listClassName[count]));  
        }
        return wrap;
}

 

I am working on trying to group my Event data with maps. What I am trying to accomplish is to group my Events in weeks > bookers > roll up count for booked appt for each week. My logic so far is:

map<string,list<Event>> Date2Event = new map<string,list<Event>>();
for(Event e: eventLst){
    if(!Date2Event.containsKey(dateMapKey(e.CreatedDate))){
         Date2Event.put(dateMapKey(e.CreatedDate), new list<Event>());
     }
     Date2Event.get(dateMapKey(e.CreatedDate)).add(e);
}

public string dateMapKey(datetime dt){
    	datetime myDt = dt;
    	date myDate = myDt.date();
    	date StartOfWeekDate = myDate.toStartOfWeek();
    	string mapKey = StartOfWeekDate.format() + '-' + StartOfWeekDate.addDays(6).format();
    	return mapKey;
}

So I have a function that is basically setting the map's key with a string of start date to end date. So far what I have accomplished is to group the events by week. Now I need to nest the grouping more and group by week and by bookers, then roll up count for each booked appt for that week. Any ideas would be greatly appreciated. Thanks.
My goal is to query a list of Employee Hours. I need to order by both the department the Employee works for and the Work Date. Which is the ending date for the work week. I am trying to count hours for all employees that worked within a department and during the same week period. So In other words I will have a header of each department, and under that header will be a secondary header that seperates each work date. Nested within each secondary header would be each employee that worked during that work date.

I will attach an example of what I have so far and what I am trying to accomplish.User-added image
Here is my backend logic. I can figure out the front-end for collapsing the rows. I just want to know what are some best practices people use for grouping and counting rows based on specific groupings. e.g. grouped by department and dates, then getting totals of all hours within that specific grouped date.
 
public class CLS_managerReportOfEmployeeHours {	
	public string sDate {get;set;}
	public string eDate {get;set;}
	public string bannerMessage {get;set;}
	public list<string> primary {get;set;}
	public list<string> unselected {get;set;}
	public list<string> selected {get;set;}
	public list<Hours__c> hlist {get;set;}
	public list<wrapper> wrap {get;set;}
	public boolean validError {get;set;}
	public boolean noResults {get;set;}
	
	public class wrapper{
		public date startOfWeek {get;set;}
		public date dateWorked {get;set;}
		public decimal onShoreHours {get;set;}
		public decimal offShoreHours {get;set;}
		public string department {get;set;}
		public string empName {get;set;}
		
		public wrapper(date startOfWeek,date dateWorked,decimal onShoreHours,decimal offShoreHours,string department,string empName){
			this.startOfWeek = startOfWeek;
			this.dateWorked = dateWorked;
			this.onShoreHours = onShoreHours;
			this.offShoreHours = offShoreHours;
			this.department = department;
			this.empName = empName;
		}	
	}
	
	//constructor
    public CLS_managerReportOfEmployeeHours() {
    	validError = false;
    	unselected = new list<string>(getEmployeeDepartmentList());
		selected = new list<string>();
		primary = new list<string>(getEmployeeDepartmentList());
		noResults = true;
    }
    
    public pageReference updateFormValues(){
    	getdata();
    	return null;
    }
    public void getData(){
    	date sd = date.parse(sDate).toStartOfWeek();
    	date ed = date.parse(eDate);
    	hList = new list<Hours__c>([SELECT Date_worked__c,Employee__r.Offshore__c,Employee__r.Name,Employee__r.Department__c,Employee_Name__c,hours__c,Minutes__c FROM Hours__c WHERE Date_worked__c >= :sd AND Date_worked__c <= :ed AND Employee__r.Department__c IN :selected ORDER BY Employee__r.Department__c,Date_worked__c]);
    	wrap = new list<wrapper>();
    	string tempDepartment;
    	date tempWorkDate;
    	date tempStart = sd;
    	decimal offshore = 0;
    	decimal onshore = 0;
    	for(Hours__c h: hList){
    		//count hours of both offshore and onshore
    		if(Employee__r.Offshore__c){
    			offshore += offshore;
    		}else{
    			onshore += onshore;
    		}
    		
    		//initiate a new wrapper for each department as a primary header
    		if( (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
    			tempDepartment = h.Employee__r.Department__c;
    			wrap.add(new wrapper(null,null,null,null,tempDepartment,''));
    		}
    		//initiate a new wrapper for each new week period, total employee hours for each week period for each department
    		if( (h.Date_worked__c != null && ((tempWorkDate != null && tempWorkDate != h.Date_worked__c) || ( tempWorkDate == null)) ) || (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
    			system.debug('isfiring');
    			tempWorkDate = h.Date_worked__c;
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,onshore,offshore,'total',''));
    		}
    		//initiate a new wrapper for each record and give the ability to open and collapse all records under a given total week period
			if(h.Employee__r.Offshore__c){
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,0,h.hours__c,'collapse',h.Employee__r.Name));
			}else{
				wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,h.hours__c,0,'collapse',h.Employee__r.Name));
			}
    	}
    	if(wrap.size() <= 0){
    		noResults = true;
    	}else{
    		noResults = false;
    	}
    	system.debug('wrap: ' + wrap);
    	system.debug('hList: ' + hList);
    }
}

Any help would be appreciated thanks.

My issue: I built a trigger that assumed a 1:1 relationship with Student Accounts:AAC Accounts. The problem is now that we have discovered that AAC has multiple AAC accounts per student, why? Who knows it is the craziest thing I heard. So what I did is built a trigger that adds the additional AAC Customer Numbers to a long text area field called AAC_Additional_Customer_Numbers__c. This field now has data similar to this: 

6535965716,6535965736,6535966326

My existing trigger before discovering that I would need to look at multiple AAC numbers looks like this:

trigger TGR_Payment on Payment__c (before insert, before update) {
  set<string> aac = new set<string>();
  set<id> students = new set<id>();
  map<string,id> aacStudent = new map<string,id>();
  map<id,id> studentQuote = new map<id,id>();
  for(Payment__c p : trigger.New){
    if(p.AAC_Customer_Number__c != '' && p.AAC_Customer_Number__c != null){
      aac.add(p.AAC_Customer_Number__c);
    }
  }
  if(aac.size() > 0){
    for(Contact c : [SELECT Id, AAC_Customer_Number__c FROM Contact WHERE AAC_Customer_Number__c IN :aac]){
      students.add(c.Id);
      aacStudent.put(c.AAC_Customer_Number__c,c.Id);
    }
    if(students.size() > 0){
      map<id,date> latestDate = new map<id,date>();
      for(Quote__c q : [SELECT Id, Student__c, Sales_Reporting_Date__c FROM Quote__c WHERE Student__c IN :students AND Active__c = true AND Sales_Reporting_Date__c != null]){
        if(latestDate.get(q.Student__c) != null){
          if(q.Sales_Reporting_Date__c > latestDate.get(q.Student__c)){
            studentQuote.put(q.Student__c,q.Id);
            latestDate.put(q.Student__c,q.Sales_Reporting_Date__c);
          }
        }else{
          studentQuote.put(q.Student__c,q.Id);
          latestDate.put(q.Student__c,q.Sales_Reporting_Date__c);
        }
      }
    }
  }
  for(Payment__c p : trigger.New){
    if(p.AAC_Customer_Number__c != '' && p.AAC_Customer_Number__c != null){
      if(p.Student__c == null && aacStudent.get(p.AAC_Customer_Number__c) != null){
        p.Student__c = aacStudent.get(p.AAC_Customer_Number__c);
      }
      if(p.Quote__c == null && aacStudent.get(p.AAC_Customer_Number__c) != null && studentQuote.get(aacStudent.get(p.AAC_Customer_Number__c)) != null){
        p.Quote__c = studentQuote.get(aacStudent.get(p.AAC_Customer_Number__c));
      }
    }
  }
}

Can someone please help me with how I might integrate looking at multiple AAC numbers from a comma seperated list into this existing trigger. Before, I just mapped the Contact ID to the one AAC Customer Number. So when importing payments I just got the ID of the AAC Customer Number being imported because the AAC Customer Number was the key, and that is how I created the lookup for the student record. Problem is now, I can't just look for one, I need to look for many and then still be able to determine what Contact ID the AAC Customer Number is associated with. Any ideas? Thanks!

Here is what I am trying to accomplish:

Not sure the best way to ask this. But essentially I have a survey for instructors that a student submits during the mid-term. Each survey submission is of course a different record but the instructor and class would be the same. When querying results I only want to show one record for that teacher and class not multiple records from the same teacher and class. Also I want to count records that have a yes or no answer within a specific custom field. An example:

//Instrustor             //Registered                   //NumofYes      //NumOfNo    //total response
Course Becky         Gosky English Composition              1                5               6
Bobbie Strother      Developmental Psychology               1                6               7
Bobbie Strother      Anatomy & Physiology                   1                6               7
Bruce Priddy         Developmental Psychology               1                8               9
Christy Saladino     Developmental Psychology               3                7               10 
Christy Saladino     NCLEX Preparation                      1                9               10

Righ now my current code works, but only counts all responses. I was wondering what would be the best way to go about this without having to do multiple queries. My current method looks like this:

//Start a survey wrapper class
    public class SurveyWrapper{ 
        public End_Of_Class_Survey__c surveyObj {get;set;}
        public integer responseCount {get;set;}
        
        public SurveyWrapper(){
            surveyObj = new End_Of_Class_Survey__c();
            responseCount = 0;
        }
    }
    //Constructor Method
    public CLS_InstructorMidSurvey(){
        instructorName = '';
        courseName = '';
        getListOfInstructorAndCourses();
    }
    //main wrapper class method to getListOfInstructorAndCoursest
    public list<SurveyWrapper> getListOfInstructorAndCourses(){
   listOfSurveyData = new list<End_Of_Class_Survey__c>([SELECT Id, Question_1_Mid_Survey__c, Question_1B_Mid_Survey__c, Question_1A_MidSurvey__c, Instructor__c, Registered_Course__c 
                                                             FROM End_Of_Class_Survey__c 
                                                             WHERE Registered_Course__c != null AND Instructor__c != null 
                                                             ORDER BY Instructor__c]);
        listOfInstructorAndCourses = new list<SurveyWrapper>();
        mapOfSurveyData = new map<string, list<End_Of_Class_Survey__c>>();
        
        /*loop through list and find key values that contain both the instructor and the registered course.
         If map does contains(key) then get the key and add it to the lstSurveyData.
         Add the entire listOfSurveyData to the lstSurveyData
         Finally make the string a unique key in the map and add the lstSurveyData as its value.
         This will allow for a unique list and no repeat of records pertaining to the same course and instructor*/
        for(End_Of_Class_Survey__c e: listOfSurveyData){
            lstSurveyData = new list<End_Of_Class_Survey__c>();
            string key = e.Instructor__c + '-' + e.Registered_Course__c;
            
            if(mapOfSurveyData.containsKey(key)){
                lstSurveyData = mapOfSurveyData.get(key);
            }
            
            lstSurveyData.add(e);
            mapOfSurveyData.put(key,lstSurveyData);
        }
        //loop through the map's keyset
        for(string key: mapOfSurveyData.keySet()){
            //create a new wrapper object and add the values to the wrapper class
            SurveyWrapper wrapperObj = new SurveyWrapper();
            wrapperObj.surveyObj = mapOfSurveyData.get(key)[0];
            wrapperObj.responseCount = mapOfSurveyData.get(key).size();
            listOfInstructorAndCourses.add(wrapperObj);  
        }
        return listOfinstructorAndCourses;
    }
Any help would be greatly appreciated :)
Not sure the best way to ask this. But essentially I have a survey for instructors that a student submits during the mid-term. Each survey submission is of course a different record but the instructor and class would be the same. When querying results I only want to show one record for that teacher and class not multiple records from the same teacher and class. Here is an example:
 
    //Instrustor        //Registered Course
    Becky Gosky         English Composition                                            
    Bobbie Strother     Developmental Psychology                                            
    Bobbie Strother     Anatomy & Physiology                                            
    Bruce Priddy        Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    Developmental Psychology                                            
    Christy Saladino    NCLEX Preparation



As you can see Bobbie teaches a class in Developmental Psychology and also in Anatomy and Physiology -- he has also received a survey review from a student in each.

Bruce Priddy teaches Developmental Psychology as well. 

Christy teaches Developmental Psychology too and has received 3 survey reviews and all 3 records are visible. I only want to output one record not multiple records that have the same instructor name and registered course. The reason why is for report user ability. I want to then add into a wrapper class the total response count for a specific instructor and and specific course.

I tried using a set, map, wrapper, etc... But the issue is instructor's names will be used more than once and so will the courses. So a set would not help. Unless I create a list, add the set to the new list, then make conditional statements and add to the list only when conditions are met. That way seems promising but I have not been able to completely make it work. Mostly because there is a time when both the instuctor and the course are in the set so I can no longer make a condition. I am convinced there has to be an easy way to just only output a record once if there are specified field names the same. I just can't seem to find a way. So I am reaching out to my community. Here is the method I am using:
 
public list<wrapper> getlistWrap(){
        wrap = new list<wrapper>();
        listSurveyData = new list<End_Of_Class_Survey__c>([SELECT        Id,Question_1_Mid_Survey__c,Question_1B_Mid_Survey__c,Question_1A_MidSurvey__c,Instructor__c,Registered_Course__c from End_Of_Class_Survey__c]);
        listInstructors = new list<Instructor__c>([SELECT Id, Name FROM Instructor__c]);
        getClassName  = new set<string>();
        getInstructorName = new set<string>();
        count = 0;
        for(integer i = 0; listSurveyData.size() > i; i++){
            if(listSurveyData[i].Instructor__c != '' && listSurveyData[i].Instructor__c != null){
                 getInstructorName.add(listSurveyData[i].Instructor__c);
            }
            if(listSurveyData[i].Registered_Course__c != '' && listSurveyData[i].Registered_Course__c != null){
                getClassName.add(listSurveyData[i].Registered_Course__c);
            }
        }
        listClassName = new list<string>(getClassName);
        instructorName = new list<string>(getInstructorName);   
        for(count = 0; listClassName.size() > count; count++ ){
            wrap.add(new wrapper(instructorName[count], listClassName[count]));  
        }
        return wrap;
}

 

I have no idea if this is the correct forum to post this in as it affects apex, visualforce, and sites. If the url parameter value contains the & symbol all parameters of the URL will be lost. For example:

 

 

PageReference page1 = new PageReference('http://www.test.com/page?name=Anderson And Smith');
system.debug(page1);

OUTPUT: System.PageReference[http://www.test.com/page?name=Anderson+And+Smith]



PageReference page2 = new PageReference('http://www.test.com/page?name=Anderson & Smith'); system.debug(page2); OUTPUT: System.PageReference[http://www.test.com/page]

 

URL encode the & symbol you might say. When I do this the symbol gets double encoded and then this causes issues:

 

 

 

PageReference page3 = new PageReference('http://www.test.com/page?name=Anderson %26 Smith');
system.debug(page3);

OUTPUT: System.PageReference[http://www.test.com/page?name=Anderson+%2526+Smith]

I'm sure part of the issue is that the & symbol is the designated seperator for URL params but there must be a way to adresss this problem, right?

 

Any ideas or solutions?

 

Thanks,

Jason