Saturday 14 December 2013

AutoClose Child Cases whenever a Parent Case is closed

This post is just to expose the way to auto close the child cases, whenever a parent for those child cases are closed, Just some simple workaround to achieve it .

In Case Object, i'm having many closed status vaues, i prefixed it by Closed as per my requirement .
And i dont want to update the already closed unnecesarily.

Code:
  1. Trigger AutoCloseChildCases on Case (after update) {
  2.   Case[] casesToUpdate = new Case[0];
  3. Set<Id>CaseSet = new Set<Id>();
  4. for (Integer c=0;c<Trigger.size;c++) {  
  5.     if ((Trigger.old[c].Status.contains('Closed')== false) && (Trigger.new[c].Status.contains('Closed')== true)) {
  6.   CaseSet.add(Trigger.New[c].Id);
  7.   }
  8.   }
  9.  
  10.   If(CaseSet.Size()>0){
  11.   Case[] cases = [select Id, Status, ParentId from Case where ParentId in:CaseSet];
  12.  
  13.   for (Integer i=0;i<Trigger.size;i++) {
  14.     if ((Trigger.old[i].Status.contains('Closed')== false) && (Trigger.new[i].Status.contains('Closed')== true)) {
  15.       for (Integer j=0;j<cases.size();j++) {
  16.         if (cases[j].ParentId == Trigger.new[i].Id) {
  17.           if(cases[j].Status.contains('Closed')==false)
  18.           {
  19.           cases[j].Status = 'Closed';
  20.           casesToUpdate.add(cases[j]);
  21.           }
  22.         } //end if
  23.       } //end for
  24.     } //end if
  25.   } //end for
  26. } //update the list
  27. if(casesToUpdate.size()>0){
  28.   update casesToUpdate;
  29.   }
  30. } //end trigger
..


Monday 25 November 2013

COUNT/ROLLUP No of Records with Multi Level Relatioinships using Trigger.

This is one of a very challenging requirment faced recently ,  I need to count the number of records and maintain the count in some other which has indirect relationship with this child object, the relationship hierarchy is just like the below one.

Example:

child  ----Lookup-----> Parent

Child Obj --> Parent Obj --> GrandParent Obj <-- Object X


  • child - online Application
  • Parent - Account
  • GrandParent - Parent Account
  • Object X - UR Account Goal
  • Field  in Online Application ---> Institution Account(Parent Account Id)(Formula field),it just populates the Parent id (Grandparent) in Online Application.

There are two types of child objects records, say one type is custom and another is standard, its just varied by using a picklist in the child object, each child object having only one parent and that parent having only one grandparent, and that grandparent is having only one ObjectX.

The twist here is, from child to grandparent, the relationship is just straight and inner level, but the destinatin object ,which needs to maintain the count of the child is related to the grandparent invertedly, as you can see above ,

What i needs to do is whenever a new child record introduces, i needs to increase the count in the Object X related to the childs-grandparent,In the Object X there is two fields named as standard count and custom count, which seperately maintains the count of  two different types of applications.

Another interest twist is i needs to write a trigger which also supports bulk/batch inserts/updates, so the challenge is if a batch inserts 200 records means, there may be a possibility of having multiple records for that child object, so the child record count is first needs to be done within that 200 records and after that i needs to append the count level in Object X.

Below is just my sample code to achieve this functionality,this can be achieved using the map concepts , I have tested the below code, it works perfectly as per the need and also supports bulk/batch inserts.

I have to tell this is not the best code, but it do the work,still trying to make this a best one and soon i will update the best ,suggestions are welcome.

Hope you understand the above requirement......


