Friday, 17 November 2017

Task Custom Record Type Selection Lightning Component with Related(whatID) pre populate (force:createRecord event)

To Make Custom Record Type Selection Available for Users in Custom Components With force:createRecord i Have created below custom Lightning component . by using this when user create task from any object like Opportunity  it will navigate to Task Record Type Selection page , once he select recordtype it will open editable mode Task record with pre populated Relatedto field (opportunity).

Lightning component:
<aura:component controller="recordtypeController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
    <aura:handler name="init" value="{!this}" action="{!c.fetchListOfRecordTypes}"/>
    <aura:attribute name="lstOfRecordType" type="String[]" />
    <aura:attribute name="isOpen" type="boolean" default="false" />
    <aura:attribute name="recordId" type="String" />
  <div class="slds-m-around--x-large">
    <lightning:button label="Create a Task" onclick="{!c.openModal}" />
   <!-- Model Box Start -->    
    <aura:if isTrue="{!v.isOpen}">
        <div role="dialog" tabindex="-1" aria-labelledby="header43" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <div class="slds-modal__header">
                    <button class="slds-button slds-modal__close slds-button--icon-inverse" title="Close" onclick="{!c.closeModal}">
                        X<span class="slds-assistive-text">Cancel</span>
                    <h2 id="header43" class="slds-text-heading--medium">New Task</h2>
                <div class="slds-modal__content slds-p-around--medium">
                    <div class="slds-grid slds-wrap">
                        <div class="slds-size--1-of-2 slds-large-size--1-of-2">
                             <div class="slds-align--absolute-center">Select a Record Type</div>                            
                        <div class="slds-size--1-of-2 slds-large-size--1-of-2">
                            <ui:inputSelect aura:id="selectid">
                                <aura:iteration items="{!v.lstOfRecordType}" var="Objtask">                            
                                    <ui:inputSelectOption text="{!Objtask}" label="{!Objtask}"  />
                        </div>&nbsp; &nbsp;
                <div class="slds-modal__footer">
                    <lightning:button class="slds-button slds-button--neutral" onclick="{!c.closeModal}">Cancel</lightning:button>
                    <lightning:button class="slds-button slds-button--brand" onclick="{!c.createRecord}">Next</lightning:button>
        <div class="slds-backdrop slds-backdrop--open"></div>

