• Eric Blaxton 11
  • NEWBIE
  • 155 Points
  • Member since 2018

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 26
    Questions
  • 29
    Replies
Hi and thanks in advance for any guidance.  

Background:  This code works great in getting a JSON response and creating cases.  The issues come when I schedule the class, as shown in my code snippet below, 'Class global class MaintenanceRequest_Sch implements Schedulable '.  It's calling the Asynchronous method in 'Maint. Request class.

Here's my code snippets:
 
public class MaintenanceRequest
{   
    // need this for scheduling callouts.
    @future(callout=true)
    public static void getMaintenanceTicketsAsync() 
    {
        getMaintenanceTickets();
    }
    
    public static void getMaintenanceTickets()
    {
        // Call public class ApiBearerKey to get new bearer key
        String tokenkey = ApiBearerKey.getBearerKey(); 
       
        // use Custom Settings in the future 
        String prdEndpoint = system.label.Portal_Prod_Endpoint;
        
        //Date variables for Endpoint
        //Put these in Custom settings, so I can adjust without redeploying
        Date d1= Date.today()-30;
        String geDate = DateTime.newInstance(d1.year(),d1.month(),d1.day()).format('YYYY-MM-dd');
        Date d2 = Date.today();
        String leDate = DateTime.newInstance(d2.year(),d2.month(),d2.day()).format('YYYY-MM-dd');
        String Jan12021 = '2021-01-01';//users only want to load cases with report date 1/1/2021 
        //Variable created to exclude all Cases with Short Description contains "Variance"
        String exclude1 = '\'Variance\'';
                         
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();   
       
        //Odata query.  We can get this running once Modified date is populated. 
        //req.setEndpoint(prdEndpoint + '?$filter=ODATA quere sample
        req.setTimeout(120000);       
        req.setMethod('GET'); 
        req.setHeader('Authorization', 'Bearer ' + tokenkey); 
                
        HTTPResponse res = h.send(req);   
        // This call returns 1.43 (1443502) MB.  Using Modified dates for 10 days
        Blob reqBody = res.getBodyAsBlob();
        system.debug('getsize ' + reqbody.size());
        system.debug('getsize ' + res);
        
        String strResponse = res.getBody();  
                
        if(res.getstatusCode() == 200 && res.getbody() != null)
            //system.debug('Response: ' + res.getBody());
            
        {           
            Map<String,Object> newMap = (Map<String, Object>)JSON.deserializeUntyped(strResponse); //strResponse gets top level and lower level details            
            //List of records passed.
            List<Object > valuelist = (List<Object>) newMap.get('value');
      
         createMaintCase.upsertCases(valuelist); 
}
}
global class MaintenanceRequest_Sch implements Schedulable {

    public void execute(SchedulableContext context)
    {
        MaintenanceRequest.getMaintenanceTicketsAsync();
    }
    
}
public class createMaintCase
{ 
    //List of Cases passed in from MaintenanceRequest.apxc
    //public static List<String> upsertCases(List <Object> caseList)
        
    public static void upsertCases(List <Object> caseList)
    {
        //system.debug('Case List ' + caseList);
        // Instantiate new list
        List<Case> toBeUpsertCases = new List<Case>();
        
        //List holding Maint Request Id's
        List<String> ticketIds = new List<String>();
        
        //List holding ticketIds, not to be confused with ticketId which holds maintrequestid's
        //List<String> listOfTicketIds = new List<String>();
        //
       Id caseMaintRecordTypeId = Schema.Sobjecttype.Case.getRecordTypeInfosByDeveloperName().get('SAP_Cases').getRecordTypeId();
        
        // Loop through list and load up received values in List toBeUpsertedCases
        Set<String> setReferenceId = new Set<String>();
        List<String> allids = new List<String>();
        system.debug('1st Case List: ' + caseList.size() );
        for(Object obj: caseList)
        {
            Map<String,Object> valueMap = (Map<String, Object> )obj; // all Values            
            
            Map<String,Object> locdetails  = (Map<String, Object>)valueMap.get('location'); // Location details            
            
            if(null != locdetails)
            {    
                // add Null check because some location details don't have a SAP Reference Id
                if (null != locdetails.get('sapReferenceId'))
                {
                    String sapReferenceId= String.valueOf(locdetails.get('sapReferenceId')); 
                                                   
                    if(null != sapReferenceId)
                     {
                      setReferenceId.add(sapReferenceId); // Load up sapReference Id's in Set
                      allids.add(sapReferenceId); // I load a map of all id's, but debug is forcefully truncated by SF.  Will need to store in an object or write to a file.
                     } 
                } 
            }
        } 
           
        if(!setReferenceId.isEmpty())
        {
            // put variables into custom setting.  to save from redeploying.  custom setting will allow
            //  me to vary sizes for testing.
            if (setReferenceId.size() > 25) {
                system.debug('setReferenceId.size: ' + setReferenceId.size());
                system.debug('caseList.size: ' + caseList.size());
				Database.executeBatch(new CreateMaintCase_Batch(setReferenceId, caseList), 25);
				return;                
            }
            
            //Fetching the assignment rules on case
               AssignmentRule AR = new AssignmentRule();
            // Get Case Active assignment rule
                AR = [Select id from AssignmentRule where SobjectType = 'Case' and Active = true limit 1];
                //Creating the DMLOptions for "Assign using active assignment rules" checkbox
                Database.DMLOptions dmlOpts = new Database.DMLOptions();
                dmlOpts.assignmentRuleHeader.assignmentRuleId= AR.id;
            
            Map<String,Account> mapReferenceIdVsAccount = new Map<String, Account>();
            //Map<String,Account> mapRefIdNotFound = new Map<String, Account>();
           //Load SAP Reference ID (Bus Loc) into Map
            for(Account acc: [Select Id, Name, AccountNumber From Account Where AccountNumber IN: setReferenceId])
            {              
                mapReferenceIdVsAccount.put(acc.AccountNumber , acc);
            }
                                  
            //System.debug('### mapReferenceIdVsAccount = '+ mapReferenceIdVsAccount);
            if(!mapReferenceIdVsAccount.isEmpty())
            {
                //This is where we pass caseList to batch class CreateMaintCase_Batch
                for (Object obj : caseList )
                {  
                    Map<String,Object> valueMap = (Map<String, Object> )obj;               
                    string ticketid= String.valueOf(valueMap.get('ticketId')); 
                    string shortDescription= String.valueOf(valueMap.get('shortDescription'));
                    string ticketNumber = String.valueOf(valueMap.get('ticketNumber')); 
                    string longDescription= String.valueOf(valueMap.get('longDescription'));                                      
                    Datetime reportDate; 
                    Datetime statusDate;
                    Datetime closeDate;
                    
                   //Create cases from JSON values
                        // Loop through and add case to List
                        toBeUpsertCases.add(newcase);
                        
                    }  //end if(mapReferenceIdVsAccount.containsKey(sapReferenceId)) 
                  }//end if (null != String.valueOf(locdetails.get('sapReferenceId')))
                  }
                }// end for (Object obj : caseList )
            }
        }    
        // Upsert Maint Request cases
        //system.debug('toBeUpsertCases: ' + toBeUpsertCases.size() );
        Schema.SObjectField f = Case.Ticket_ID__c; 
        if(!toBeUpsertCases.isEmpty()){
            Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);
            system.debug('CR from create maintenance case : ' + cr.size());
           
                             
    }// end public static void upsertCases(List <Object> caseList)
}// end public class createMaintCase
global class CreateMaintCase_Batch implements Database.Batchable<sObject>, Database.Stateful
{
    List<Case> toBeUpsertCases; 
    
    //Fetching the assignment rules on case
     AssignmentRule AR = new AssignmentRule();     
    
    string query;
    Set<String> setReferenceId;
    List <Object> caseList;
    String emailBody;
    Integer numberOfFailedCases;
    global CreateMaintCase_Batch(Set<String> setReferenceId, List <Object> caseList)
    {
        this.setReferenceId = setReferenceId;
        this.caseList = caseList;
        //Create Query
        query = 'Select Id, Name, AccountNumber From Account Where AccountNumber IN :setReferenceId';
        system.debug('Query ' + query);
        toBeUpsertCases = new List<Case>();
        emailBody = 'Failed Cases\n';
        numberOfFailedCases = 0;
    }
    
    //Makes it batchable
    global Database.QueryLocator start(Database.BatchableContext bc)
    {
        return Database.getQueryLocator(query);
    }
    
    //Execute code
    global void execute(Database.BatchableContext bc, List<Object> accounts)
    {
        // Get Case Active assignment rule
        AR = [Select id from AssignmentRule where SobjectType = 'Case' and Active = true limit 1];
        //Creating the DMLOptions for "Assign using active assignment rules" checkbox
        Database.DMLOptions dmlOpts = new Database.DMLOptions();
        dmlOpts.assignmentRuleHeader.assignmentRuleId= AR.id;
        
        Map<String, Account> mapReferenceIdVsAccount = new Map<String, Account>();
        for(Account acc: (List<Account>)accounts)
        {              
                mapReferenceIdVsAccount.put(acc.AccountNumber , acc);
        }
        
        Id caseMaintRecordTypeId = Schema.Sobjecttype.Case.getRecordTypeInfosByDeveloperName().get('SAP_Cases').getRecordTypeId();
       
                  //Populate cases off Json values

                        // Loop through and add case to List
                        toBeUpsertCases.add(newcase);
                        processedSapIds.add(sapReferenceId);
                        
                        // Stop once list sizes don't match
                        if (processedSapIds.size() == mapReferenceIdVsAccount.size()) {
                            break;
                        }
                    }  //end if(mapReferenceIdVsAccount.containsKey(sapReferenceId)) 
                  }//end if (null != String.valueOf(locdetails.get('sapReferenceId')))
                  }
                }// end for (Object obj : caseList )
        
        Schema.SObjectField f = Case.Ticket_ID__c; // This defines Ticket_Number__c as the External ID key
        system.debug('Before upsert: ' + tobeUpsertCases.size());
        if(!toBeUpsertCases.isEmpty()){
            Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);
            //Clear list before next batch processes
            tobeUpsertCases.clear();
            system.debug('After upsert: ' + tobeUpsertCases.size());
            
        
    }
    
    //Finish the Batch
    global void finish(Database.BatchableContext bc)
    {
        
    }
}





 
Hi and thanks in advance.
My goal is to speed up an area of my apex class.  I was told that deserializing in a loop causes drag.  

I can successfully deserialize a JSON string Date to a DateTime value like this:
reportDate= (DateTime)JSON.deserialize('"' + valueMap.get('reportDate') + '"', DateTime.class);
I tried using DateTime.valueof like this:
reportDate= datetime.valueof(valueMap.get('reportDate'));
Here's the error I get:
Line: 74, Column: 1
System.TypeException: Invalid date/time: 2020-12-28T11:33:31-06:00

Eric



 
Hi and thanks in advance.

I wrote an OData query and it worked until I added a Not Contains filter
String exclude = 'Variance';
and%20not%20contains(shortDescription,'+ exclude +')
Resulting query is:
not%20contains(shortDescription,Variance)
My question is how do I get single quotes around the variable.