Trigger Code:


  1. Trigger CountTrigger on Online_Application__c (after insert, after update) {
  2. Set<String> InstAccSet = new Set<String>();
  3. Online_Application__c oldapp,newapp;
  4. Map<Id,UniversityRelationsAccountGoals__c> URGoalMap = new Map<Id,UniversityRelationsAccountGoals__c>();
  5. For(Online_Application__c oapp : Trigger.New){
  6. if(( Trigger.IsInsert && oapp.Offering__c!=null) || (Trigger.IsUpdate &&  oapp.Offering__c!=null &&Trigger.oldMap.get(oapp.Id).Type__c!=Trigger.newMap.get(oapp.Id).Type__c) ){
  7. InstAccSet.add(oapp.Institution_Account__c);
  8. }
  9. }
  10. If(InstAccSet.size()>0){
  11. List<UniversityRelationsAccountGoals__c> URGoalList = [Select Id,Account__c,AcademicTerm__c,Standard_Program_Count_Source__c,Custom_Program_Count_Source__c from UniversityRelationsAccountGoals__c where Account__c  IN: InstAccSet];
  12. For(Online_Application__c OnlineApp : Trigger.New){
  13. For(UniversityRelationsAccountGoals__c URGoalMapLoop: URGoalList){
  14.  if(OnlineApp.Institution_Account__c == URGoalMapLoop.Account__c ){
  15.          if(OnlineApp.Academic_Term__c == URGoalMapLoop.AcademicTerm__c ){
  16.          
  17.          if(URGoalMap.containsKey(URGoalMapLoop.Id)){
  18.          
  19.           if(OnlineApp.Type__c=='Custom'){  
  20.                         URGoalMapLoop.Custom_Program_Count_Source__c=URGoalMap.get(URGoalMapLoop.Id).Custom_Program_Count_Source__c+1;}
  21.                if(OnlineApp.Type__c=='Standard'){
  22.                         URGoalMapLoop.Standard_Program_Count_Source__c=URGoalMap.get(URGoalMapLoop.Id).Standard_Program_Count_Source__c+1;}
  23.                             URGoalMap.put(URGoalMapLoop.Id,URGoalMapLoop);
  24.          }
  25.          
  26.          else {
  27.                    if(OnlineApp.Type__c=='Custom'){  
  28.                         URGoalMapLoop.Custom_Program_Count_Source__c=URGoalMapLoop.Custom_Program_Count_Source__c+1;}
  29.                if(OnlineApp.Type__c=='Standard'){
  30.                         URGoalMapLoop.Standard_Program_Count_Source__c=URGoalMapLoop.Standard_Program_Count_Source__c+1;}
  31.          URGoalMap.put(URGoalMapLoop.Id,URGoalMapLoop);
  32.               }
  33. }
  34. }
  35. }
  36. }}
  37. update URGoalMap.values();


...

Dynamic Data passing from VisualForce page into the Apex Controller using a Apex checkbox coloumn

This post is just to expose the one of the way to sending a records/datas displayed in the visualforce page in to our apex controller, The data displaying in vf page is queried in the databased using the same apex controller, the point is to send the back the selected records from the overall queried records displayed in the visualforce page.
Generally this can be achieved by using wrapper class functionality of Apex, its a great functionality,as well as bit hard to understand and implement though, so below code is just some simple workaround to achieve this by the help of simple javascript.

The Below code just sending the selected records recordids to the apex controller seperated by commas, we can treat it as a set in apex class,the ids going to send can be displayed as alert message in visualforce page for the reference.

This is just the sample code to give you the idea, soon will post the complete workaround code.

VisualForce Code:
  1. <apex:page tabStyle="Task" sidebar="false" showHeader="false" id="page1" controller="clsSearchContact">
  2. <apex:form >
  3. <script>
  4. var flag=0;
  5. var SelectConId1='';
  6. function checkAll(cb)
  7. {    
  8.     flag=0;
  9.     SelectConId1='';
  10.     var inputElem = document.getElementsByTagName("input");
  11.     for(var i=1; i<inputElem.length; i++)
  12.     {
  13.         if(inputElem[i].id.indexOf("checkedone")!=-1)
  14.         {
  15.             inputElem[i].checked = cb.checked;
  16.             flag=flag+1;
  17.             SelectConId1=SelectConId1+inputElem[i].name+',';
  18.         }
  19.     }
  20.     if(cb.checked!=true)
  21.     {
  22.         SelectConId1="";
  23.         flag=0;
  24.     }
  25.     alert(SelectConId1);
  26.  
  27. }
  28.  
  29. function checkone(cb)
  30. {
  31.     var countchbox=0;
  32.    
  33.     if(cb.checked)
  34.     {  
  35.         flag=flag+1;
  36.         if((SelectConId1.length)<=1)
  37.         {
  38.             SelectConId1=cb.name+',';
  39.         }
  40.         else
  41.         {
  42.             SelectConId1=SelectConId1+cb.name+',';
  43.         }
  44.     }
  45.     else if((cb.checked)!=true)
  46.     {
  47.         flag=flag-1;
  48.         if((SelectConId1.length)<=1)
  49.         {
  50.             SelectConId1=cb.name+',';
  51.         }
  52.         else
  53.         {
  54.             var allids=SelectConId1.split(',');
  55.             var idarray='';
  56.             for(var i=0;i<allids.length;i++)
  57.             {
  58.                 if(allids[i]!=cb.name  && allids[i]!='')
  59.                 {
  60.                     idarray=idarray+allids[i]+',';
  61.                 }
  62.             }
  63.             SelectConId1=idarray;
  64.         }
  65.     }
  66.    
  67.      var inputElem = document.getElementsByTagName("input");
  68.     for(var i=0; i<inputElem.length; i++)
  69.     {
  70.         if(inputElem[i].id.indexOf("checkedone"))
  71.         {
  72.             countchbox=countchbox+1;
  73.         }
  74.     }
  75.     if(flag==countchbox-1)
  76.     {
  77.           document.getElementById("main").checked=true;
  78.     }
  79.     else
  80.     {
  81.          document.getElementById("main").checked=false;
  82.     }
  83.    alert(SelectConId1);
  84. }
  85.  
  86. function search_element()
  87. {
  88.     //alert('hello');
  89.     var element=document.getElementById("searchtext").value;
  90.    // alert(element);
  91.     searchelement(element);
  92.     return false;
  93. }
  94. function addtolist()
  95. {
  96.    
  97.     if((SelectConId1.length)<=1)
  98.     {
  99.         alert('Please select atleast one contact');
  100.         return false;
  101.     }
  102.     else
  103.     {
  104.         addtolistcontact();
  105.     }
  106. }
  107.  
  108. </script>
  109.  
  110.  
  111.     <apex:pageblock tabstyle="account">
  112.      <apex:pageBlockSection title="Select Multiple Contact"   collapsible="false" columns="1">
  113.      <Apex:pageBlock >
  114.            
  115.             <apex:pageBlockButtons location="both" >
  116.             <apex:outputLabel >&nbsp;</apex:outputLabel>
  117.                 <apex:commandButton onclick="return addtolist();" value="Add to List"/>
  118.                 <Apex:commandButton value="Done"  onclick="return closethis()"/>
  119.             </apex:pageBlockButtons>
  120.             <apex:outputPanel >
  121.                 <input type="text" id="searchtext"/>
  122.                 <apex:actionFunction immediate="true"  action="{!searchcontact}" reRender="pbtable"name="searchelement">
  123.                     <apex:param name="assignserach" value="" assignTo="{!searchfiled}"/>
  124.                 </apex:actionFunction>
  125.                 <apex:commandButton value="search" onclick="return search_element();" />
  126.             </apex:outputPanel>
  127.             <apex:pageBlockTable value="{!getconlist}" var="cc" id="pbtable">
  128.                 <apex:column >
  129.                     <apex:facet name="header">
  130.                         <input type="checkbox" id="main" onclick="return checkAll(this)"  />
  131.                        
  132.                     </apex:facet>
  133.                      <input type="checkbox" name="{!cc.id}" id="checkedone"  onclick="return checkone(this)"  />
  134.                     </apex:column>
  135.                 <div id="{!cc.id}">
  136.                 <apex:column >
  137.                     <apex:facet name="header" >Name</apex:facet>
  138.                     {!cc.name}
  139.                         </apex:column>
  140.                 <apex:column >
  141.                     <apex:facet name="header" >Title</apex:facet>
  142.                     {!cc.Title}
  143.                 </apex:column>
  144.  
  145.                   <apex:column >
  146.                      <apex:facet name="header" >Phone</apex:facet>
  147.                     {!cc.phone}
  148.                 </apex:column>
  149.                   <apex:column >
  150.                     <apex:facet name="header" >Email</apex:facet>
  151.                     {!cc.email}
  152.                 </apex:column>
  153.  
  154.                 <apex:column >
  155.                     <apex:facet name="header" >Account/Company</apex:facet>
  156.                     {!cc.account.name}
  157.                 </apex:column>
  158.                
  159.                 <apex:column >
  160.                     <apex:facet name="header" >Owner</apex:facet>
  161.                     {!cc.owner.name}
  162.                 </apex:column>
  163.                 </div>
  164.             </apex:pageBlockTable>
  165.      
  166.        
  167.        </Apex:pageBlock>
  168.        </apex:pageBlockSection>
  169.     </apex:pageblock>
  170.     </apex:form>
  171. </apex:page>


Apex Controller Code:
  1. public class clsSearchContact
  2. {
  3. public string searchfiled{get;set;}
  4. public list<contact> getconlist{get;set;}
  5.  
  6. public clsSearchContact()
  7. {
  8.     getconlist =new list<contact>();
  9.     getconlist=database.query('Select name,phone,email,account.name,title,owner.name from contact limit 10');
  10. }
  11.  
  12. public void searchcontact()
  13.     {
  14.          try
  15.          {
  16.        
  17.            searchfiled= '%'+searchfiled+ '%';
  18.              getconlist =new list<contact>();
  19.              getconlist=database.query('Select name,phone,email,account.name,title,owner.name from contact  WHERE Name like :searchfiled limit 100');
  20.            
  21.          }
  22.          catch(Exception e)
  23.          {
  24.              system.debug('Error'+e);
  25.          }
  26.     }
  27. }