Javascript controller:
   /* On the component Load this function call the apex class method, 
    * which is return the list of RecordTypes of object 
    * and set it to the lstOfRecordType attribute to display record Type values
    * on ui:inputSelect component. */
   fetchListOfRecordTypes: function(component, event, helper) {
      var action = component.get("c.fetchRecordTypeValues");
      action.setCallback(this, function(response) {
         component.set("v.lstOfRecordType", response.getReturnValue());
   /* In this "createRecord" function, first we have call apex class method 
    * and pass the selected RecordType values[label] and this "getRecTypeId"
    * apex method return the selected recordType ID.
    * When RecordType ID comes, we have call  "e.force:createRecord"
    * event and pass object API Name and 
    * set the record type ID in recordTypeId parameter. and fire this event
    * if response state is not equal = "SUCCESS" then display message on various situations.
   createRecord: function(component, event, helper) {
      component.set("v.isOpen", true);
      var action = component.get("c.getRecTypeId");
      var recordTypeLabel = component.find("selectid").get("v.value");
         "recordTypeLabel": recordTypeLabel
      action.setCallback(this, function(response) {
         var state = response.getState();
         if (state === "SUCCESS") {
            var createRecordEvent = $A.get("e.force:createRecord");
            var RecTypeID  = response.getReturnValue();
             var whatidvar  = component.get("v.recordId");
               "entityApiName": 'Task',
               "recordTypeId": RecTypeID,
                 'defaultFieldValues': {
                'WhatId': whatidvar

         } else if (state == "INCOMPLETE") {
            var toastEvent = $A.get("e.force:showToast");
               "title": "Oops!",
               "message": "No Internet Connection"
         } else if (state == "ERROR") {
            var toastEvent = $A.get("e.force:showToast");
               "title": "Error!",
               "message": "Please contact your administrator"
   closeModal: function(component, event, helper) {
      // set "isOpen" attribute to false for hide/close model box 
      component.set("v.isOpen", false);
   openModal: function(component, event, helper) {
      // set "isOpen" attribute to true to show model box
      component.set("v.isOpen", true);

Server side Controller :
public class recordtypeController {
    public static Map<Id, String> recordtypemap {get;set;}
    public static List<String> fetchRecordTypeValues(){
        List<Schema.RecordTypeInfo> recordtypes = Task.SObjectType.getDescribe().getRecordTypeInfos();    
        recordtypemap = new Map<Id, String>();
        for(RecordTypeInfo rt : recordtypes){
            if(rt.getName() != 'Master')
            recordtypemap.put(rt.getRecordTypeId(), rt.getName());
        return recordtypemap.values();
    public static Id getRecTypeId(String recordTypeLabel){
        Id recid = Schema.SObjectType.Task.getRecordTypeInfosByName().get(recordTypeLabel).getRecordTypeId();        
        return recid;

Test class:

public class recordtypeControllerTest {

static testmethod void testFetchRecordTypes() {
    List<String> values = recordtypeController.fetchRecordTypeValues();

 static testmethod void testgetRecordTypeId() {
    String recordTypeLabel = 'Test1';
    ID testId = recordtypeController.getRecTypeId(recordTypeLabel);
    System.assert(testId != null);


Tuesday, 23 May 2017

Custom approval process : to Add Custom fields to "Items to Approve" home page component

I  have approval process on Opportunity. my requirement is like to display custom field (TC Meeting Notes)to "Items to Approve" home page component, we can't customise this, but we can create a custom component for this behaviour using Visualforce.  i have created vf page apex class and
custom home page component .
here TC_Meeting_Notes__c is custom field from opportunity :
Idea link:

VF page:
<apex:page controller="ItemstoApprovvecontroller" sidebar="false" showHeader="false" tabStyle="Approver_Configuration__c" >
    <apex:form >
        <apex:pageBlock title="Items To Approve">
            <apex:pageBlockTable value="{!items_to_approve}" var="item_to_approve">
                <apex:column headerValue="Action" width="160 px" >
                                    <apex:commandLink target="_top" value="Reassign |" action="{!REASSIGNnavigation}" style="text-decoration:none;color: #015ba7;" styleClass="cactionLink">
                                                       <apex:param name="myParam" value="{!item_to_approve.approvalid }" />

                    <apex:commandLink target="_top" value=" Approve / Reject" action="{!ApproveRejectnavigation}" style="text-decoration:none;color: #015ba7;"  >

                   <apex:param name="myParam" value="{!item_to_approve.approvalid }" />

               <apex:column headerValue="Type"  width="100 px">
                    <apex:outputText >{!item_to_approve.objtype}
                <apex:column headerValue="Deal" width="300 px">
                    <apex:outputLink target="_top" value="/{!}">{!}
                <apex:column headerValue="TC Meeting Notes">
                    <apex:outputtext >{!item_to_approve.tcmeetingcomments}
                <apex:column headerValue="Date Submitted" width="150 px">
                    <apex:outputtext >{!item_to_approve.DateSubmited }

Apex class:
public class ItemstoApprovvecontroller {
    ApexPages.standardController stdController= null;
    public ItemstoApprovvecontroller(ApexPages.StandardController controller) {
    public opportunity Objectopportunity {get; set;}
    public List<opportunity> lstopportunityapprove {get; set;}
    ID Oppyid;
    Set<ID> oppyids=new Set<ID>();
    public class item_wrapper {
        public item_wrapper(id id,string name,string objtype,String DateSubmited,string tcmeetingcomments, id approvalid ) {
   = id;
   = name;
            this.objtype = objtype;
            this.DateSubmited = DateSubmited;
            this.approvalid =approvalid ;
        public id id { get; set; }
        public string name { get; set; }
        public string objtype { get; set; }
        public String DateSubmited { get; set; }
        public string tcmeetingcomments{ get; set; }
        public id approvalid { get; set; }
    public list<item_wrapper> items_to_approve { get; set; }
    public ItemstoApprovvecontroller() {
        items_to_approve = new list<item_wrapper>();
        map<id,ProcessInstanceWorkItem> mpaPIWIdToPIW = new map<id,ProcessInstanceWorkItem>();
        list<ProcessInstanceWorkItem> lstPIWI = [select processinstance.targetobjectid,CreatedDate ,,ProcessInstance.TargetObject.type from processinstanceworkitem where actorid = :userinfo.getuserid() Order by CreatedDate Desc];
            for(ProcessInstanceWorkItem item: lstPIWI) {
        map<id,Opportunity> mapoptyIdtoMeetingnotes = new map<id,Opportunity>();
            lstopportunityapprove=[select id,,name,Deal_Comments__c,stagename,TC_Meeting_Notes__c  from Opportunity where id in : oppyids];
                for(opportunity objoppy:lstopportunityapprove){
            for(ProcessInstanceWorkItem item: mpaPIWIdToPIW.values()) {
                String dateTimeValue = item.CreatedDate.format('MM/dd/yyyy hh:mm a');
                system.debug(dateTimeValue +'Debug2 dateTimeValue ');
                if(item.processinstance.TargetObject.type == 'Opportunity'){
                                    system.debug(item.processinstance.targetobjectid +'Debug2 dateTimeValue ');

                    items_to_approve.add(new item_wrapper(item.processinstance.targetobjectid,,item.processinstance.TargetObject.type,dateTimeValue ,mapoptyIdtoMeetingnotes.get(item.processinstance.targetobjectid).TC_Meeting_Notes__c, ));
                   system.debug(item.processinstance.targetobjectid +'Debug2 dateTimeValue ');

                    String sObjName = item.processinstance.targetobjectid.getSObjectType().getDescribe().getLabel();
                                                           system.debug(sObjName +'sObjNameValue ');

                    items_to_approve.add(new item_wrapper(item.processinstance.targetobjectid,,sObjName ,dateTimeValue ,'', ));
    public  static String ApproveRejectnavigation() {
        String url='';
        string myParam = apexpages.currentpage().getparameters().get('myParam');
        url='https://'+ System.URL.getSalesforceBaseUrl().getHost() +
            '/p/process/ProcessInstanceWorkitemWizardStageManager?id=' + myParam ;    
        return url;
    public  static String REASSIGNnavigation() {
        String url='';
        string myParam = apexpages.currentpage().getparameters().get('myParam');
        url='https://'+ System.URL.getSalesforceBaseUrl().getHost()+'/'+ myParam +'/e?et=REASSIGN';    
        return url;

Sunday, 23 April 2017

Opportunity Owner should get email notification when task is completed on opportunity

trigger NotifyOpportunityowner on Task ( after update) {
List<Task> taskList = new List<Task>();
Set<ID> taskIDSet = new Set<ID>();

if (trigger.old != null)
for (Task t: trigger.old)
}Set<String> strwhatIDs = new Set<String>();
set<Id> setClosedTaskId = new set<Id>();
Map<id,string> maprecortypes=new Map<id,string>();
Map<id,string> mapEmailAdress=new Map<id,string>();
Map<id,string> mapcurrentOwnerid=new Map<id,string>();
string[] toaddress = New String[] {};
for (Task t : (List<Task>) {
Task oldTask = (Task)trigger.oldMap.get(t.Id);
Task newTask = (Task)trigger.newMap.get(t.Id);
if(((oldTask.status != newTask.status) && t.status == 'Completed' )){

list<Task> lstTask = [select id,OwnerId,what.recordtype.developername, from Task where Id IN : setClosedTaskId ];

EmailTemplate objEt =  [select id,developername from EmailTemplate where developername ='Testing_vf_template'];
list<Opportunity> lstopt = [select id, from Opportunity where id IN: strwhatIDs];

for(Opportunity Opt : lstopt){


for(string str :mapEmailAdress.values()){
toaddress = New String[] {str};
List<Messaging.SingleEmailMessage> lstEmailId=new List<Messaging.SingleEmailMessage>();
Contact cont = [select id,name from contact limit 1];

for(Task tk : lstTask){
system.debug('toaddress exception'+toaddress);

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

}Catch(Exception ee){
system.debug('Print exception'+ee);


customize omni channel logic to distribute cases based on Case Creation Date

Omni Channel queues distributes cases, based on Date/Time the case is assigned to the queue. we can customize this logic to look for some ...