Thank you,
Eric

 
Hi and thanks in advance for any help.
Situation:
I wrote a web service to grab new cases from an external source.  That part works fine, BUT an after update trigger fires when uploading new cases and i get a ''Apex CPU time limit exceeded".  I thought if I skipped the Record Type it would skip the trigger code. 
This line causes the error is the for loop, which occurs before the RT check:
for (Case cse : Trigger.new){
trigger CompleteResolutionTimeMilestone on Case (after update) {
    
    for (Case cse : Trigger.new){        
        system.debug('cse.RecordTypeId ' + cse.RecordTypeId);
        if (cse.RecordTypeId != Schema.Sobjecttype.Case.getRecordTypeInfosByDeveloperName().get('Maintenance').getRecordTypeId()){
          if (UserInfo.getUserType() == 'Standard'){
        
           DateTime completionDate = System.now(); 
              List<Id> updateCases = new List<Id>();
              for (Case c : Trigger.new){
                  if (((c.isClosed == true)||(c.Status == 'Closed'))&&((c.SlaStartDate 
                        <= completionDate)&&(c.SlaExitDate == null)))
            updateCases.add(c.Id);
                       }
    if (updateCases.isEmpty() == false)
        milestoneUtils.completeMilestone(updateCases, 'Support Resolution Time', completionDate);
    }
        }// end if (cse.RecordTypeId !=
    }
}
Regards,
Eric
 
Hi and thanks in advance for any help provided.

This is my second HTTP call. The call works, but I am confused on the stucture of the JSON.  I can successfully work with the "childWorkOrders", but I need to access the "workOrder", which is the Parent.  How would I do that?

JSON return:
{
    "status": "New",
    "shortDescription": "xxx",
    "description": "* 11/11/2020 13:12:53 CST  (SVCPOXPO) * xxx",
    "openedOn": "2020-11-11T13:12:53",
    "closeOn": "0002-11-30T00:00:00",
    "workOrder": {
        "parentWorkOrder": null,
        "assignedTo": "xxx",
        "openedOn": "2020-11-11T13:12:53",
        "lastUpdatedOn": "2020-11-11T13:44:20",
        "closeOn": "0002-11-30T00:00:00",
        "shortDescription": "xxx",
        "description": "xxx",
        "status": "Assigned",
        "workOrderNumber": "000007018372",
        "vendorName": null,
        "chargeBack": "0.00 ",
        "invoice": null
    },
    "childWorkOrders": [
        {
            "parentWorkOrder": "000007018372",
            "assignedTo": "xxx",
            "openedOn": "2020-11-11T15:18:59",
            "lastUpdatedOn": "2020-11-11T15:19:01",
            "closeOn": "0002-11-30T00:00:00",
            "shortDescription": "Dispenser",
            "description": null,
            "status": "Assigned",
            "workOrderNumber": "000007018381",
            "vendorName": null,
            "chargeBack": "0.00 ",
            "invoice": null
        }
    ]
}



APEX snippet:
HTTP h2 = new HTTP();
 HTTPRequest req2 = new HTTPRequest(); 
 // This gets the work orders.  The trick is to get the Maintenance Ticket ID into the ().  It would have to be a loop or something

  req2.setEndpoint(qaEndpoint + '(78401)/GetWorkOrders'); 
  req2.setTimeout(120000);       
  req2.setMethod('GET');        
 // QA Authorization
  req2.setHeader('Authorization', 'Bearer ' + tokenkey);  
  HTTPResponse res2 = h2.send(req2);
  String strResponse2 = res2.getBody();  
  if(res2.getstatusCode() == 200 && res2.getbody() != null)
            system.debug('Response: ' + res2.getBody());
        {           
            Map<String,Object> newMap2 = (Map<String, Object>)JSON.deserializeUntyped(strResponse2); //strResponse gets top level and lower level details            
           List<Object > valuelist2 = (List<Object>) newMap2.get('workOrder');            
              
            system.debug('valuelist2: ' + valuelist2);
        
            //Pass values to create/upsert cases (public class createMaintCase)
            //createMaintCase.upsertCases(valuelist);
            
         return null;
        } // end 2nd HTTPRequest
Error:  From line:
List<Object > valuelist2 = (List<Object>) newMap2.get('workOrder'); 

System.TypeException: Invalid conversion from runtime type Map<String,ANY> to List<String>

Regards,
Eric
 

 
Hi and thanks in advance,

Help with a test class.  Not sure what I am doing yet.  How do I get code coverage on this class.  
  1. Create users to test on.  u1 should be updated.  u2 should not be

Apex Class:
public class updateAdminEmailsonRefresh
{
    public static String getEmailAddress()
    { 
        // Instantiate List        
        List<User> emailAddress = new List<User>();
        
        // Get records to work with
        for(User email: [Select Id, Email, Name From User WHERE profileId = 'xxx' AND isActive = True AND email LIKE '%.invalid' ])
            {   
                String newEmail = String.valueOf(email.email);
                emailAddress.add(email);
                newEmail = newEmail.substring(0, newEmail.length()-8); //remove '.invalid'
                email.Email = newEmail;
            }        
               // update the email address
                update emailAddress;
                
        return null;
    }       
}

Test Class:
 
/*
Created by: Eric Blaxton

This test class covers the code coverage of following classes:
1. updateAdminEmailsonRefresh
*/
@IsTest (SeeAllData=false)
public class updateAdminEmailsonRefreshTest
{
 @IsTest   static  void testUsers()
 {
     //Get Profile id of Admin
     
     Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator'];
     
     List<User> emailAddress = new List<User>();
     
     
     // User email needs to be updated
     User u1 = new User(FirstName = 'Abel', LastName = 'Axiom', Alias = 'aaxio',Email = 'abel.axiom@sunoco.com.invalid',Username = 'abel.axiom@sunoco.com',CommunityNickname = 'aaxio', isActive = True,ProfileId = p.Id,
                    UserRoleId = '00Ed0000000S2ZS', ExternalSysID__c = 'abel.axiom@sunoco.com',Corporate_Office__c = 'DAL',EmailEncodingKey='UTF-8',
                    LanguageLocaleKey='en_US', TimeZoneSidKey='America/Chicago' ); 
     insert u1;
     
     User u2 = new User(FirstName = 'Bob', LastName = 'Builder', Alias = 'bbuil',Email = 'bob.builder@sunoco.com.invalid',Username = 'bob.builder@sunoco.com',CommunityNickname = 'bbuil', isActive = False,ProfileId = p.Id,
                    UserRoleId = '00Ed0000000S2ZS', ExternalSysID__c = 'bob.builder@sunoco.com',Corporate_Office__c = 'DAL',EmailEncodingKey='UTF-8',
                    LanguageLocaleKey='en_US', TimeZoneSidKey='America/Chicago' ); 
     insert u2;
                  
// In my mind, I create the users and i want to call the Apex class to run. What am I missing.  

     updateAdminEmailsonRefresh.getEmailAddress(); 
     
 }
}

Regards,
Eric
 
Hi and thanks in advance,

I have 2 goals here:
  • get a List Value and assign to a variable.
  • If record not found, do nothing, go to the next record. (This works)
Note: I can access the variable through acc.id if query without a list, but I get an error when a record is not found and it won't go to the next record. For example,
Account acc = [SELECT id, OwnerId, Name, AccountNumber FROM Account where AccountNumber =:ReferenceId];

Load list through query: (does not throw exception if record not found)
List<Account> acc = [SELECT id, OwnerId, Name, AccountNumber FROM Account where AccountNumber =:ReferenceId];
Access id value code (Does not work)
newcase.AccountId = acc.id;
Error:
Variable does not exist: id
Regards,
Eric


 
Hello and thanks in advance,

I am trying to store a DateTime value in a DateTime variable.  I've tried the valueofGMT and got an error also. 

Returned Value from HTTP request: 
"reportDate":"2020-11-04T13:51:16.4718777-06:00"

Line causing fatal error:
Datetime reportDate= Datetime.valueOf(valueMap.get('reportDate'));

Error Code: 
10:00:25:056 FATAL_ERROR System.TypeException: Invalid date/time: 2020-11-04T13:49:57.3103458-06:00
Regards,
Eric
 
Hi and thanks in advance.

I want to see the records that were created or updated via Database.UpsertResult.  The records are being updated and/or created, but I am not getting ANY results from the for loop. 

Any ideas?
 
Schema.SObjectField f = Case.Ticket_Number__c; 

       Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);  
        
        // I want to see what was updated / created        
        for(Integer index = 0; index < cr.size(); index++ )
        {
            if(cr[index].isSuccess())
            {
                if(cr[index].isCreated())
                {
                    System.debug(toBeUpsertCases[index].Ticket_Number__c + ' was created');
                } else 
                 {
                   System.debug(toBeUpsertCases[index].Ticket_Number__c + ' was updated'); 
                 }
            }
        }// end for loop

Eric
Hi and thanks in advance.

I am trying to get an access key and keep getting the "unsupported grant type" error.

I've verified I can access the url via Postman
User-added image

Apex class:
 
public class ApiBearerKey {
    public static String getBearerKey()
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://fakeaddress/token');
        request.setMethod('POST');
        
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setHeader('username','xxx'); 
        request.setHeader('password','xxx'); 
        request.setHeader('grant_type','password');

       
        request.setBody('');
        
        HttpResponse response = http.send(request);
        System.debug('Response : '+response.getBody());
        System.debug('UserInfo : '+UserInfo.getSessionID());
        
        return null;
    }
}
Appreciate the help.

Eric

 
Hi and thanks for any tips in advance.
First time writing a Get request. 

1. My Class:
public class MaintenanceTicket 
{
	public static String getMaintenanceTickets(string location )
    {
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();     
                    
        req.setEndpoint('https://api.fake/odata/AccountBalances?$expand=businessUnit&$count=true&$skip=0&$top=3');
      
        req.setTimeout(120000);    
            
        req.setMethod('GET');
       
       // QA Authorization
       req.setHeader('Authorization', 'Bearer ' + 'FakeID');
        HTTPResponse res = h.send(req);
        String strResponse = res.getBody();
        
        if(res.getstatusCode() == 200 && res.getbody() != null)
            system.debug('Response: ' + res.getBody());
        {
         //MAP<String,Object> jsonBody = (Map<String,Object>)Json.deserializeUntyped(res.getBody()); // pass data
        
         List<Object > jsonBody = (List<Object>) Json.deserialize(strResponse, List<Object>.class);
          
         system.debug('Got these values:');
         
         System.debug(jsonBody);
        
        String ticket = String.valueof(jsonBody);
                
        return ticket;
        
        }
                  
     } 
}
2. My Remote Site settings is accurate

3. My anonymous apex code:
String busloc = MaintenanceTicket.getMaintenanceTickets('385');
    System.debug(busloc);

4. Response body (system.debug):
13:10:22:633 USER_DEBUG [26]|DEBUG|Response: {"@odata.context":"http://api.fake/$metadata#AccountBalances(businessUnit())",
"@odata.count":xxx,
"value":[{"id":1,
"businessUnitId":xxx,
"charges":46536.710000,
"credits":-37741.810000,
"balance":8794.900000,
"effectiveDate":"2020-03-03T02:54:03.81-06:00",
"businessUnit":{"id":385,"transactionType":2,"billToNumber":&quot

5.  The error:
13:10:22:654 FATAL_ERROR System.JSONException: Malformed JSON: Expected '[' at the beginning of List/Set

13:10:22:000 FATAL_ERROR Class.System.JSON.deserialize: line 15, column 1

13:10:22:000 FATAL_ERROR Class.MaintenanceTicket.getMaintenanceTickets: line 30, column 1

Regards,
Eric
​​​​​​​

 
Hi and thanks in advance...

I found this class online without Test class.  The class works great and I found a Test class for it, but it doesn't work.  

I've included the Class and the Test Class and associated errors for test class

Class:
global class UnlockRecordBatchJob implements Database.batchable<sObject> {
    //Start of this batch job
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id FROM Case LIMIT 50000000 '; //50 Million records
        return Database.getQueryLocator(query);
    }
    //Exeution of batch job
    global void execute(Database.BatchableContext BC, List<Case> scope) { //Scope max = 2000
        //List<Case> caseList = [SELECT Id From CaseLimit 2]; case already in scope varible
        //Check locked records
        List<Case> caseLockList = new List<Case>();
        for(Case c : scope)
        {
            if(Approval.isLocked(c.id)){
                caseLockList.add(c);
            }
        }
        
        if(!caseLockList.isEmpty()){
            //Unlock records
            List<Approval.UnlockResult> ulrList = Approval.unlock(caseLockList, false);
            
            // Iterate through each returned result
            for(Approval.UnlockResult  ulr : ulrList) {
                if (ulr.isSuccess()) {
                    //Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully locked account with ID: ' + ulr.getId());
                }
                else {
                    //Operation failed, so get all errors                
                    for(Database.Error err : ulr.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Case fields that affected this error: ' + err.getFields());
                    }
                }
            }
        }
    }
    //finish job
    global void finish(Database.BatchableContext BC) {
    }
}
test Class:
@isTest
public class TestDemoTest {
    @isTest
    private static void testDemo(){
        List<Case> lcase=new List<Case>();
        for(integer i=0;i<10;i++){
            Case c=new Case();
            c.Status='New';
            c.Origin='Email';
            lcase.add(c);
            
        }
        insert lcase;
        List<Approval.LockResult> lrList = Approval.lock(lcase, false);
        Test.startTest();
        TestDemo td=new TestDemo();
        Database.executeBatch(td);
        Test.stopTest();
        
    }
}

The errors I get are:
Invalid type: TestDemo

Method does not exist or incorrect signature: void executeBatch(TestDemo) from the type Database



 
Hi and thanks in advance for any help.

I created a lightning component (Quick action).  How do I add a spinner while the code is doing it's job?  
 
Component

<aura:component controller="sendtoBrandQA" implements="force:lightningQuickActionWithoutHeader,force:hasRecordId,force:appHostable,flexipage:availableForAllPageTypes" >
	       
    <aura:attribute name="cse" type="Case"/> 
    <!--old way of passing to Controller and runs without interaction from user -->
    <!--<aura:handler name="init" value="{!this}" action="{!c.doInit}" /> -->  
    <!--shows/waits for outlined button to be pressed: "Send Brand QA email" -->
    <lightning:button variant="brand-outline" label="Send Brand QA Email" onclick="{!c.doInit}" />
    
     
</aura:component>
 
Controller:

({
       
    doInit : function(component, event, helper) 
    {         
        
        //Get Current user
        var userId = $A.get("$SObjectType.CurrentUser.Id"); 
        console.log("### userId = "+userId);
        var action = component.get("c.escalateCase");
        action.setParams({
            "objectId": component.get("v.recordId"),
            "userId" : userId            
        });
        
        
        action.setCallback(this, function(response){
            var state = response.getState();
           
            console.log("#### state = "+state);
            if(component.isValid() && state === "SUCCESS"){
                console.log("Hello 1");
                console.log("### response.getReturnValue() = "+JSON.stringify(response.getReturnValue()));
                var str = response.getReturnValue();
                console.log("#### str = "+ str);
                if(str == 'Item has been escalated!'){
                    console.log("#### success = "+str);
                    helper.toastMessage(str, 'success');
                    $A.get("e.force:closeQuickAction").fire();
                    
                }else{
                    console.log("#### error = "+str);
                    helper.toastMessage(str, 'error');
                    $A.get("e.force:closeQuickAction").fire();
                }
                
            }
        });
        
        $A.enqueueAction(action);
    }    
    
})
Helper:

({
    
 toastMessage : function(msg, type) 
    {        
        var toastEvent = $A.get("e.force:showToast");              
        toastEvent.setParams
        ({
            title : 'Brand QA Information',
            message: msg,
            duration:' 15000',
            key: 'info_alt',
            type: type,
            mode: 'dismissable'
        });
        toastEvent.fire();        
 }    
    
})

Regards,
Eric 
 
Hi and thanks in advance for any help / insight.

When I press send on the email action, I get the spinning wheel until I click refresh.  

Any ideas on what is slowing this down.  A caveat is that it doesn't happen all the time.

1. We have a quick email action
email case action2.  We have 3 fields predefined.
predefined fields
Hi and thanks in advance.  

This error is happening in a users browser when working on Case object in LEX. 

I've set up debug logs for the user and the  sf actions are processing fast, but the wheels keep on spinning for this one user.   

It's very inconsistent behavior.

It's causing user to get the "spinning wheels of death".

User-added image
Hi and thanks in advance.  

Converted to Lightning and having issues with VF command button.  

I've done research and cannot figure this one out.  I could create a lightning component, but don't want to change things too much.

Classic Behavior: the VFP resides in a page.  When the command button "add" is clicked, the page is does its thing and is refreshed within the parent page

Lightning Behavior:  the VFP looks great, but when the command button is clicked, a new window is opened up and I cannot get back to the parent Case easily.  I would like the same behavior as classic, if possible.

VF page
User-added image

VF code 
<apex:page tabStyle="Case" standardController="Case" extensions="AddFuelTypes"   lightningstylesheets="true">
    <!-- Case -->
    <style>
        .apexp .bPageBlock.apexDefaultPageBlock .pbBody .pbSubheader { 
            background-color: transparent;
            color: Black
        }
        body .bPageBlock, body #bodyCell .bResource .secondaryPalette, body .secondaryPalette.bPageBlock, body .individualPalette .secondaryPalette.bPageBlock, body .bodyDiv .genericTable, body .genericPageBlockTable, body .bodyDiv .bSubBlock, body .bComponentBlock .bPageBlock, body .bMyDashboard .bPageBlock, body.rlHoverFrame .bPageBlock, body.subjectSelectionPopup div.choicesBox, body.lookupTab .secondaryPalette.bPageBlock, body.popupTab .secondaryPalette.bPageBlock, body.UserTagStatsPage .secondaryPalette.bPageBlock {
            background-color: transparent;
            color: Black
        }
    </style>
    
    <apex:pageBlock >
        <apex:pageBlockSection title="Fuel Delivery Summary" columns="2" >
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Total Gallons Rq" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Total_Gallons_Rq__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Carrier Confirm Date/Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Carrier_Confirm_Date_Time__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Total Gallons Delivered" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Total_Gallons_Delivered__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Delivered Date/Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Delivered_Time__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Fuel Order Variance" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Fuel_Order_Variance__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Fuel Delivery Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Fuel_Delivery_Time__c}"/>
            </apex:pageBlockSectionItem>
            
        </apex:pageBlockSection>
    </apex:pageBlock>
    
    <!-- Add FuelType form -->
    <apex:form >
        <apex:pageBlock >
            <apex:pageMessages />
            <apex:pageBlockSection title="Add Fuel Types" columns="3">
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Fuel Type" style="font-weight:bold"/>
                    <apex:outputPanel styleClass="requiredInput" layout="block" id="pwPanel" >
                        <apex:outputPanel styleClass="requiredBlock"/>
                        <apex:selectList value="{!fuelObj.Fuel_Type__c}" size="1" required="true">
                            <apex:selectOptions value="{!FuelTypeOptions}"/>
                        </apex:selectList>
                    </apex:outputPanel>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Requested Gallons" style="font-weight:bold"/>
                    <apex:inputField value="{!fuelObj.Requested_Gallons__c}" required="true"/>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
            <div align="Center" draggable="false" >
                <apex:commandButton action="{!saveFuelType}" value="Add" reRender="" onclick="redirectTo('/apex/Add_Fuel_Types','');return true;" />
            </div>            
        </apex:pageBlock>
    </apex:form>
    <apex:form >
        <div name='rerender' style="overflow-x:auto; height: 200px;">
            <apex:pageBlock >
                <apex:pageBlockTable value="{!fuelTypes}" var="ft">
                    <apex:column value="{!ft.Fuel_Type__c}"/>
                    <apex:column value="{!ft.Requested_Gallons__c}"/>
                    <apex:column value="{!ft.Delivered_Gallons__c}"/>
                    <apex:column value="{!ft.Gallon_Variance__c}"/>
                    <apex:column value="{!ft.CreatedDate}"/>
                    <apex:column >
                        <apex:commandLink value="Remove"  action="{!removeFuelType}" >
                            <apex:param name="selectedFuelTypeId" value="{!ft.Id}"/>
                        </apex:commandLink>
                    </apex:column>
                </apex:pageBlockTable>
                  <apex:outputText rendered="{!fuelTypes.size==0}">
                      <table width="100%">
                          <tr ><th>Fuel Type</th>
                          <th>Requested Gallons</th>
                          <th>Delivered Gallons</th>
                          <th>Gallon Variance</th>
                          <th>Created Date</th>
                          </tr> 
                          <tr></tr>
                          <tr><td colspan="5" style="text-align:center;">No Records</td></tr>
                      </table>
                  </apex:outputText> 
            </apex:pageBlock>
        </div>
    </apex:form>    
</apex:page>

APEX Class
 
public class AddFuelTypes {
    public string result {get; set;}
    public Case caseObj {get; set;}
    public Fuel_Type__c fuelObj {get; set;}
    public List<Fuel_Type__c> fuelTypes {get; set;}
    public string selectedFuelTypeId {get; set;}      // Selected fuel Type
    public boolean haveFuelTypes {get; set;}    // Flag to display no schedule error message

    
    public AddFuelTypes(ApexPages.StandardController stdController){   
        this.caseObj = (Case)stdController.getRecord();  // Gets the current case working on.  Case has to be created first then add fuel types
        caseObj = [SELECT Old_Total_Gallons_Rq__c,SendtoTMW__c, Carrier_Confirm_Date_Time__c, Fuel_Order_Status__c, Fuel_Order_Variance__c, Delivered_Time__c,
                   Total_Gallons_Delivered__c, Total_Gallons_Rq__c,Fuel_Delivery_Time__c
                   FROM Case 
                   WHERE Id = :ApexPages.currentPage().getParameters().get('Id')];
        
        // Get fuel order information for current case
        fuelTypes = [SELECT Id, Fuel_Type__c, Requested_Gallons__c, Delivered_Gallons__c, 
                     Gallon_Variance__c, CreatedDate
                     FROM Fuel_Type__c 
                     WHERE Case__c = :caseObj.Id];
        
        fuelObj = new Fuel_Type__c();
        
        haveFuelTypes = false;
        if(fuelTypes.size() > 0) // Variable havefuelTypes starts as false.  Once fuel type added set to true
        {
            haveFuelTypes = true;
        }
        
        // Error messages
        selectedFuelTypeId = '';
        String temp=ApexPages.currentPage().getParameters().get('Status');
        if(temp!=NULL){
            if(temp.equals('false'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Duplicate fuel type cannot be entered. Please remove an existing type to add again.'));
            else if(temp.equals('CannotDelete'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Unable to delete, order is already Sent to TMW!'));
            else if(temp.equals('CannotAdd'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Unable to add, order is already Sent to TMW!'));
            else if(temp.equals('CannotBelower'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please enter a valid quantity larger than 0'));
            else if(temp.equals('CannotBeHigher'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please enter a valid smaller quantity'));
            else if(temp.equals('NotAllowed'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please select a valid Fuel Type'));
        }
    }
    
    public List<SelectOption> getFuelTypeOptions(){
       
       List<SelectOption> options = new List<SelectOption>();
       Schema.DescribeFieldResult fieldResult = Fuel_Type__c.Fuel_Type__c.getDescribe();
       List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
       for( Schema.PicklistEntry f : ple)
       {
               options.add(new SelectOption(f.getLabel(), f.getValue()));
       }     
       return options;
    }
    
    public PageReference saveFuelType(){
        
        result='true';
        fuelObj.Case__c = caseObj.id;
        if(fuelObj.Fuel_Type__c!=NULL){
            if(fuelObj.Fuel_Type__c.equals('None'))  // Error checking, Fuel Type cannot be None
                result='NotAllowed';}
        fuelTypes = [SELECT Id, Fuel_Type__c, Requested_Gallons__c, Delivered_Gallons__c, 
                     Gallon_Variance__c, CreatedDate
                     FROM Fuel_Type__c 
                     WHERE Case__c = :caseObj.Id];
        for(Fuel_Type__c ft : fueltypes) 
        {
          if(ft.Fuel_Type__c==fuelObj.Fuel_Type__c)
              result='false';
        }
        
            if(caseObj.SendtoTMW__c!=true)
            {   
                if(!result.equals('NotAllowed')){
                    if(result.equals('true')){  // Requested Gallons must be greater than 0 and less than 100,000 gallons.  Else throw error
                        if(fuelObj.Requested_Gallons__c>=1)
                        {   
                            if(fuelObj.Requested_Gallons__c<100000)
                                insert fuelObj;
                            else
                                result='CannotBeHigher';
                        }else
                            result='CannotBelower';
                    }else
                        result='false';
                }
            }
            else
                result='CannotAdd';
        // Redirect back to same page
        PageReference reRend = new PageReference('/apex/Add_Fuel_Types?id='+ caseObj.Id+'&Status='+result);
        reRend.setRedirect(true);
        return reRend;
    }
    
    public PageReference removeFuelType(){   //Error checking when Removing fuel type.  Fuel Types cannot be removed once order has been sent to TMW 
        
        selectedFuelTypeId = ApexPages.currentPage().getParameters().get('selectedFuelTypeId');   
        List<Fuel_Type__c> FuelTypesToBeRemoved = [SELECT Id, Fuel_Type__c FROM Fuel_Type__c
                                               WHERE Id = :selectedFuelTypeId];

        system.debug('FT Id ...........' + selectedFuelTypeId);
        system.debug('FT Control here ...........' + FuelTypesToBeRemoved);
        if(caseObj.SendtoTMW__c!=true)
            delete FuelTypesToBeRemoved;
        else
            result='CannotDelete';
        
        // Redirect back to same page
        PageReference reRend = new PageReference('/'+caseObj.Id);
        reRend.setRedirect(true);
        return reRend;
    } 
}



 
Hi and appreciate any insight on this.

My save button no longer works.  It was a VS button.  I made a new List View button calling VFP/ APEX  Not sure what went wrong here.  

Button
 
User-added image

VFP.
<apex:page standardController="Case" recordSetVar="cases" lightningStylesheets="true" extensions="setQuickCaseExtensionController"> 
    <apex:form >
        <apex:pageBlock title="Quick Case Entry" mode="edit">
            <apex:pageMessages id="showmsg"></apex:pageMessages>
            
            <apex:pageBlockSection title="Case Details" columns="1">                 
                                
              <apex:inputField label="Source Type" required="true" value="{!case.Source_Type__c}" /> 
              <apex:inputField label="Origin" required="true" value="{!case.Origin}"/>  
              <apex:inputField label="Contact" value="{!case.ContactId}"/> 
              <apex:inputField label="Subject" required="true" value="{!case.Subject}"/> 
              <apex:inputTextArea style="width:300px;height:100px" required="true" label="Description (Min 10 chars)"  value="{!case.Description}"/>
              <apex:inputField label="Category" required="true" value="{!case.Category__c}"/> 
              <apex:inputField label="Sub-Catagory 1" required="true" value="{!case.Sub_Catagory_1__c}"/>  
              <apex:inputField label="Sub-Catagory 2" required="true" value="{!case.Sub_Category_2__c}"/>  
              <apex:inputField label="Sub-Catagory 3" required="true" value="{!case.Sub_Category_3__c}"/>              
              <apex:inputField value="{!case.Related_Account__c}" label="Account"/>          
              <apex:inputField value="{!case.Incident_Occurence_Date__c}" label="Incident Occurrence Date"/>
              <apex:inputField value="{!case.Incident_Occurrence_Time__c}" label="Incident Occurrence Time"/>  
             </apex:pageBlockSection>   
            
            <apex:pageBlockButtons > 
                <apex:commandButton value="Save & Close Quick Case" action="{!save}"/> 
                <apex:commandButton value="Cancel" action="{!cancel}"/> 
            </apex:pageBlockButtons> 
                       
          
        </apex:pageBlock> 
    </apex:form>
</apex:page>

APEX Class

public class setQuickCaseExtensionController {
   private Case QC; 
   public ApexPages.StandardSetController stdController; 
   public setQuickCaseExtensionController(ApexPages.StandardSetController controller){
        controller.setPageSize(10);
        this.QC = (Case)controller.getRecord(); 
        RecordType RecId = new RecordType();
        RecId=[SELECT Id FROM RecordType where Name='Customer First' LIMIT 1];
        QC.RecordTypeId=RecId.Id;
        QC.Quick_Case__c = True;
        QC.Origin = 'Phone';
        QC.Source_Type__c = 'Consumer';
        QC.Description='Quick Case';
        QC.Quick_Case_Closed__c = True;
        QC.Subject='New Quick Case';
        stdcontroller=controller;        
    }

}
Hi and thanks for help in advance.

I need help to get better coverage.  I am at 73%.  There's about 6 lines i need help with.

///These 6 lines in the Apex Class below  arent covered.
                            cs.SendtoTMW__C = false;
                            result= 'There is no valid TMW Surrogate ID for this case';
                            return result;

                        }
                    }else{
                        cs.SendtoTMW__C = false;
                        result= 'There is no valid TMW Surrogate ID for this case';
                        return result; 


Apex Class:

public with sharing class SendtoTMW {
    
    @AuraEnabled  
    public static String getCurCase(Id caseId)
    {
        //Query current user profile id
        String result;
        Case cs =  [select id,SendtoTMW__c,SendtoTMWPerm__c,SFtoTMWSent__c,Origin,AccountId
                    FROM Case WHERE id = :caseId];
        System.debug('#### cs = '+ cs);
        if(cs != null){
            
            if (cs.AccountId == null) {
                cs.SendtoTMW__C = false;
                result= 'Order cannot be submitted to TMW.  Please enter an Account on the Case.';
                return result;
            } else{
                // Check if TMW surrogate ID exists in translation table
                //Id surrogateIds = '';
                //var surrogateIds = sforce.connection.query("SELECT Surrogate_ID__c FROM Translation_Table__c where IntegratedSite__c = '{!Case.AccountId}'"); //Commented this line out because it if user did not have rights to TT then would fail. This next line runs for all.
                List<Translation_Table__c> listTranslationTable = TMWSendOrderService.GetSurrogates(cs.AccountId);
                // I need to pass the case id here.  I'm getting a null return value.  This is what passes it to TMWSendOrderService and sends to TMW 
               // csid = TMWSendOrderService.SendOrderToTmw(cs.Id);
                System.debug('#### list trans table = '+ listTranslationTable);
                if(!listTranslationTable.isEmpty()){
                    if(null !=  listTranslationTable[0].Surrogate_ID__c){
                        String surrogateId = listTranslationTable[0].Surrogate_ID__c;
                        if(surrogateId.substring(0, 3) != 'TMW'){
///These 6 lines arent covered.
                            cs.SendtoTMW__C = false;
                            result= 'There is no valid TMW Surrogate ID for this case';
                            return result;

                        }
                    }else{
                        cs.SendtoTMW__C = false;
                        result= 'There is no valid TMW Surrogate ID for this case';
                        return result; 

                    }
                    
                }else{
                    cs.SendtoTMW__C = false;
                    result = 'There is no valid TMW Surrogate ID for this case';
                    return result;
                }
                if ((cs.Origin == 'TMWUI To Case' || cs.Origin == 'TMWFIX To Case' || cs.Origin == 'TMWFRCST To Case' || cs.Origin == 'TMWCarrierHUB To Case')) {
                    result= 'Order already submitted to or received from TMW. All updates are managed in TMW interface';
                    return result;
                }
                
                if ((cs.Origin != 'TMWUI To Case')) {
                    if (cs.Origin != 'TMWFIX To Case') {
                        if (cs.Origin != 'TMWFRCST To Case') {
                            if (cs.Origin != 'TMWCarrierHUB To Case') {
                                if (cs.SendtoTMW__C == true) {
                                    cs.SendtoTMW__C = false;
                                    result = 'Order already submitted to or received from TMW. All updates are managed in TMW interface.';
                                    return result;
                                }
                            }
                        }
                    }
                }
                Profile pr =  [Select Id, Name from Profile Where Id =: UserInfo.getProfileId() LIMIT 1]; 
                if(pr.Name == 'Transportation Mgmt'|| pr.Name == 'Transportation Team' || pr.Name == 'System Administrator')
                {
                    
                   System.debug('#### profile name = '+ pr);
                   System.debug('### test is running' + cs.SendtoTMW__C);
                    
                    if(Test.isRunningTest()){
                        System.debug('### test is running ' + cs.SendtoTMW__C);
                        cs.SendtoTMW__C = true;
                    }
                    
                    if (cs.SendtoTMW__C == false) {
                        
                        try
                        {
                            result =TMWSendOrderService.SendToTmw(cs.Id);
                           // System.debug('### send to tmw ' + cs.SendtoTMW__C);
                            return result;
                            
                            
                        }
                        catch(Exception ex)
                        {
                            result = ex.getMessage();
                           // System.debug('### send to tmw catch ' + cs.SendtoTMW__C);
                            return result;                            
                        }
                    }
                }                
            }           
        }else{            
        }        
        return null;
    }    
}

Test Class

@isTest
private class SendtoTMWTest 
{    
    // create test case
    @testSetup
    static void setupTestData(){
        test.startTest();
        Account ac=new Account(name='Test Account');
        Insert ac;
        Translation_Table__c translation_table_Obj = new Translation_Table__c(Integration_Status__c = false, IntegratedSite__c= ac.id, 
                                                                              Surrogate_ID__c='TMW-Test123');
        Insert translation_table_Obj; 
        test.stopTest();
    }
    
    //create Account and TT entry 
    @isTest
    static void getCurCase(){
        Account ac=new Account(name='Test Account');
        Insert ac;
        List<Translation_Table__c> translation_table_Obj  =  [SELECT Integration_Status__c, Name from Translation_Table__c];
        System.assertEquals(true,translation_table_Obj.size()>0);
        TMWSendOrderService obj01 = new TMWSendOrderService();
        TMWSendOrderService.OrderResponse obj11 = new TMWSendOrderService.OrderResponse();
        TMWSendOrderService.FuelOrdered obj21 = new TMWSendOrderService.FuelOrdered();
        TMWSendOrderService.TmwOrder obj31 = new TMWSendOrderService.TmwOrder();
        
        
        Case caseObj = new Case(accountId = ac.id, status='Open', 
                                Fuel_Order_Status__c = 'Pending',  
                                Origin = 'Phone',
                                RQ_Delivery_Date__c=system.Today(), 
                                RQ_Delivery_Timeframe__c='9am-3pm',
                                Description='testing fuel order');
        // Add all required field here
        insert  caseObj;
        SendtoTMW.getCurCase(caseObj.id);
        caseObj.AccountId = null;
        update caseObj;
        SendtoTMW.getCurCase(caseObj.id);
        
        caseObj.AccountId = ac.id;
        update caseObj;
        for(Translation_Table__c trans: translation_table_Obj){
            trans.IntegratedSite__c = ac.Id;
        }
        update  translation_table_Obj;
        SendtoTMW.getCurCase(caseObj.id);
       
        
        caseObj.SendtoTMW__c = true;
        update CaseObj;
        SendtoTMW.getCurCase(caseObj.id);
        
        caseObj.Origin ='TMWUI To Case';
        update caseObj;
        SendtoTMW.getCurCase(caseObj.id);
        
        caseObj.SendtoTMW__c = true;
        update CaseObj;
        SendtoTMW.getCurCase(caseObj.id);
        
         
        for(Translation_Table__c trans: translation_table_Obj){
            trans.IntegratedSite__c = ac.Id;
            trans.Surrogate_ID__c = null;
        }
        update  translation_table_Obj;
        SendtoTMW.getCurCase(caseObj.id);
        
        TMWSendOrderService obj = new TMWSendOrderService();
        TMWSendOrderService.SendToTmw(caseObj.id);
        
        Case cs =  [select id,SendtoTMW__c,SendtoTMWPerm__c,SFtoTMWSent__c,Origin,AccountId
                    FROM Case WHERE id = :caseObj.id];
        
        if(cs != null)
        {
            if (cs.AccountId == null)
            {
                cs.SendtoTMW__C = false;
                //result= 'Order cannot be submitted to TMW.  Please enter an Account on the Case.';
            }    
        }   // end if(cs != null)
    } //end static testMethod void getCurCase()
    
    @isTest
    static void getCurCase1(){
        Account ac=new Account(name='Test Account');
        Insert ac;
        List<Translation_Table__c> translation_table_Obj  =  [SELECT Integration_Status__c, Name from Translation_Table__c];
        System.assertEquals(true,translation_table_Obj.size()>0);
        
        
        Case caseObj = new Case(accountId = ac.id, status='Open', 
                                Fuel_Order_Status__c = 'Pending',  
                                Origin = 'Phone',
                                RQ_Delivery_Date__c=system.Today(), 
                                RQ_Delivery_Timeframe__c='9am-3pm',
                                Description='testing fuel order');
        // Add all required field here
        insert  caseObj;
        for(Translation_Table__c trans: translation_table_Obj){
            trans.IntegratedSite__c = ac.Id;
        }
        update  translation_table_Obj;
                SendtoTMW.getCurCase(caseObj.id);

        caseObj.SendtoTMW__c = true;
        update CaseObj;
        SendtoTMW.getCurCase(caseObj.id);                
    } //end static testMethod void getCurCase()       
}
 
Hi and thanks in advance for any pointers here.

Issue:  I created an Action button on the CASE object that calls a Lightning component.  When I click on the Add button, then click the Cancel button, the Add button is no longer there.  I have to click on another tab and then go back to the Case and then the Add button is there.

My component:
<aura:component controller="newCheckRequest" implements="force:lightningQuickActionWithoutHeader,force:hasRecordId,force:appHostable,flexipage:availableForAllPageTypes" >
    <!--This controls the display of the New Check Request action screen, before the New CR screen.  It supresses it.   -->
    <aura:html tag="style">
        .slds-backdrop {
        background: rgba(43, 40, 38, 0) !important;  
        }
      <!--  .slds-fade-in-open {
        display:none !important;-->
        
    </aura:html>  
    <aura:attribute name="cre" type="Check_Request__c"/>     
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
</aura:component>

My Controller:
({
    doInit : function(component, event, helper)
    {
       var action = component.get("c.getCase");
       action.setParams({"caseId": component.get("v.recordId")});
       action.setCallback(this, function(response)
       {
        var state = response.getState();
    
       if(component.isValid() && state === "SUCCESS") 
        {
        var  cre = response.getReturnValue();        
                 
            // create method in helper class
            // Putting RT first changes header of the pop up
            var createCrEvent = $A.get("e.force:createRecord");
            var crid=component.get("v.recordId");
            console.log('cre-'+cre);
            createCrEvent.setParams
             ({
                "entityApiName": "Check_Request__c",
                "defaultFieldValues":
                {
                    'Check_RequestRelTo__c' : cre.Id
                  
                }
              });
            createCrEvent.fire(); 
        }
                         
});          
       
     $A.enqueueAction(action);
      // $A.get("e.force:closeQuickAction").fire();
    }        
})

My Helper class: Not really needed, but maybe in the future
({
 toastMessage : function(msg) 
    {
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams
        ({
            title : 'Warning',
            message: msg,
            duration:' 5000',
            key: 'info_alt',
            type: 'error',
            mode: 'dismissible'
        });
        toastEvent.fire();
 }
})

My Apex class: to get the record id

public with sharing class newCheckRequest
{
 @AuraEnabled
    public static Case getCase(Id caseId) 
    {
        //Query fields from Parent record to prepopulate New CheckRequest
        return [SELECT Id,CaseNumber FROM Case where id = :caseId];     
    }
}

Thanks,
Eric
Hi and thanks in advance.

We are converting a url button to Lightning component.  I can get the url button to work in Lightning, but I don't have the control over pre populating fields etc.  I want to clear out a few fields.  This is a Clone account button which fires an Apex Class.  

The error I get when clicking the Action button is "Error while creating component for lightning component quick action [Unable to find action 'getAccount' on the controller of c:Clone]"

Please advise on where i went wrong.


I wrote a component

<aura:component controller="CloneAcctBtn" implements="force:lightningQuickActionWithoutHeader,lightning:isUrlAddressable,force:hasRecordId,lightning:hasPageReference,force:appHostable,flexipage:availableForAllPageTypes" >
    <!--This controls the display of the New RTO Quick action screen, before the New Account screen.  It supresses it.   
    <aura:html tag="style">
        .slds-backdrop {
        background: rgba(43, 40, 38, 0) !important;  
        }
        .slds-fade-in-open {
        display:none !important;
        }
    </aura:html>-->
    <aura:attribute name="acc" type="Account"/>     
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />    
         
</aura:component>

Controller:

({
    doInit : function(component, event, helper) 
    {
      var userId = $A.get("$SObjectType.CurrentUser.Id");   
      var action = component.get("c.getAccount");
      action.setParams({"accountId": component.get("v.recordId")});
      action.setCallback(this, function(response){
      var state = response.getState();   
     
      if(component.isValid() && state === "SUCCESS")
       {
        var  acc = response.getReturnValue(); 
        var createAcountEvent = $A.get("e.force:createRecord");
        var accid=component.get("v.recordId");
            
        console.log('accid-'+accid);
          //example set
          createAcountEvent.setParams({
              "entityApiName": "Account",
              "defaultFieldValues":{
          'Name': acc.sObjectInfo.Name,  
          'DataSrc__cSave' : acc.sObjectInfo.DataSrc__c, 
          'CMF_Bill_To_DUNS_Number__cSave' : acc.sObjectInfo.CMF_Bill_To_DUNS_Number__c,
          'Federal_Tax_ID_Number__cSave' : acc.sObjectInfo.Federal_Tax_ID_Number__c,
          'AccountNumberSave' : acc.sObjectInfo.AccountNumber
              }    
       });

        createAcountEvent.fire(); 
                    
        } 
        else
        {
        //write toast message replace the console.log
        helper.toastMessage('Problem getting account, response state');
        //console.log('Problem getting account, response state: ' + state);
        }
        });
        $A.enqueueAction(action);
    }
                    
 })

Class
    public with sharing class CloneAcctBtn {
@AuraEnabled
    public Account a;
    Map<String, Schema.SObjectField> m1 = Schema.SObjectType.Account.fields.getMap();
    string oldRecType;
    
    public CloneAcctBtn(ApexPages.StandardController stdController) {
        this.a = (Account)stdController.getRecord();
        oldRecType = a.RecordTypeId;
    
    }

    
    public Pagereference acctCloned(){//Account acct
        //find all record types
        List<Schema.RecordTypeInfo> infos = Schema.SObjectType.Account.RecordTypeInfos;
        Id defaultRecordTypeId;
        integer i = 0;
        
        String theId = ApexPages.currentPage().getParameters().get('id');
        system.debug(a + ' '+ theID);
        //a = [select id, name, BillingStreet from Account where id =:theId];
        
        /* query lead and then clone it */
        String soql = GrabUpdateableFieldsUtil.getCreatableFieldsSOQL('Account','id=\''+theId+'\'');
        if(Test.isRunningTest())
            System.debug('SOQL for clone: ' + soql);
        a = (Account)Database.query(soql);
        
        // Do all the dirty work we need the code
        Account clonedAcc = a.clone(false,true,false,false);
        
        //check each one
        for (Schema.RecordTypeInfo info : infos) {
            i++;
            if (info.DefaultRecordTypeMapping && info.isAvailable()) {
                defaultRecordTypeId = info.RecordTypeId;
            }
            
        }
        
        for(String fieldName : m1.keySet()) {
            if(m1.get(fieldName).getDescribe().isUpdateable()) {
                system.debug(m1.get(fieldName) + ' ' +m1.get(fieldName).getDescribe().getType() + ' '+m1.get(fieldName).getDescribe() );
                
                //get data types for each fields
                Schema.DisplayType fielddataType = m1.get(fieldName).getDescribe().getType();

                if(fielddataType  == Schema.DisplayType.Integer)
                {
                    clonedAcc.put(fieldName , 0);
                }
                else if(fielddataType != Schema.DisplayType.DateTime){
                    continue;
                }
                else if(fielddataType != Schema.DisplayType.Date){
                    clonedAcc.put(fieldName , date.valueof(system.today()));
                }
                else if(fielddataType != Schema.DisplayType.Double){
                    clonedAcc.put(fieldName , 0.0);
                }
                else if(fielddataType != Schema.DisplayType.Boolean){
                    clonedAcc.put(fieldName , true);
                }
                //else if(fielddataType != Schema.DisplayType.String){
                   // clonedAcc.put(fieldName , '');
               // }
                else
                   clonedAcc.put(fieldName , 'Some Value');
            }
        }
        //here is the default RecordType Id for the current user
        System.debug(defaultRecordTypeId);
        if(oldRecType != defaultRecordTypeId)
        {
            clonedAcc.Type__c = '';
        }
        clonedAcc.OwnerID = userinfo.getUserID();
        clonedAcc.Account_Status__c = 'Prospect';
        clonedAcc.RecordTypeId = defaultRecordTypeId;
        clonedAcc.ExternalSysID__c = ''; 
        clonedAcc.Bill_To_DUNs_Number__c = '';
        clonedAcc.accountnumber = '';
        clonedAcc.CMF_Bill_To_DUNS_Number__c = '';
        clonedAcc.CMF_Ship_To_DUNS_Number__c = '';
        
        insert clonedAcc;
        //System.assertEquals(a, clonedAcc); to do
        

        //Redirect the user back to the original page
        PageReference pageRef = new PageReference('/' + clonedAcc.id); 
        pageRef.setRedirect(true);
        return pageRef;   
        
        
    }

}
Hi and thanks in advance for any guidance.  

Background:  This code works great in getting a JSON response and creating cases.  The issues come when I schedule the class, as shown in my code snippet below, 'Class global class MaintenanceRequest_Sch implements Schedulable '.  It's calling the Asynchronous method in 'Maint. Request class.

Here's my code snippets:
 
public class MaintenanceRequest
{   
    // need this for scheduling callouts.
    @future(callout=true)
    public static void getMaintenanceTicketsAsync() 
    {
        getMaintenanceTickets();
    }
    
    public static void getMaintenanceTickets()
    {
        // Call public class ApiBearerKey to get new bearer key
        String tokenkey = ApiBearerKey.getBearerKey(); 
       
        // use Custom Settings in the future 
        String prdEndpoint = system.label.Portal_Prod_Endpoint;
        
        //Date variables for Endpoint
        //Put these in Custom settings, so I can adjust without redeploying
        Date d1= Date.today()-30;
        String geDate = DateTime.newInstance(d1.year(),d1.month(),d1.day()).format('YYYY-MM-dd');
        Date d2 = Date.today();
        String leDate = DateTime.newInstance(d2.year(),d2.month(),d2.day()).format('YYYY-MM-dd');
        String Jan12021 = '2021-01-01';//users only want to load cases with report date 1/1/2021 
        //Variable created to exclude all Cases with Short Description contains "Variance"
        String exclude1 = '\'Variance\'';
                         
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();   
       
        //Odata query.  We can get this running once Modified date is populated. 
        //req.setEndpoint(prdEndpoint + '?$filter=ODATA quere sample
        req.setTimeout(120000);       
        req.setMethod('GET'); 
        req.setHeader('Authorization', 'Bearer ' + tokenkey); 
                
        HTTPResponse res = h.send(req);   
        // This call returns 1.43 (1443502) MB.  Using Modified dates for 10 days
        Blob reqBody = res.getBodyAsBlob();
        system.debug('getsize ' + reqbody.size());
        system.debug('getsize ' + res);
        
        String strResponse = res.getBody();  
                
        if(res.getstatusCode() == 200 && res.getbody() != null)
            //system.debug('Response: ' + res.getBody());
            
        {           
            Map<String,Object> newMap = (Map<String, Object>)JSON.deserializeUntyped(strResponse); //strResponse gets top level and lower level details            
            //List of records passed.
            List<Object > valuelist = (List<Object>) newMap.get('value');
      
         createMaintCase.upsertCases(valuelist); 
}
}
global class MaintenanceRequest_Sch implements Schedulable {

    public void execute(SchedulableContext context)
    {
        MaintenanceRequest.getMaintenanceTicketsAsync();
    }
    
}
public class createMaintCase
{ 
    //List of Cases passed in from MaintenanceRequest.apxc
    //public static List<String> upsertCases(List <Object> caseList)
        
    public static void upsertCases(List <Object> caseList)
    {
        //system.debug('Case List ' + caseList);
        // Instantiate new list
        List<Case> toBeUpsertCases = new List<Case>();
        
        //List holding Maint Request Id's
        List<String> ticketIds = new List<String>();
        
        //List holding ticketIds, not to be confused with ticketId which holds maintrequestid's
        //List<String> listOfTicketIds = new List<String>();
        //
       Id caseMaintRecordTypeId = Schema.Sobjecttype.Case.getRecordTypeInfosByDeveloperName().get('SAP_Cases').getRecordTypeId();
        
        // Loop through list and load up received values in List toBeUpsertedCases
        Set<String> setReferenceId = new Set<String>();
        List<String> allids = new List<String>();
        system.debug('1st Case List: ' + caseList.size() );
        for(Object obj: caseList)
        {
            Map<String,Object> valueMap = (Map<String, Object> )obj; // all Values            
            
            Map<String,Object> locdetails  = (Map<String, Object>)valueMap.get('location'); // Location details            
            
            if(null != locdetails)
            {    
                // add Null check because some location details don't have a SAP Reference Id
                if (null != locdetails.get('sapReferenceId'))
                {
                    String sapReferenceId= String.valueOf(locdetails.get('sapReferenceId')); 
                                                   
                    if(null != sapReferenceId)
                     {
                      setReferenceId.add(sapReferenceId); // Load up sapReference Id's in Set
                      allids.add(sapReferenceId); // I load a map of all id's, but debug is forcefully truncated by SF.  Will need to store in an object or write to a file.
                     } 
                } 
            }
        } 
           
        if(!setReferenceId.isEmpty())
        {
            // put variables into custom setting.  to save from redeploying.  custom setting will allow
            //  me to vary sizes for testing.
            if (setReferenceId.size() > 25) {
                system.debug('setReferenceId.size: ' + setReferenceId.size());
                system.debug('caseList.size: ' + caseList.size());
				Database.executeBatch(new CreateMaintCase_Batch(setReferenceId, caseList), 25);
				return;                
            }
            
            //Fetching the assignment rules on case
               AssignmentRule AR = new AssignmentRule();
            // Get Case Active assignment rule
                AR = [Select id from AssignmentRule where SobjectType = 'Case' and Active = true limit 1];
                //Creating the DMLOptions for "Assign using active assignment rules" checkbox
                Database.DMLOptions dmlOpts = new Database.DMLOptions();
                dmlOpts.assignmentRuleHeader.assignmentRuleId= AR.id;
            
            Map<String,Account> mapReferenceIdVsAccount = new Map<String, Account>();
            //Map<String,Account> mapRefIdNotFound = new Map<String, Account>();
           //Load SAP Reference ID (Bus Loc) into Map
            for(Account acc: [Select Id, Name, AccountNumber From Account Where AccountNumber IN: setReferenceId])
            {              
                mapReferenceIdVsAccount.put(acc.AccountNumber , acc);
            }
                                  
            //System.debug('### mapReferenceIdVsAccount = '+ mapReferenceIdVsAccount);
            if(!mapReferenceIdVsAccount.isEmpty())
            {
                //This is where we pass caseList to batch class CreateMaintCase_Batch
                for (Object obj : caseList )
                {  
                    Map<String,Object> valueMap = (Map<String, Object> )obj;               
                    string ticketid= String.valueOf(valueMap.get('ticketId')); 
                    string shortDescription= String.valueOf(valueMap.get('shortDescription'));
                    string ticketNumber = String.valueOf(valueMap.get('ticketNumber')); 
                    string longDescription= String.valueOf(valueMap.get('longDescription'));                                      
                    Datetime reportDate; 
                    Datetime statusDate;
                    Datetime closeDate;
                    
                   //Create cases from JSON values
                        // Loop through and add case to List
                        toBeUpsertCases.add(newcase);
                        
                    }  //end if(mapReferenceIdVsAccount.containsKey(sapReferenceId)) 
                  }//end if (null != String.valueOf(locdetails.get('sapReferenceId')))
                  }
                }// end for (Object obj : caseList )
            }
        }    
        // Upsert Maint Request cases
        //system.debug('toBeUpsertCases: ' + toBeUpsertCases.size() );
        Schema.SObjectField f = Case.Ticket_ID__c; 
        if(!toBeUpsertCases.isEmpty()){
            Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);
            system.debug('CR from create maintenance case : ' + cr.size());
           
                             
    }// end public static void upsertCases(List <Object> caseList)
}// end public class createMaintCase
global class CreateMaintCase_Batch implements Database.Batchable<sObject>, Database.Stateful
{
    List<Case> toBeUpsertCases; 
    
    //Fetching the assignment rules on case
     AssignmentRule AR = new AssignmentRule();     
    
    string query;
    Set<String> setReferenceId;
    List <Object> caseList;
    String emailBody;
    Integer numberOfFailedCases;
    global CreateMaintCase_Batch(Set<String> setReferenceId, List <Object> caseList)
    {
        this.setReferenceId = setReferenceId;
        this.caseList = caseList;
        //Create Query
        query = 'Select Id, Name, AccountNumber From Account Where AccountNumber IN :setReferenceId';
        system.debug('Query ' + query);
        toBeUpsertCases = new List<Case>();
        emailBody = 'Failed Cases\n';
        numberOfFailedCases = 0;
    }
    
    //Makes it batchable
    global Database.QueryLocator start(Database.BatchableContext bc)
    {
        return Database.getQueryLocator(query);
    }
    
    //Execute code
    global void execute(Database.BatchableContext bc, List<Object> accounts)
    {
        // Get Case Active assignment rule
        AR = [Select id from AssignmentRule where SobjectType = 'Case' and Active = true limit 1];
        //Creating the DMLOptions for "Assign using active assignment rules" checkbox
        Database.DMLOptions dmlOpts = new Database.DMLOptions();
        dmlOpts.assignmentRuleHeader.assignmentRuleId= AR.id;
        
        Map<String, Account> mapReferenceIdVsAccount = new Map<String, Account>();
        for(Account acc: (List<Account>)accounts)
        {              
                mapReferenceIdVsAccount.put(acc.AccountNumber , acc);
        }
        
        Id caseMaintRecordTypeId = Schema.Sobjecttype.Case.getRecordTypeInfosByDeveloperName().get('SAP_Cases').getRecordTypeId();
       
                  //Populate cases off Json values

                        // Loop through and add case to List
                        toBeUpsertCases.add(newcase);
                        processedSapIds.add(sapReferenceId);
                        
                        // Stop once list sizes don't match
                        if (processedSapIds.size() == mapReferenceIdVsAccount.size()) {
                            break;
                        }
                    }  //end if(mapReferenceIdVsAccount.containsKey(sapReferenceId)) 
                  }//end if (null != String.valueOf(locdetails.get('sapReferenceId')))
                  }
                }// end for (Object obj : caseList )
        
        Schema.SObjectField f = Case.Ticket_ID__c; // This defines Ticket_Number__c as the External ID key
        system.debug('Before upsert: ' + tobeUpsertCases.size());
        if(!toBeUpsertCases.isEmpty()){
            Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);
            //Clear list before next batch processes
            tobeUpsertCases.clear();
            system.debug('After upsert: ' + tobeUpsertCases.size());
            
        
    }
    
    //Finish the Batch
    global void finish(Database.BatchableContext bc)
    {
        
    }
}





 
Hi and thanks in advance.

I wrote an OData query and it worked until I added a Not Contains filter
String exclude = 'Variance';
and%20not%20contains(shortDescription,'+ exclude +')
Resulting query is:
not%20contains(shortDescription,Variance)
My question is how do I get single quotes around the variable.

Thank you,
Eric

 
Hi and thanks in advance,

Help with a test class.  Not sure what I am doing yet.  How do I get code coverage on this class.  
  1. Create users to test on.  u1 should be updated.  u2 should not be

Apex Class:
public class updateAdminEmailsonRefresh
{
    public static String getEmailAddress()
    { 
        // Instantiate List        
        List<User> emailAddress = new List<User>();
        
        // Get records to work with
        for(User email: [Select Id, Email, Name From User WHERE profileId = 'xxx' AND isActive = True AND email LIKE '%.invalid' ])
            {   
                String newEmail = String.valueOf(email.email);
                emailAddress.add(email);
                newEmail = newEmail.substring(0, newEmail.length()-8); //remove '.invalid'
                email.Email = newEmail;
            }        
               // update the email address
                update emailAddress;
                
        return null;
    }       
}

Test Class:
 
/*
Created by: Eric Blaxton

This test class covers the code coverage of following classes:
1. updateAdminEmailsonRefresh
*/
@IsTest (SeeAllData=false)
public class updateAdminEmailsonRefreshTest
{
 @IsTest   static  void testUsers()
 {
     //Get Profile id of Admin
     
     Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator'];
     
     List<User> emailAddress = new List<User>();
     
     
     // User email needs to be updated
     User u1 = new User(FirstName = 'Abel', LastName = 'Axiom', Alias = 'aaxio',Email = 'abel.axiom@sunoco.com.invalid',Username = 'abel.axiom@sunoco.com',CommunityNickname = 'aaxio', isActive = True,ProfileId = p.Id,
                    UserRoleId = '00Ed0000000S2ZS', ExternalSysID__c = 'abel.axiom@sunoco.com',Corporate_Office__c = 'DAL',EmailEncodingKey='UTF-8',
                    LanguageLocaleKey='en_US', TimeZoneSidKey='America/Chicago' ); 
     insert u1;
     
     User u2 = new User(FirstName = 'Bob', LastName = 'Builder', Alias = 'bbuil',Email = 'bob.builder@sunoco.com.invalid',Username = 'bob.builder@sunoco.com',CommunityNickname = 'bbuil', isActive = False,ProfileId = p.Id,
                    UserRoleId = '00Ed0000000S2ZS', ExternalSysID__c = 'bob.builder@sunoco.com',Corporate_Office__c = 'DAL',EmailEncodingKey='UTF-8',
                    LanguageLocaleKey='en_US', TimeZoneSidKey='America/Chicago' ); 
     insert u2;
                  
// In my mind, I create the users and i want to call the Apex class to run. What am I missing.  

     updateAdminEmailsonRefresh.getEmailAddress(); 
     
 }
}

Regards,
Eric
 
Hi and thanks in advance,

I have 2 goals here:
  • get a List Value and assign to a variable.
  • If record not found, do nothing, go to the next record. (This works)
Note: I can access the variable through acc.id if query without a list, but I get an error when a record is not found and it won't go to the next record. For example,
Account acc = [SELECT id, OwnerId, Name, AccountNumber FROM Account where AccountNumber =:ReferenceId];

Load list through query: (does not throw exception if record not found)
List<Account> acc = [SELECT id, OwnerId, Name, AccountNumber FROM Account where AccountNumber =:ReferenceId];
Access id value code (Does not work)
newcase.AccountId = acc.id;
Error:
Variable does not exist: id
Regards,
Eric


 
Hello and thanks in advance,

I am trying to store a DateTime value in a DateTime variable.  I've tried the valueofGMT and got an error also. 

Returned Value from HTTP request: 
"reportDate":"2020-11-04T13:51:16.4718777-06:00"

Line causing fatal error:
Datetime reportDate= Datetime.valueOf(valueMap.get('reportDate'));

Error Code: 
10:00:25:056 FATAL_ERROR System.TypeException: Invalid date/time: 2020-11-04T13:49:57.3103458-06:00
Regards,
Eric
 
Hi and thanks in advance.

I want to see the records that were created or updated via Database.UpsertResult.  The records are being updated and/or created, but I am not getting ANY results from the for loop. 

Any ideas?
 
Schema.SObjectField f = Case.Ticket_Number__c; 

       Database.UpsertResult [] cr = Database.upsert(toBeUpsertCases, f, false);  
        
        // I want to see what was updated / created        
        for(Integer index = 0; index < cr.size(); index++ )
        {
            if(cr[index].isSuccess())
            {
                if(cr[index].isCreated())
                {
                    System.debug(toBeUpsertCases[index].Ticket_Number__c + ' was created');
                } else 
                 {
                   System.debug(toBeUpsertCases[index].Ticket_Number__c + ' was updated'); 
                 }
            }
        }// end for loop

Eric
Hi and thanks in advance.

I am trying to get an access key and keep getting the "unsupported grant type" error.

I've verified I can access the url via Postman
User-added image

Apex class:
 
public class ApiBearerKey {
    public static String getBearerKey()
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://fakeaddress/token');
        request.setMethod('POST');
        
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setHeader('username','xxx'); 
        request.setHeader('password','xxx'); 
        request.setHeader('grant_type','password');

       
        request.setBody('');
        
        HttpResponse response = http.send(request);
        System.debug('Response : '+response.getBody());
        System.debug('UserInfo : '+UserInfo.getSessionID());
        
        return null;
    }
}
Appreciate the help.

Eric

 
Hi and thanks for any tips in advance.
First time writing a Get request. 

1. My Class:
public class MaintenanceTicket 
{
	public static String getMaintenanceTickets(string location )
    {
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();     
                    
        req.setEndpoint('https://api.fake/odata/AccountBalances?$expand=businessUnit&$count=true&$skip=0&$top=3');
      
        req.setTimeout(120000);    
            
        req.setMethod('GET');
       
       // QA Authorization
       req.setHeader('Authorization', 'Bearer ' + 'FakeID');
        HTTPResponse res = h.send(req);
        String strResponse = res.getBody();
        
        if(res.getstatusCode() == 200 && res.getbody() != null)
            system.debug('Response: ' + res.getBody());
        {
         //MAP<String,Object> jsonBody = (Map<String,Object>)Json.deserializeUntyped(res.getBody()); // pass data
        
         List<Object > jsonBody = (List<Object>) Json.deserialize(strResponse, List<Object>.class);
          
         system.debug('Got these values:');
         
         System.debug(jsonBody);
        
        String ticket = String.valueof(jsonBody);
                
        return ticket;
        
        }
                  
     } 
}
2. My Remote Site settings is accurate

3. My anonymous apex code:
String busloc = MaintenanceTicket.getMaintenanceTickets('385');
    System.debug(busloc);

4. Response body (system.debug):
13:10:22:633 USER_DEBUG [26]|DEBUG|Response: {"@odata.context":"http://api.fake/$metadata#AccountBalances(businessUnit())",
"@odata.count":xxx,
"value":[{"id":1,
"businessUnitId":xxx,
"charges":46536.710000,
"credits":-37741.810000,
"balance":8794.900000,
"effectiveDate":"2020-03-03T02:54:03.81-06:00",
"businessUnit":{"id":385,"transactionType":2,"billToNumber":&quot

5.  The error:
13:10:22:654 FATAL_ERROR System.JSONException: Malformed JSON: Expected '[' at the beginning of List/Set

13:10:22:000 FATAL_ERROR Class.System.JSON.deserialize: line 15, column 1

13:10:22:000 FATAL_ERROR Class.MaintenanceTicket.getMaintenanceTickets: line 30, column 1

Regards,
Eric
​​​​​​​

 
Hi and thanks in advance...

I found this class online without Test class.  The class works great and I found a Test class for it, but it doesn't work.  

I've included the Class and the Test Class and associated errors for test class

Class:
global class UnlockRecordBatchJob implements Database.batchable<sObject> {
    //Start of this batch job
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id FROM Case LIMIT 50000000 '; //50 Million records
        return Database.getQueryLocator(query);
    }
    //Exeution of batch job
    global void execute(Database.BatchableContext BC, List<Case> scope) { //Scope max = 2000
        //List<Case> caseList = [SELECT Id From CaseLimit 2]; case already in scope varible
        //Check locked records
        List<Case> caseLockList = new List<Case>();
        for(Case c : scope)
        {
            if(Approval.isLocked(c.id)){
                caseLockList.add(c);
            }
        }
        
        if(!caseLockList.isEmpty()){
            //Unlock records
            List<Approval.UnlockResult> ulrList = Approval.unlock(caseLockList, false);
            
            // Iterate through each returned result
            for(Approval.UnlockResult  ulr : ulrList) {
                if (ulr.isSuccess()) {
                    //Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully locked account with ID: ' + ulr.getId());
                }
                else {
                    //Operation failed, so get all errors                
                    for(Database.Error err : ulr.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Case fields that affected this error: ' + err.getFields());
                    }
                }
            }
        }
    }
    //finish job
    global void finish(Database.BatchableContext BC) {
    }
}
test Class:
@isTest
public class TestDemoTest {
    @isTest
    private static void testDemo(){
        List<Case> lcase=new List<Case>();
        for(integer i=0;i<10;i++){
            Case c=new Case();
            c.Status='New';
            c.Origin='Email';
            lcase.add(c);
            
        }
        insert lcase;
        List<Approval.LockResult> lrList = Approval.lock(lcase, false);
        Test.startTest();
        TestDemo td=new TestDemo();
        Database.executeBatch(td);
        Test.stopTest();
        
    }
}

The errors I get are:
Invalid type: TestDemo

Method does not exist or incorrect signature: void executeBatch(TestDemo) from the type Database



 
Hi and thanks in advance for any help.

I created a lightning component (Quick action).  How do I add a spinner while the code is doing it's job?  
 
Component

<aura:component controller="sendtoBrandQA" implements="force:lightningQuickActionWithoutHeader,force:hasRecordId,force:appHostable,flexipage:availableForAllPageTypes" >
	       
    <aura:attribute name="cse" type="Case"/> 
    <!--old way of passing to Controller and runs without interaction from user -->
    <!--<aura:handler name="init" value="{!this}" action="{!c.doInit}" /> -->  
    <!--shows/waits for outlined button to be pressed: "Send Brand QA email" -->
    <lightning:button variant="brand-outline" label="Send Brand QA Email" onclick="{!c.doInit}" />
    
     
</aura:component>
 
Controller:

({
       
    doInit : function(component, event, helper) 
    {         
        
        //Get Current user
        var userId = $A.get("$SObjectType.CurrentUser.Id"); 
        console.log("### userId = "+userId);
        var action = component.get("c.escalateCase");
        action.setParams({
            "objectId": component.get("v.recordId"),
            "userId" : userId            
        });
        
        
        action.setCallback(this, function(response){
            var state = response.getState();
           
            console.log("#### state = "+state);
            if(component.isValid() && state === "SUCCESS"){
                console.log("Hello 1");
                console.log("### response.getReturnValue() = "+JSON.stringify(response.getReturnValue()));
                var str = response.getReturnValue();
                console.log("#### str = "+ str);
                if(str == 'Item has been escalated!'){
                    console.log("#### success = "+str);
                    helper.toastMessage(str, 'success');
                    $A.get("e.force:closeQuickAction").fire();
                    
                }else{
                    console.log("#### error = "+str);
                    helper.toastMessage(str, 'error');
                    $A.get("e.force:closeQuickAction").fire();
                }
                
            }
        });
        
        $A.enqueueAction(action);
    }    
    
})
Helper:

({
    
 toastMessage : function(msg, type) 
    {        
        var toastEvent = $A.get("e.force:showToast");              
        toastEvent.setParams
        ({
            title : 'Brand QA Information',
            message: msg,
            duration:' 15000',
            key: 'info_alt',
            type: type,
            mode: 'dismissable'
        });
        toastEvent.fire();        
 }    
    
})

Regards,
Eric 
 
Hi and thanks in advance.  

Converted to Lightning and having issues with VF command button.  

I've done research and cannot figure this one out.  I could create a lightning component, but don't want to change things too much.

Classic Behavior: the VFP resides in a page.  When the command button "add" is clicked, the page is does its thing and is refreshed within the parent page

Lightning Behavior:  the VFP looks great, but when the command button is clicked, a new window is opened up and I cannot get back to the parent Case easily.  I would like the same behavior as classic, if possible.

VF page
User-added image

VF code 
<apex:page tabStyle="Case" standardController="Case" extensions="AddFuelTypes"   lightningstylesheets="true">
    <!-- Case -->
    <style>
        .apexp .bPageBlock.apexDefaultPageBlock .pbBody .pbSubheader { 
            background-color: transparent;
            color: Black
        }
        body .bPageBlock, body #bodyCell .bResource .secondaryPalette, body .secondaryPalette.bPageBlock, body .individualPalette .secondaryPalette.bPageBlock, body .bodyDiv .genericTable, body .genericPageBlockTable, body .bodyDiv .bSubBlock, body .bComponentBlock .bPageBlock, body .bMyDashboard .bPageBlock, body.rlHoverFrame .bPageBlock, body.subjectSelectionPopup div.choicesBox, body.lookupTab .secondaryPalette.bPageBlock, body.popupTab .secondaryPalette.bPageBlock, body.UserTagStatsPage .secondaryPalette.bPageBlock {
            background-color: transparent;
            color: Black
        }
    </style>
    
    <apex:pageBlock >
        <apex:pageBlockSection title="Fuel Delivery Summary" columns="2" >
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Total Gallons Rq" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Total_Gallons_Rq__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Carrier Confirm Date/Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Carrier_Confirm_Date_Time__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Total Gallons Delivered" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Total_Gallons_Delivered__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Delivered Date/Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Delivered_Time__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Fuel Order Variance" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Fuel_Order_Variance__c}"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Fuel Delivery Time" style="font-weight:bold"/>
                <apex:outputField value="{!caseObj.Fuel_Delivery_Time__c}"/>
            </apex:pageBlockSectionItem>
            
        </apex:pageBlockSection>
    </apex:pageBlock>
    
    <!-- Add FuelType form -->
    <apex:form >
        <apex:pageBlock >
            <apex:pageMessages />
            <apex:pageBlockSection title="Add Fuel Types" columns="3">
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Fuel Type" style="font-weight:bold"/>
                    <apex:outputPanel styleClass="requiredInput" layout="block" id="pwPanel" >
                        <apex:outputPanel styleClass="requiredBlock"/>
                        <apex:selectList value="{!fuelObj.Fuel_Type__c}" size="1" required="true">
                            <apex:selectOptions value="{!FuelTypeOptions}"/>
                        </apex:selectList>
                    </apex:outputPanel>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Requested Gallons" style="font-weight:bold"/>
                    <apex:inputField value="{!fuelObj.Requested_Gallons__c}" required="true"/>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
            <div align="Center" draggable="false" >
                <apex:commandButton action="{!saveFuelType}" value="Add" reRender="" onclick="redirectTo('/apex/Add_Fuel_Types','');return true;" />
            </div>            
        </apex:pageBlock>
    </apex:form>
    <apex:form >
        <div name='rerender' style="overflow-x:auto; height: 200px;">
            <apex:pageBlock >
                <apex:pageBlockTable value="{!fuelTypes}" var="ft">
                    <apex:column value="{!ft.Fuel_Type__c}"/>
                    <apex:column value="{!ft.Requested_Gallons__c}"/>
                    <apex:column value="{!ft.Delivered_Gallons__c}"/>
                    <apex:column value="{!ft.Gallon_Variance__c}"/>
                    <apex:column value="{!ft.CreatedDate}"/>
                    <apex:column >
                        <apex:commandLink value="Remove"  action="{!removeFuelType}" >
                            <apex:param name="selectedFuelTypeId" value="{!ft.Id}"/>
                        </apex:commandLink>
                    </apex:column>
                </apex:pageBlockTable>
                  <apex:outputText rendered="{!fuelTypes.size==0}">
                      <table width="100%">
                          <tr ><th>Fuel Type</th>
                          <th>Requested Gallons</th>
                          <th>Delivered Gallons</th>
                          <th>Gallon Variance</th>
                          <th>Created Date</th>
                          </tr> 
                          <tr></tr>
                          <tr><td colspan="5" style="text-align:center;">No Records</td></tr>
                      </table>
                  </apex:outputText> 
            </apex:pageBlock>
        </div>
    </apex:form>    
</apex:page>

APEX Class
 
public class AddFuelTypes {
    public string result {get; set;}
    public Case caseObj {get; set;}
    public Fuel_Type__c fuelObj {get; set;}
    public List<Fuel_Type__c> fuelTypes {get; set;}
    public string selectedFuelTypeId {get; set;}      // Selected fuel Type
    public boolean haveFuelTypes {get; set;}    // Flag to display no schedule error message

    
    public AddFuelTypes(ApexPages.StandardController stdController){   
        this.caseObj = (Case)stdController.getRecord();  // Gets the current case working on.  Case has to be created first then add fuel types
        caseObj = [SELECT Old_Total_Gallons_Rq__c,SendtoTMW__c, Carrier_Confirm_Date_Time__c, Fuel_Order_Status__c, Fuel_Order_Variance__c, Delivered_Time__c,
                   Total_Gallons_Delivered__c, Total_Gallons_Rq__c,Fuel_Delivery_Time__c
                   FROM Case 
                   WHERE Id = :ApexPages.currentPage().getParameters().get('Id')];
        
        // Get fuel order information for current case
        fuelTypes = [SELECT Id, Fuel_Type__c, Requested_Gallons__c, Delivered_Gallons__c, 
                     Gallon_Variance__c, CreatedDate
                     FROM Fuel_Type__c 
                     WHERE Case__c = :caseObj.Id];
        
        fuelObj = new Fuel_Type__c();
        
        haveFuelTypes = false;
        if(fuelTypes.size() > 0) // Variable havefuelTypes starts as false.  Once fuel type added set to true
        {
            haveFuelTypes = true;
        }
        
        // Error messages
        selectedFuelTypeId = '';
        String temp=ApexPages.currentPage().getParameters().get('Status');
        if(temp!=NULL){
            if(temp.equals('false'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Duplicate fuel type cannot be entered. Please remove an existing type to add again.'));
            else if(temp.equals('CannotDelete'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Unable to delete, order is already Sent to TMW!'));
            else if(temp.equals('CannotAdd'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Unable to add, order is already Sent to TMW!'));
            else if(temp.equals('CannotBelower'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please enter a valid quantity larger than 0'));
            else if(temp.equals('CannotBeHigher'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please enter a valid smaller quantity'));
            else if(temp.equals('NotAllowed'))
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please select a valid Fuel Type'));
        }
    }
    
    public List<SelectOption> getFuelTypeOptions(){
       
       List<SelectOption> options = new List<SelectOption>();
       Schema.DescribeFieldResult fieldResult = Fuel_Type__c.Fuel_Type__c.getDescribe();
       List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
       for( Schema.PicklistEntry f : ple)
       {
               options.add(new SelectOption(f.getLabel(), f.getValue()));
       }     
       return options;
    }
    
    public PageReference saveFuelType(){
        
        result='true';
        fuelObj.Case__c = caseObj.id;
        if(fuelObj.Fuel_Type__c!=NULL){
            if(fuelObj.Fuel_Type__c.equals('None'))  // Error checking, Fuel Type cannot be None
                result='NotAllowed';}
        fuelTypes = [SELECT Id, Fuel_Type__c, Requested_Gallons__c, Delivered_Gallons__c, 
                     Gallon_Variance__c, CreatedDate
                     FROM Fuel_Type__c 
                     WHERE Case__c = :caseObj.Id];
        for(Fuel_Type__c ft : fueltypes) 
        {
          if(ft.Fuel_Type__c==fuelObj.Fuel_Type__c)
              result='false';
        }
        
            if(caseObj.SendtoTMW__c!=true)
            {   
                if(!result.equals('NotAllowed')){
                    if(result.equals('true')){  // Requested Gallons must be greater than 0 and less than 100,000 gallons.  Else throw error
                        if(fuelObj.Requested_Gallons__c>=1)
                        {   
                            if(fuelObj.Requested_Gallons__c<100000)
                                insert fuelObj;
                            else
                                result='CannotBeHigher';
                        }else
                            result='CannotBelower';
                    }else
                        result='false';
                }
            }
            else
                result='CannotAdd';
        // Redirect back to same page
        PageReference reRend = new PageReference('/apex/Add_Fuel_Types?id='+ caseObj.Id+'&Status='+result);
        reRend.setRedirect(true);
        return reRend;
    }
    
    public PageReference removeFuelType(){   //Error checking when Removing fuel type.  Fuel Types cannot be removed once order has been sent to TMW 
        
        selectedFuelTypeId = ApexPages.currentPage().getParameters().get('selectedFuelTypeId');   
        List<Fuel_Type__c> FuelTypesToBeRemoved = [SELECT Id, Fuel_Type__c FROM Fuel_Type__c
                                               WHERE Id = :selectedFuelTypeId];

        system.debug('FT Id ...........' + selectedFuelTypeId);
        system.debug('FT Control here ...........' + FuelTypesToBeRemoved);
        if(caseObj.SendtoTMW__c!=true)
            delete FuelTypesToBeRemoved;
        else
            result='CannotDelete';
        
        // Redirect back to same page
        PageReference reRend = new PageReference('/'+caseObj.Id);
        reRend.setRedirect(true);
        return reRend;
    } 
}



 
Hi and appreciate any insight on this.

My save button no longer works.  It was a VS button.  I made a new List View button calling VFP/ APEX  Not sure what went wrong here.  

Button
 
User-added image

VFP.
<apex:page standardController="Case" recordSetVar="cases" lightningStylesheets="true" extensions="setQuickCaseExtensionController"> 
    <apex:form >
        <apex:pageBlock title="Quick Case Entry" mode="edit">
            <apex:pageMessages id="showmsg"></apex:pageMessages>
            
            <apex:pageBlockSection title="Case Details" columns="1">                 
                                
              <apex:inputField label="Source Type" required="true" value="{!case.Source_Type__c}" /> 
              <apex:inputField label="Origin" required="true" value="{!case.Origin}"/>  
              <apex:inputField label="Contact" value="{!case.ContactId}"/> 
              <apex:inputField label="Subject" required="true" value="{!case.Subject}"/> 
              <apex:inputTextArea style="width:300px;height:100px" required="true" label="Description (Min 10 chars)"  value="{!case.Description}"/>
              <apex:inputField label="Category" required="true" value="{!case.Category__c}"/> 
              <apex:inputField label="Sub-Catagory 1" required="true" value="{!case.Sub_Catagory_1__c}"/>  
              <apex:inputField label="Sub-Catagory 2" required="true" value="{!case.Sub_Category_2__c}"/>  
              <apex:inputField label="Sub-Catagory 3" required="true" value="{!case.Sub_Category_3__c}"/>              
              <apex:inputField value="{!case.Related_Account__c}" label="Account"/>          
              <apex:inputField value="{!case.Incident_Occurence_Date__c}" label="Incident Occurrence Date"/>
              <apex:inputField value="{!case.Incident_Occurrence_Time__c}" label="Incident Occurrence Time"/>  
             </apex:pageBlockSection>   
            
            <apex:pageBlockButtons > 
                <apex:commandButton value="Save & Close Quick Case" action="{!save}"/> 
                <apex:commandButton value="Cancel" action="{!cancel}"/> 
            </apex:pageBlockButtons> 
                       
          
        </apex:pageBlock> 
    </apex:form>
</apex:page>

APEX Class

public class setQuickCaseExtensionController {
   private Case QC; 
   public ApexPages.StandardSetController stdController; 
   public setQuickCaseExtensionController(ApexPages.StandardSetController controller){
        controller.setPageSize(10);
        this.QC = (Case)controller.getRecord(); 
        RecordType RecId = new RecordType();
        RecId=[SELECT Id FROM RecordType where Name='Customer First' LIMIT 1];
        QC.RecordTypeId=RecId.Id;
        QC.Quick_Case__c = True;
        QC.Origin = 'Phone';
        QC.Source_Type__c = 'Consumer';
        QC.Description='Quick Case';
        QC.Quick_Case_Closed__c = True;
        QC.Subject='New Quick Case';
        stdcontroller=controller;        
    }

}
global class UnlockRecordBatchJob implements Database.batchable<sObject> {
    //Start of this batch job
    global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id FROM Case LIMIT 50000000 '; //50 Million records
        return Database.getQueryLocator(query);
    }
    //Exeution of batch job
    global void execute(Database.BatchableContext BC, List<Case> scope) { //Scope max = 2000
        //List<Case> caseList = [SELECT Id From CaseLimit 2]; case already in scope varible
        //Check locked records
        List<Case> caseLockList = new List<Case>();
        for(Case c : scope)
        {
            if(Approval.isLocked(c.id)){
                caseLockList.add(c);
            }
        }
        
        if(!caseLockList.isEmpty()){
            //Unlock records
            List<Approval.UnlockResult> ulrList = Approval.unlock(caseLockList, false);
            
            // Iterate through each returned result
            for(Approval.UnlockResult  ulr : ulrList) {
                if (ulr.isSuccess()) {
                    //Operation was successful, so get the ID of the record that was processed
                    System.debug('Successfully locked account with ID: ' + ulr.getId());
                }
                else {
                    //Operation failed, so get all errors                
                    for(Database.Error err : ulr.getErrors()) {
                        System.debug('The following error has occurred.');                    
                        System.debug(err.getStatusCode() + ': ' + err.getMessage());
                        System.debug('Case fields that affected this error: ' + err.getFields());
                    }
                }
            }
        }
    }
    //finish job
    global void finish(Database.BatchableContext BC) {
    }
}

I am stuck at 22% the Execute is not being covered