function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Bob 11Bob 11 

Test Class Error System.QueryException: List has no rows for assignment to SObject

I made an update to a apex test class but when i try to deploy it give me the following error. I'm not sure how to fix this

System.QueryException: List has no rows for assignment to SObject
Stack Trace: Class.advic_fsl_AppointmentBooking.scheduleServiceAppointment: line 71, column 1 Class.advic_fsl_AppointmentBookingTest.testScheduleServiceAppointment: line 146, column 1

here is the test class below. i will post the apex class too
 
@isTest
private class advic_fsl_AppointmentBookingTest {

    @testSetup
    static void setup() {
        // Create test data
        // Create Scheduling Policy
        FSL__Scheduling_Policy__c schedulingPolicy = new FSL__Scheduling_Policy__c(FSL__Commit_Mode__c='AlwaysCommit', FSL__Fix_Overlaps__c=false, FSL__Daily_Optimization__c=false,
                Name='Customer First', FSL__Travel_Mode__c=false);
        insert schedulingPolicy;
        // Create Operating Hours
        OperatingHours operatingHours = new OperatingHours(Description='Testing Hours', Name='Energy Assessment Calendar', TimeZone='America/New_York');
        insert operatingHours;
        // Create Time Slots
        List<TimeSlot> timeSlots = new List<TimeSlot>();
        timeSlots.add(new TimeSlot(DayOfWeek='Monday', Type='Normal', OperatingHoursId=operatingHours.Id,
                StartTime=Time.newInstance(10,0,0,0), EndTime=Time.newInstance(12,0,0,0)));
        timeSlots.add(new TimeSlot(DayOfWeek='Tuesday', Type='Normal', OperatingHoursId=operatingHours.Id,
                StartTime=Time.newInstance(10,0,0,0), EndTime=Time.newInstance(12,0,0,0)));
        insert timeSlots;
        Account testAccount = new Account(Name='Test Account', Customer_Eligible__c=true);
        insert testAccount;
        Contact testContact = new Contact(AccountId=testAccount.Id, LastName='TestContact');
        insert testContact;
        Profile riseCommunityCustomerProfile = [SELECT Id FROM Profile WHERE Name='RISE Community Customer User'];
        User runningUser = new User(Alias = 'standt', Email='standarduser@testorg.com', EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US',
                LocaleSidKey='en_US', ProfileId = riseCommunityCustomerProfile.Id, TimeZoneSidKey='America/New_York', UserName='standarduser@testorg.com',
                ContactId=testContact.Id);
        insert runningUser;
        
        
        WorkType eaIh  = new WorkType();
        eaIh.Name = 'Energy Assessment - In Home';
        eaIh.EstimatedDuration = 90.0;
        insert eaIh;
        
        
    }

    static testMethod void testCreateWorkOrderAndServiceAppointment() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT Id FROM User WHERE ContactId =: contact.Id];

        

        List<WorkOrder> insertedWorkOrders = [SELECT AccountId, ContactId FROM WorkOrder];
        List<ServiceAppointment> insertedServiceAppointments = [SELECT AccountId, ContactId, ParentRecordId, EarliestStartTime, DueDate FROM ServiceAppointment ];

      
       

        if(insertedWorkOrders.size() == 1) {
            WorkOrder insertedWorkOrder = insertedWorkOrders[0];
            System.assertEquals(account.Id, insertedWorkOrder.AccountId, 'The Work Order AccountId was not assigned.');
            System.assertEquals(contact.Id, insertedWorkOrder.ContactId, 'The Work Order ContactId was not assigned.');

            if(insertedServiceAppointments.size() == 1) {
                ServiceAppointment insertServiceAppointment = insertedServiceAppointments[0];
                System.assertEquals(account.Id, insertServiceAppointment.AccountId, 'The Service Appointment AccountId was not assigned.');
                System.assertEquals(contact.Id, insertServiceAppointment.ContactId, 'The Service Appointment ContactId was not assigned.');
                System.assertEquals(insertedWorkOrder.Id, insertServiceAppointment.ParentRecordId, 'The Work Order that was inserted was not assigned to the inserted Service Appointment.');
                System.assert(insertServiceAppointment.EarliestStartTime != null, 'The Service Appointment EarliestStartTime was not populated.');
                System.assert(insertServiceAppointment.DueDate != null, 'The Service Appointment DueDate was not populated.');
            }
        }
    }

    static testMethod void testGetAppointmentSlots() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];

        WorkOrder testWorkOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId);
        insert testWorkOrder;
        ServiceAppointment testServiceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=testWorkOrder.Id, EarliestStartTime=Datetime.now(), DueDate=Datetime.now().addMonths(1));
        insert testServiceAppointment;

        Test.startTest();
            advic_fsl_AppointmentBooking.CmpData data = advic_fsl_AppointmentBooking.getAppointmentSlots(testWorkOrder.Id, testServiceAppointment.Id);
        Test.stopTest();

        // Letting the managed package tests control the FSL methods and test them.
        // The method itself is covered in the FSL managed package tests.
    }

    static testMethod void testUndeleteWorkOrderAndServiceAppointment() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];

        WorkOrder testWorkOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId);
        insert testWorkOrder;
        ServiceAppointment testServiceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=testWorkOrder.Id, EarliestStartTime=Datetime.now(), DueDate=Datetime.now().addMonths(1));
        insert testServiceAppointment;

        delete testWorkOrder;

        Test.startTest();
            advic_fsl_AppointmentBooking.undeleteWorkOrderAndServiceAppointment(testWorkOrder.Id, testServiceAppointment.Id);
        Test.stopTest();

        System.assertEquals(1, [SELECT Id FROM WorkOrder WHERE Id =: testWorkOrder.Id].size(), 'The Work Order was not undeleted.');
        System.assertEquals(1, [SELECT Id FROM ServiceAppointment WHERE Id =: testServiceAppointment.Id].size(), 'The Service Appointment was not undeleted');
    }

    static testMethod void testUpdateServiceAppointment() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];

        WorkOrder testWorkOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId);
        insert testWorkOrder;
        ServiceAppointment testServiceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=testWorkOrder.Id, EarliestStartTime=Datetime.now(), DueDate=Datetime.now().addMonths(1));
        insert testServiceAppointment;

        String slotJSON = '{"grade":100,"times":{"endDT":"2020-06-02T15:00:00.000Z","startDT":"2020-06-02T13:00:00.000Z"}}';

        System.runAs(runningUser) {
            Test.startTest();
            advic_fsl_AppointmentBooking.updateServiceAppointment(slotJSON, testServiceAppointment.Id, 'abc', 'xyz');
            Test.stopTest();
        }

        ServiceAppointment serviceAppointment = [SELECT ArrivalWindowStartTime, ArrivalWindowEndTime FROM ServiceAppointment WHERE Id =: testServiceAppointment.Id];

        DateTime arrivalWindowStartTime = (DateTime)json.deserialize('"2020-06-02T13:00:00.000Z"', datetime.class);
        DateTime arrivalWindowEndTime = (DateTime)json.deserialize('"2020-06-02T15:00:00.000Z"', datetime.class);

        //System.assertEquals(arrivalWindowStartTime, serviceAppointment.ArrivalWindowStartTime, 'The Service Appointment ArrivalWindowStartTime is incorrect.');
        //System.assertEquals(arrivalWindowEndTime, serviceAppointment.ArrivalWindowEndTime, 'The Service Appointment ArrivalWindowEndTime is incorrect.');
    }

    static testMethod void testScheduleServiceAppointment() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];

        WorkOrder testWorkOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId);
        insert testWorkOrder;
        ServiceAppointment testServiceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=testWorkOrder.Id,
                EarliestStartTime=Datetime.now(), DueDate=Datetime.now().addMonths(1), ArrivalWindowStartTime=Datetime.now(), ArrivalWindowEndTime=Datetime.now().addMonths(1), Status = 'Scheduled');
        insert testServiceAppointment;

        Test.startTest();
            advic_fsl_AppointmentBooking.scheduleServiceAppointment(testServiceAppointment.Id);
        Test.stopTest();

        // Letting the managed package tests control the FSL methods and test them.
        // The method itself is covered in the FSL managed package tests.
    }

    static testMethod void testCheckAccountEligibility_NoAccounts() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'DISC';
        account.Square_Footage__c = '';
        account.Building_Type__c = 'Single-Family Home';
        contact.Part_of_Condo_Association__c = 'No';
        update account;
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
                eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Due to your utility service rate code, we are not able to service your property. Please contact your local Community Action Partnership, or call our offices for more information. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335. Thank you.', eligibilityStatus, 'The Account should be ineligible.');
    }
    static testMethod void testCheckAccountEligibility_NoAccounts1() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'COM';
        account.Square_Footage__c = '';
        account.Building_Type__c = 'Single-Family Home';
        contact.Part_of_Condo_Association__c = 'No';
        update account;
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
                eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment. Please contact out office for further assistance at 401-784-3700.', eligibilityStatus, 'The Account should be ineligible.');
    }
    static testMethod void testCheckAccountEligibility_NoAccounts2() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'PP';
        account.Square_Footage__c = '';
        account.Building_Type__c = 'Single-Family Home';
        contact.Part_of_Condo_Association__c = 'No';
        update account;
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
                eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program. For further assistance, please contact our offices. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335. Thank you.', eligibilityStatus, 'The Account should be ineligible.');
    }
    static testMethod void testCheckAccountEligibility_NoAccounts3() {
        Account account = [SELECT Id FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'AMA';
        account.Square_Footage__c = '';
        account.Building_Type__c = 'Single-Family Home';
        contact.Part_of_Condo_Association__c = 'No';
        update account;
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
                eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335.', eligibilityStatus, 'The Account should be ineligible.');
    }

    static testMethod void testCheckAccountEligibility_GasAccountEligible() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Gas_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Eligible_Testing__c = true;
        account.Building_Type__c = 'Single-Family Home';
        account.Square_Footage__c = '2000-3000 sq ft';
        update account;
        contact.Gas_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Natural Gas';
        contact.Part_of_Condo_Association__c = 'No';
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
            eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Eligible', eligibilityStatus, 'The Contact should be eligible.');
    }

    static testMethod void testCheckAccountEligibility_GasAccountIneligible() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Gas_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Ineligible_Reason_Code__c = 'DISC';
        update account;
        contact.Gas_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Natural Gas';
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
            eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Due to your utility service rate code, we are not able to service your property. Please contact your local Community Action Partnership, or call our offices for more information. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335. Thank you.', eligibilityStatus, 'The General Error message should have returned.');
    }
     static testMethod void testCheckAccountEligibility_GasAccountIneligible1() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Gas_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Ineligible_Reason_Code__c = 'COM';
        update account;
        contact.Gas_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Natural Gas';
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
            eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment. Please contact out office for further assistance at 401-784-3700.', eligibilityStatus, 'The General Error message should have returned.');
    }
    static testMethod void testCheckAccountEligibility_GasAccountIneligible2() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Gas_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Ineligible_Reason_Code__c = 'PP';
        update account;
        contact.Gas_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Natural Gas';
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
            eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program. For further assistance, please contact our offices. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335. Thank you.', eligibilityStatus, 'The Contact should be eligible.');
    }
    static testMethod void testCheckAccountEligibility_GasAccountIneligible3() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Gas_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Ineligible_Reason_Code__c = 'AMA';
        update account;
        contact.Gas_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Natural Gas';
        update contact;

        String eligibilityStatus = '';
        System.runAs(runningUser) {
            Test.startTest();
            eligibilityStatus = advic_fsl_AppointmentBooking.checkAccountEligibility();
            Test.stopTest();
        }

        System.assertEquals('Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices. For National Grid Rhode Island customers dial 888-633-7947. For National Grid Cape Cod or Cape Light Compact customers dial 774-352-1022. For Eversource, Liberty or Unitil customers dial 339-502-6335.', eligibilityStatus, 'The Contact should be eligible.');
    }

   
  

    

        
    static testMethod void testCheckAccountEligibility_ElectricAccountIneligibleq1() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Electric_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'COM';
        update account;
        contact.Electric_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Electric';
        update contact;

    }
    static testMethod void testCheckAccountEligibility_ElectricAccountIneligible2() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Electric_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'PP';
        update account;
        contact.Electric_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Electric';
        update contact;

    }     
    static testMethod void testCheckAccountEligibility_ElectricAccountIneligible3() {
        Account account = [SELECT Id, Utility_Number__c, Eligible_Testing__c, Ineligible_Reason_Code__c FROM Account WHERE Customer_Eligible__c = true LIMIT 1];
        Contact contact = [SELECT Id, Electric_Utility_Number__c, How_do_you_heat_your_home__c FROM Contact WHERE AccountId =: account.Id];
        User runningUser = [SELECT AccountId, ContactId FROM User WHERE ContactId =: contact.Id];
        account.Utility_Number__c = '14356';
        account.Eligible_Testing__c = false;
        account.Ineligible_Reason_Code__c = 'AMA';
        update account;
        contact.Electric_Utility_Number__c = '14356';
        contact.How_do_you_heat_your_home__c = 'Electric';
        update contact;

               }
}
Best Answer chosen by Bob 11
Sai PraveenSai Praveen (Salesforce Developers) 
Hi Bob,

Can you try changing the Apex class little as below. There will be no change in functionality just best pratice. I have highlited the change.

Please find the below article (https://help.salesforce.com/s/articleView?id=000328824&type=1) for the same.
 
public without sharing class advic_fsl_AppointmentBooking {

    @AuraEnabled
    public static CmpData createWorkOrderAndServiceAppointment() {
        CmpData retData = new CmpData();
        User runningUser = getRunningUser();
        system.debug('Who is the running user: '+runningUser.AccountId);
        retData.isEligibleCustomer = checkCustomerEligibility(runningUser.AccountId);
        if(retData.isEligibleCustomer) {
            retData.workOrderId = createWorkOrder(runningUser);
            retData.serviceAppointmentId = createServiceAppointment(runningUser, retData.workOrderId);
        }
        
        return retData;
    }
    
    @AuraEnabled
    public static CmpData getAppointmentSlots(Id workOrderId, Id serviceAppointmentId) {
        System.debug('@@@@ HERE');
        CmpData retData = new CmpData();
        retData.slots = getSlots(serviceAppointmentId);
        // We delete the created Work Order and Service Appointment in case the user quits the process before scheduling his/her appointment.
        // Once the user confirms their scheduled appointment, we will undelete the Work Order and Service Appointment.
        deleteWorkOrderAndServiceAppointment(workOrderId, serviceAppointmentId);
        System.debug('@@@@ retData: ' + retData);
        return retData;
    }
    
    @AuraEnabled
    public static void undeleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        List<WorkOrder> deletedWorkOrders = [SELECT Id FROM WorkOrder WHERE Id =: workOrderId ALL ROWS];
        List<ServiceAppointment> deletedServiceAppointments = [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId ALL ROWS];
        try {
            undelete deletedWorkOrders;
            undelete deletedServiceAppointments;
        } catch(DmlException e) {
            System.debug('Error in undeleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }
    
    @AuraEnabled
    public static void updateServiceAppointment(String slotJSON, Id serviceAppointmentId, String detailsAccount, String detailsServiceAppt) {
        System.debug(slotJSON);
        System.debug(serviceAppointmentId);
        System.debug(detailsAccount);
        System.debug(detailsServiceAppt);
        AppointmentBookingSlot slot = (AppointmentBookingSlot)JSON.deserialize(slotJSON, advic_fsl_AppointmentBooking.AppointmentBookingSlot.class);
        try{
            ServiceAppointment serviceAppointment = [SELECT ArrivalWindowStartTime, ArrivalWindowEndTime, Status, Additional_Details__c FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
            serviceAppointment.ArrivalWindowStartTime = utcToUserTimezone(slot.times.startDT);
            serviceAppointment.ArrivalWindowEndTime = utcToUserTimezone(slot.times.endDT);
            
            serviceAppointment.Status = 'Scheduled';
            ServiceAppointment.Additional_Details__c = detailsServiceAppt;
            
            User runningUser = getRunningUser();
            system.debug('Who is the running user: '+runningUser.AccountId);
            Account account = [SELECT Additional_Details__c FROM Account WHERE Id =: runningUser.AccountId];
            account.Additional_Details__c = detailsAccount;
            
            update serviceAppointment;
            update account;
        } catch(DmlException e) {
            System.debug('updateServiceAppointment: ' + serviceAppointmentId + ' Error: ' + + e.getMessage());
        }
        
    }
    
    @AuraEnabled
    public static void scheduleServiceAppointment(Id serviceAppointmentId) {
        Public Id schedulingPolicyId;

        List<FSL__Scheduling_Policy__c> schlist= new List<FSL__Scheduling_Policy__c>();
        schlist=[SELECT Id, Name FROM FSL__Scheduling_Policy__c WHERE Name = 'Customer First' LIMIT 1];

        if(schlist.size()<0)
        {
         schedulingPolicyId = schlist[0].Id;
        }
        
        //Schedules the service appointment in the best available slot. If there are no available slots, the appointment isn’t scheduled.
        FSL.ScheduleResult result = new FSL.ScheduleResult();
        //Returns the result of the scheduling process.
        System.debug('svcApptId to Svc: '+ serviceAppointmentId);
        result = FSL.ScheduleService.schedule(schedulingPolicyId, serviceAppointmentId);
        try{
            System.debug('FSL.ScheduleService result: ' + JSON.serializePretty(result));
        }
        catch(Exception e){
            System.debug('JSON ERROR. On: '+ result);
        }
    }
    
    private static Boolean checkCustomerEligibility(Id accountId) {
        Account account = [SELECT Customer_Eligible__c FROM Account WHERE Id =: accountId];
        
        //return account.Customer_Eligible__c;
        return true; //for testing only.
    }
    //new eligibility that we need to incoporate REMS-191
    @AuraEnabled
    public static String checkAccountEligibility() {
        String eligibilityStatus = '';
        Boolean codeStartsWithPp = false;
        User runningUser = getRunningUser();
        Contact cont = [SELECT Electric_Utility_Number__c, Gas_Utility_Number__c, How_do_you_heat_your_home__c, AccountId, Part_of_Condo_Association__c FROM Contact WHERE Id =: runningUser.ContactId];
        System.debug('@@@ cont.Gas_Utility_Number__c: ' + cont.Gas_Utility_Number__c);
        System.debug('@@@ cont.Electric_Utility_Number__c: ' + cont.Electric_Utility_Number__c);
        if(String.isBlank(cont.Gas_Utility_Number__c) && String.isBlank(cont.Electric_Utility_Number__c)) {
            Account account = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Square_Footage__c, Building_Type__c FROM Account WHERE Id = :cont.AccountId];
            System.debug('@@@ account: ' + account);
            codeStartsWithPp = checkIneligibleReasonCode(account.Ineligible_Reason_Code__c);
            if(account.Eligible_Testing__c == false) {
                //Need to display general ineligible code info
                if(account.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property. Please contact your local Community Action Partnership, or call our offices for more information.';
                }
                else if(account.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Please contact out office for further assistance at 401-000-0000';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you  Thank you.';
                } else if(account.Ineligible_Reason_Code__c != 'DISC' || account.Ineligible_Reason_Code__c != 'COM' || !codeStartsWithPp){
                eligibilityStatus = 'thank you';
                } else{
                    eligibilityStatus = 'thank you';                    
                }
            } else if(account.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || account.Building_Type__c != 'Single-Family Home' || account.Square_Footage__c == '3000-3500 sq ft' || account.Square_Footage__c == '3500-6000 sq ft' || account.Square_Footage__c == '6000+ sq ft')){
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';                    
            } else {
                eligibilityStatus = 'Eligible';
                }}
        if(String.isNotBlank(cont.Gas_Utility_Number__c)) {
            Account gasAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Gas_Utility_Number__c LIMIT 1];
            System.debug('@@@ gasAcc: ' + gasAcc);
            codeStartsWithPp = checkIneligibleReasonCode(gasAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || gasAcc.Building_Type__c != 'Single-Family Home' || gasAcc.Square_Footage__c == '3000-3500 sq ft' || gasAcc.Square_Footage__c == '3500-6000 sq ft' || gasAcc.Square_Footage__c == '6000+ sq ft')){
                System.debug('@@@@ A');
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices. ';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC'){
                System.debug('@@@@ B');
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                System.debug('@@@@ C');
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
            } else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                System.debug('@@@@ D');
                if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                    System.debug('@@@@ E');
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                }
                else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                    System.debug('@@@@ F');
                    eligibilityStatus = 'Due';
                }
                else if(codeStartsWithPp){
                    System.debug('@@@@ G');
                    eligibilityStatus = 'We are not able to schedule you';
                } else{
                    System.debug('@@@@ H');
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        System.debug('@@@@ I');
                        //Need to display general ineligible code info
                        if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                            System.debug('@@@@ J');
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                        }
                        else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                            System.debug('@@@@ K');
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            System.debug('@@@@ L');
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.';
                        }
                        else{
                            System.debug('@@@@ M');
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
                        }}
                }
        }
        if(String.isNotBlank(cont.Electric_Utility_Number__c)) {
            Account elecAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Electric_Utility_Number__c LIMIT 1];
            System.debug('@@@ elecAcc: ' + elecAcc);
            codeStartsWithPp = checkIneligibleReasonCode(elecAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC'){
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
            } 
            else if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_You_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
            }
            else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true){
                eligibilityStatus = 'Eligible';
            } else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                }
                else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.. Thank you.';
                } else {
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance,';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        //Need to display general ineligible code info
                        if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                        }
                        else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program. For further assistance, please contact our offices. Thank you.';
                        }else{
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                        }}
            }
        }

        System.debug('@@@@ eligibilityStatus: ' + eligibilityStatus);

        return eligibilityStatus;
    }

    public static User getRunningUser() {
        Id runningUserId = UserInfo.getUserId();

        return [SELECT AccountId, ContactId, Account.BillingStreet, Account.BillingCity, Account.BillingState, Account.BillingCountry, Account.BillingPostalCode FROM User WHERE Id =: runningUserId];
    }

    public static Id createWorkOrder(User runningUser) {
        WorkType energyInHomeWt = [SELECT Id FROM WorkType WHERE Name = 'Energy Assessment - In Home' LIMIT 1];
        WorkOrder workOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId, Street=runningUser.Account.BillingStreet, WorkTypeId=energyInHomeWt.Id,
                City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry, PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert workOrder;
        } catch(DmlException e) {
            System.debug('Error in createWorkOrder: ' + e.getMessage());
        }

        return workOrder.Id;
    }

    public static Id createServiceAppointment(User runningUser, Id workOrderId) {
        ServiceAppointment serviceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=workOrderId, EarliestStartTime=Datetime.now().addMonths(1), DueDate=Datetime.now().addMonths(1),
            Street=runningUser.Account.BillingStreet, City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry,
            PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert serviceAppointment;
        } catch(DmlException e) {
            System.debug('Error in createServiceAppointment: ' + e.getMessage());
        }

        return serviceAppointment.Id;
    }

    private static Boolean checkIneligibleReasonCode(String ineligibleReasonCode) {
        Boolean codeStartsWithPp = false;
        if(String.isNotBlank(ineligibleReasonCode)) {
            if(ineligibleReasonCode.startsWith('PP')) {
                codeStartsWithPp = true;
            }
        }

        return codeStartsWithPp;
    }

    private static void deleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        try {
            delete [SELECT Id FROM WorkOrder WHERE Id =: workOrderId];
            delete [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
        } catch(DmlException e) {
            System.debug('Error in deleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }

    /*
    * Appointment booking returns the available slots for a service appointment, while considering scheduling policies, work rules, and service objectives.
    * */
    public static List<AppointmentBookingSlot> getSlots(Id serviceAppointmentId) {
        System.debug('@@@@ serviceAppointmentId: ' + serviceAppointmentId);
        ServiceAppointment serviceAppointment = [SELECT Id, AccountId, ContactId, EarliestStartTime, DueDate FROM ServiceAppointment WHERE Id =: serviceAppointmentId LIMIT 5];

        Id schedulingPolicyId = [SELECT Id, Name FROM FSL__Scheduling_Policy__c LIMIT 1].Id;

        Id operatingHoursId  = [SELECT Id, Name FROM OperatingHours WHERE Name = 'Energy Assessment Calendar' LIMIT 1].Id;

        Timezone tz = UserInfo.getTimeZone();
        System.debug('getting slots with....'+ serviceAppointment.Id + '//'+schedulingPolicyId+ '//'+operatingHoursId+ '//'+tz) ;
        List<FSL.AppointmentBookingSlot> slots = FSL.AppointmentBookingService.GetSlots(serviceAppointment.Id, schedulingPolicyId, operatingHoursId, tz, false);
        System.debug('slots: ' + slots);

        List<AppointmentBookingSlot> slotList = new List<AppointmentBookingSlot>();
        for(FSL.AppointmentBookingSlot slot : slots){
            DateTime slotStartDT = slot.interval.start;
            DateTime slotFinishDT = slot.interval.finish;
            Date slotStartDay = slotStartDT.date();
            
            if(slotStartDay > Date.today() ){
                AppointmentBookingSlot newSlot = new AppointmentBookingSlot();
                Interval times = new Interval();
                times.startDT = slot.interval.start;
                times.endDT = slot.interval.finish;
                newSlot.grade = slot.grade;
                newSlot.times = times;
                slotList.add(newSlot);
            }
        }
        System.debug('slotList:: '+ slotList);
        //I'm thinking they may want these ordered by rank, but not 100% sure. If so, we can do that with the comparable interface:
        //https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_comparable.htm --Chuck
        
        //return setToTimeZone(slotList);
        return slotList;
    }
    
    public static DateTime utcToUserTimezone(DateTime utcDT){
        DateTime userDT = utcDT;
        String utcDtString = utcDT.format('yyyy-MM-dd HH:mm:ss', 'UTC');
        //String utcDtString = utcDT.format('yyyy-MM-dd hh:mm a', 'UTC');

        System.debug('@@@@ str: '+utcDtString);
        userDT = DateTime.valueOf(utcDtString);
        System.debug('@@@@ DT: '+userDT);
        return userDT;
    }
    
    /*public static List<AppointmentBookingSlot> setToTimezone(List<AppointmentBookingSlot> slots){
        if(slots.isEmpty()){
            return slots;
        }
        String timeZone = UserInfo.getTimeZone().getID();

        for(AppointmentBookingSlot slot: slots){
            if(slot.times != NULL){
                System.debug('~~~~~~');
                System.debug('BEFORE: '+ slot.times.endDT);
                slot.times.startDT = Datetime.valueOf(slot.times.startDT);
                slot.times.endDT = Datetime.valueOf(slot.times.endDT);
                System.debug('AFTER: '+ slot.times.endDT.format());
            }
        }
        
        return slots;
    }*/
    
    

    public class CmpData {
        @AuraEnabled
        public Id workOrderId {get;set;}
        @AuraEnabled
        public Id serviceAppointmentId {get;set;}
        @AuraEnabled
        public List<AppointmentBookingSlot> slots {get;set;}
        @AuraEnabled
        public Boolean isEligibleCustomer {get;set;}
    }
    public class AppointmentBookingSlot {
        @AuraEnabled
        public Decimal grade {get;set;}
        @AuraEnabled
        public Interval times {get;set;}
    }
    public class Interval {
        @AuraEnabled
        public DateTime startDT {get;set;}
        @AuraEnabled
        public DateTime endDT {get;set;}
    }
}

Let me know if you face any issues.

If this solution helps, Please mark it as best answer.

Thanks,

All Answers

Bob 11Bob 11
Here is the Class
public without sharing class advic_fsl_AppointmentBooking {

    @AuraEnabled
    public static CmpData createWorkOrderAndServiceAppointment() {
        CmpData retData = new CmpData();
        User runningUser = getRunningUser();
        system.debug('Who is the running user: '+runningUser.AccountId);
        retData.isEligibleCustomer = checkCustomerEligibility(runningUser.AccountId);
        if(retData.isEligibleCustomer) {
            retData.workOrderId = createWorkOrder(runningUser);
            retData.serviceAppointmentId = createServiceAppointment(runningUser, retData.workOrderId);
        }
        
        return retData;
    }
    
    @AuraEnabled
    public static CmpData getAppointmentSlots(Id workOrderId, Id serviceAppointmentId) {
        System.debug('@@@@ HERE');
        CmpData retData = new CmpData();
        retData.slots = getSlots(serviceAppointmentId);
        // We delete the created Work Order and Service Appointment in case the user quits the process before scheduling his/her appointment.
        // Once the user confirms their scheduled appointment, we will undelete the Work Order and Service Appointment.
        deleteWorkOrderAndServiceAppointment(workOrderId, serviceAppointmentId);
        System.debug('@@@@ retData: ' + retData);
        return retData;
    }
    
    @AuraEnabled
    public static void undeleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        List<WorkOrder> deletedWorkOrders = [SELECT Id FROM WorkOrder WHERE Id =: workOrderId ALL ROWS];
        List<ServiceAppointment> deletedServiceAppointments = [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId ALL ROWS];
        try {
            undelete deletedWorkOrders;
            undelete deletedServiceAppointments;
        } catch(DmlException e) {
            System.debug('Error in undeleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }
    
    @AuraEnabled
    public static void updateServiceAppointment(String slotJSON, Id serviceAppointmentId, String detailsAccount, String detailsServiceAppt) {
        System.debug(slotJSON);
        System.debug(serviceAppointmentId);
        System.debug(detailsAccount);
        System.debug(detailsServiceAppt);
        AppointmentBookingSlot slot = (AppointmentBookingSlot)JSON.deserialize(slotJSON, advic_fsl_AppointmentBooking.AppointmentBookingSlot.class);
        try{
            ServiceAppointment serviceAppointment = [SELECT ArrivalWindowStartTime, ArrivalWindowEndTime, Status, Additional_Details__c FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
            serviceAppointment.ArrivalWindowStartTime = utcToUserTimezone(slot.times.startDT);
            serviceAppointment.ArrivalWindowEndTime = utcToUserTimezone(slot.times.endDT);
            
            serviceAppointment.Status = 'Scheduled';
            ServiceAppointment.Additional_Details__c = detailsServiceAppt;
            
            User runningUser = getRunningUser();
            system.debug('Who is the running user: '+runningUser.AccountId);
            Account account = [SELECT Additional_Details__c FROM Account WHERE Id =: runningUser.AccountId];
            account.Additional_Details__c = detailsAccount;
            
            update serviceAppointment;
            update account;
        } catch(DmlException e) {
            System.debug('updateServiceAppointment: ' + serviceAppointmentId + ' Error: ' + + e.getMessage());
        }
        
    }
    
    @AuraEnabled
    public static void scheduleServiceAppointment(Id serviceAppointmentId) {
        Id schedulingPolicyId = [SELECT Id, Name FROM FSL__Scheduling_Policy__c WHERE Name = 'Customer First' LIMIT 1].Id;
        
        //Schedules the service appointment in the best available slot. If there are no available slots, the appointment isn’t scheduled.
        FSL.ScheduleResult result = new FSL.ScheduleResult();
        //Returns the result of the scheduling process.
        System.debug('svcApptId to Svc: '+ serviceAppointmentId);
        result = FSL.ScheduleService.schedule(schedulingPolicyId, serviceAppointmentId);
        try{
            System.debug('FSL.ScheduleService result: ' + JSON.serializePretty(result));
        }
        catch(Exception e){
            System.debug('JSON ERROR. On: '+ result);
        }
    }
    
    private static Boolean checkCustomerEligibility(Id accountId) {
        Account account = [SELECT Customer_Eligible__c FROM Account WHERE Id =: accountId];
        
        //return account.Customer_Eligible__c;
        return true; //for testing only.
    }
    //new eligibility that we need to incoporate REMS-191
    @AuraEnabled
    public static String checkAccountEligibility() {
        String eligibilityStatus = '';
        Boolean codeStartsWithPp = false;
        User runningUser = getRunningUser();
        Contact cont = [SELECT Electric_Utility_Number__c, Gas_Utility_Number__c, How_do_you_heat_your_home__c, AccountId, Part_of_Condo_Association__c FROM Contact WHERE Id =: runningUser.ContactId];
        System.debug('@@@ cont.Gas_Utility_Number__c: ' + cont.Gas_Utility_Number__c);
        System.debug('@@@ cont.Electric_Utility_Number__c: ' + cont.Electric_Utility_Number__c);
        if(String.isBlank(cont.Gas_Utility_Number__c) && String.isBlank(cont.Electric_Utility_Number__c)) {
            Account account = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Square_Footage__c, Building_Type__c FROM Account WHERE Id = :cont.AccountId];
            System.debug('@@@ account: ' + account);
            codeStartsWithPp = checkIneligibleReasonCode(account.Ineligible_Reason_Code__c);
            if(account.Eligible_Testing__c == false) {
                //Need to display general ineligible code info
                if(account.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property. Please contact your local Community Action Partnership, or call our offices for more information.';
                }
                else if(account.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Please contact out office for further assistance at 401-000-0000';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you  Thank you.';
                } else if(account.Ineligible_Reason_Code__c != 'DISC' || account.Ineligible_Reason_Code__c != 'COM' || !codeStartsWithPp){
                eligibilityStatus = 'thank you';
                } else{
                    eligibilityStatus = 'thank you';                    
                }
            } else if(account.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || account.Building_Type__c != 'Single-Family Home' || account.Square_Footage__c == '3000-3500 sq ft' || account.Square_Footage__c == '3500-6000 sq ft' || account.Square_Footage__c == '6000+ sq ft')){
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';                    
            } else {
                eligibilityStatus = 'Eligible';
                }}
        if(String.isNotBlank(cont.Gas_Utility_Number__c)) {
            Account gasAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Gas_Utility_Number__c LIMIT 1];
            System.debug('@@@ gasAcc: ' + gasAcc);
            codeStartsWithPp = checkIneligibleReasonCode(gasAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || gasAcc.Building_Type__c != 'Single-Family Home' || gasAcc.Square_Footage__c == '3000-3500 sq ft' || gasAcc.Square_Footage__c == '3500-6000 sq ft' || gasAcc.Square_Footage__c == '6000+ sq ft')){
                System.debug('@@@@ A');
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices. ';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC'){
                System.debug('@@@@ B');
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                System.debug('@@@@ C');
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
            } else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                System.debug('@@@@ D');
                if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                    System.debug('@@@@ E');
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                }
                else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                    System.debug('@@@@ F');
                    eligibilityStatus = 'Due';
                }
                else if(codeStartsWithPp){
                    System.debug('@@@@ G');
                    eligibilityStatus = 'We are not able to schedule you';
                } else{
                    System.debug('@@@@ H');
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        System.debug('@@@@ I');
                        //Need to display general ineligible code info
                        if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                            System.debug('@@@@ J');
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                        }
                        else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                            System.debug('@@@@ K');
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            System.debug('@@@@ L');
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.';
                        }
                        else{
                            System.debug('@@@@ M');
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
                        }}
                }
        }
        if(String.isNotBlank(cont.Electric_Utility_Number__c)) {
            Account elecAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Electric_Utility_Number__c LIMIT 1];
            System.debug('@@@ elecAcc: ' + elecAcc);
            codeStartsWithPp = checkIneligibleReasonCode(elecAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC'){
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
            } 
            else if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_You_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
            }
            else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true){
                eligibilityStatus = 'Eligible';
            } else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                }
                else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.. Thank you.';
                } else {
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance,';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        //Need to display general ineligible code info
                        if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                        }
                        else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program. For further assistance, please contact our offices. Thank you.';
                        }else{
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                        }}
            }
        }

        System.debug('@@@@ eligibilityStatus: ' + eligibilityStatus);

        return eligibilityStatus;
    }

    public static User getRunningUser() {
        Id runningUserId = UserInfo.getUserId();

        return [SELECT AccountId, ContactId, Account.BillingStreet, Account.BillingCity, Account.BillingState, Account.BillingCountry, Account.BillingPostalCode FROM User WHERE Id =: runningUserId];
    }

    public static Id createWorkOrder(User runningUser) {
        WorkType energyInHomeWt = [SELECT Id FROM WorkType WHERE Name = 'Energy Assessment - In Home' LIMIT 1];
        WorkOrder workOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId, Street=runningUser.Account.BillingStreet, WorkTypeId=energyInHomeWt.Id,
                City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry, PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert workOrder;
        } catch(DmlException e) {
            System.debug('Error in createWorkOrder: ' + e.getMessage());
        }

        return workOrder.Id;
    }

    public static Id createServiceAppointment(User runningUser, Id workOrderId) {
        ServiceAppointment serviceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=workOrderId, EarliestStartTime=Datetime.now().addMonths(1), DueDate=Datetime.now().addMonths(1),
            Street=runningUser.Account.BillingStreet, City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry,
            PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert serviceAppointment;
        } catch(DmlException e) {
            System.debug('Error in createServiceAppointment: ' + e.getMessage());
        }

        return serviceAppointment.Id;
    }

    private static Boolean checkIneligibleReasonCode(String ineligibleReasonCode) {
        Boolean codeStartsWithPp = false;
        if(String.isNotBlank(ineligibleReasonCode)) {
            if(ineligibleReasonCode.startsWith('PP')) {
                codeStartsWithPp = true;
            }
        }

        return codeStartsWithPp;
    }

    private static void deleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        try {
            delete [SELECT Id FROM WorkOrder WHERE Id =: workOrderId];
            delete [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
        } catch(DmlException e) {
            System.debug('Error in deleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }

    /*
    * Appointment booking returns the available slots for a service appointment, while considering scheduling policies, work rules, and service objectives.
    * */
    public static List<AppointmentBookingSlot> getSlots(Id serviceAppointmentId) {
        System.debug('@@@@ serviceAppointmentId: ' + serviceAppointmentId);
        ServiceAppointment serviceAppointment = [SELECT Id, AccountId, ContactId, EarliestStartTime, DueDate FROM ServiceAppointment WHERE Id =: serviceAppointmentId LIMIT 5];

        Id schedulingPolicyId = [SELECT Id, Name FROM FSL__Scheduling_Policy__c LIMIT 1].Id;

        Id operatingHoursId  = [SELECT Id, Name FROM OperatingHours WHERE Name = 'Energy Assessment Calendar' LIMIT 1].Id;

        Timezone tz = UserInfo.getTimeZone();
        System.debug('getting slots with....'+ serviceAppointment.Id + '//'+schedulingPolicyId+ '//'+operatingHoursId+ '//'+tz) ;
        List<FSL.AppointmentBookingSlot> slots = FSL.AppointmentBookingService.GetSlots(serviceAppointment.Id, schedulingPolicyId, operatingHoursId, tz, false);
        System.debug('slots: ' + slots);

        List<AppointmentBookingSlot> slotList = new List<AppointmentBookingSlot>();
        for(FSL.AppointmentBookingSlot slot : slots){
            DateTime slotStartDT = slot.interval.start;
            DateTime slotFinishDT = slot.interval.finish;
            Date slotStartDay = slotStartDT.date();
            
            if(slotStartDay > Date.today() ){
                AppointmentBookingSlot newSlot = new AppointmentBookingSlot();
                Interval times = new Interval();
                times.startDT = slot.interval.start;
                times.endDT = slot.interval.finish;
                newSlot.grade = slot.grade;
                newSlot.times = times;
                slotList.add(newSlot);
            }
        }
        System.debug('slotList:: '+ slotList);
        //I'm thinking they may want these ordered by rank, but not 100% sure. If so, we can do that with the comparable interface:
        //https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_comparable.htm --Chuck
        
        //return setToTimeZone(slotList);
        return slotList;
    }
    
    public static DateTime utcToUserTimezone(DateTime utcDT){
        DateTime userDT = utcDT;
        String utcDtString = utcDT.format('yyyy-MM-dd HH:mm:ss', 'UTC');
        //String utcDtString = utcDT.format('yyyy-MM-dd hh:mm a', 'UTC');

        System.debug('@@@@ str: '+utcDtString);
        userDT = DateTime.valueOf(utcDtString);
        System.debug('@@@@ DT: '+userDT);
        return userDT;
    }
    
    /*public static List<AppointmentBookingSlot> setToTimezone(List<AppointmentBookingSlot> slots){
        if(slots.isEmpty()){
            return slots;
        }
        String timeZone = UserInfo.getTimeZone().getID();

        for(AppointmentBookingSlot slot: slots){
            if(slot.times != NULL){
                System.debug('~~~~~~');
                System.debug('BEFORE: '+ slot.times.endDT);
                slot.times.startDT = Datetime.valueOf(slot.times.startDT);
                slot.times.endDT = Datetime.valueOf(slot.times.endDT);
                System.debug('AFTER: '+ slot.times.endDT.format());
            }
        }
        
        return slots;
    }*/
    
    

    public class CmpData {
        @AuraEnabled
        public Id workOrderId {get;set;}
        @AuraEnabled
        public Id serviceAppointmentId {get;set;}
        @AuraEnabled
        public List<AppointmentBookingSlot> slots {get;set;}
        @AuraEnabled
        public Boolean isEligibleCustomer {get;set;}
    }
    public class AppointmentBookingSlot {
        @AuraEnabled
        public Decimal grade {get;set;}
        @AuraEnabled
        public Interval times {get;set;}
    }
    public class Interval {
        @AuraEnabled
        public DateTime startDT {get;set;}
        @AuraEnabled
        public DateTime endDT {get;set;}
    }
}

 
Sai PraveenSai Praveen (Salesforce Developers) 
Hi Bob,

Can you try changing the Apex class little as below. There will be no change in functionality just best pratice. I have highlited the change.

Please find the below article (https://help.salesforce.com/s/articleView?id=000328824&type=1) for the same.
 
public without sharing class advic_fsl_AppointmentBooking {

    @AuraEnabled
    public static CmpData createWorkOrderAndServiceAppointment() {
        CmpData retData = new CmpData();
        User runningUser = getRunningUser();
        system.debug('Who is the running user: '+runningUser.AccountId);
        retData.isEligibleCustomer = checkCustomerEligibility(runningUser.AccountId);
        if(retData.isEligibleCustomer) {
            retData.workOrderId = createWorkOrder(runningUser);
            retData.serviceAppointmentId = createServiceAppointment(runningUser, retData.workOrderId);
        }
        
        return retData;
    }
    
    @AuraEnabled
    public static CmpData getAppointmentSlots(Id workOrderId, Id serviceAppointmentId) {
        System.debug('@@@@ HERE');
        CmpData retData = new CmpData();
        retData.slots = getSlots(serviceAppointmentId);
        // We delete the created Work Order and Service Appointment in case the user quits the process before scheduling his/her appointment.
        // Once the user confirms their scheduled appointment, we will undelete the Work Order and Service Appointment.
        deleteWorkOrderAndServiceAppointment(workOrderId, serviceAppointmentId);
        System.debug('@@@@ retData: ' + retData);
        return retData;
    }
    
    @AuraEnabled
    public static void undeleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        List<WorkOrder> deletedWorkOrders = [SELECT Id FROM WorkOrder WHERE Id =: workOrderId ALL ROWS];
        List<ServiceAppointment> deletedServiceAppointments = [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId ALL ROWS];
        try {
            undelete deletedWorkOrders;
            undelete deletedServiceAppointments;
        } catch(DmlException e) {
            System.debug('Error in undeleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }
    
    @AuraEnabled
    public static void updateServiceAppointment(String slotJSON, Id serviceAppointmentId, String detailsAccount, String detailsServiceAppt) {
        System.debug(slotJSON);
        System.debug(serviceAppointmentId);
        System.debug(detailsAccount);
        System.debug(detailsServiceAppt);
        AppointmentBookingSlot slot = (AppointmentBookingSlot)JSON.deserialize(slotJSON, advic_fsl_AppointmentBooking.AppointmentBookingSlot.class);
        try{
            ServiceAppointment serviceAppointment = [SELECT ArrivalWindowStartTime, ArrivalWindowEndTime, Status, Additional_Details__c FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
            serviceAppointment.ArrivalWindowStartTime = utcToUserTimezone(slot.times.startDT);
            serviceAppointment.ArrivalWindowEndTime = utcToUserTimezone(slot.times.endDT);
            
            serviceAppointment.Status = 'Scheduled';
            ServiceAppointment.Additional_Details__c = detailsServiceAppt;
            
            User runningUser = getRunningUser();
            system.debug('Who is the running user: '+runningUser.AccountId);
            Account account = [SELECT Additional_Details__c FROM Account WHERE Id =: runningUser.AccountId];
            account.Additional_Details__c = detailsAccount;
            
            update serviceAppointment;
            update account;
        } catch(DmlException e) {
            System.debug('updateServiceAppointment: ' + serviceAppointmentId + ' Error: ' + + e.getMessage());
        }
        
    }
    
    @AuraEnabled
    public static void scheduleServiceAppointment(Id serviceAppointmentId) {
        Public Id schedulingPolicyId;

        List<FSL__Scheduling_Policy__c> schlist= new List<FSL__Scheduling_Policy__c>();
        schlist=[SELECT Id, Name FROM FSL__Scheduling_Policy__c WHERE Name = 'Customer First' LIMIT 1];

        if(schlist.size()<0)
        {
         schedulingPolicyId = schlist[0].Id;
        }
        
        //Schedules the service appointment in the best available slot. If there are no available slots, the appointment isn’t scheduled.
        FSL.ScheduleResult result = new FSL.ScheduleResult();
        //Returns the result of the scheduling process.
        System.debug('svcApptId to Svc: '+ serviceAppointmentId);
        result = FSL.ScheduleService.schedule(schedulingPolicyId, serviceAppointmentId);
        try{
            System.debug('FSL.ScheduleService result: ' + JSON.serializePretty(result));
        }
        catch(Exception e){
            System.debug('JSON ERROR. On: '+ result);
        }
    }
    
    private static Boolean checkCustomerEligibility(Id accountId) {
        Account account = [SELECT Customer_Eligible__c FROM Account WHERE Id =: accountId];
        
        //return account.Customer_Eligible__c;
        return true; //for testing only.
    }
    //new eligibility that we need to incoporate REMS-191
    @AuraEnabled
    public static String checkAccountEligibility() {
        String eligibilityStatus = '';
        Boolean codeStartsWithPp = false;
        User runningUser = getRunningUser();
        Contact cont = [SELECT Electric_Utility_Number__c, Gas_Utility_Number__c, How_do_you_heat_your_home__c, AccountId, Part_of_Condo_Association__c FROM Contact WHERE Id =: runningUser.ContactId];
        System.debug('@@@ cont.Gas_Utility_Number__c: ' + cont.Gas_Utility_Number__c);
        System.debug('@@@ cont.Electric_Utility_Number__c: ' + cont.Electric_Utility_Number__c);
        if(String.isBlank(cont.Gas_Utility_Number__c) && String.isBlank(cont.Electric_Utility_Number__c)) {
            Account account = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Square_Footage__c, Building_Type__c FROM Account WHERE Id = :cont.AccountId];
            System.debug('@@@ account: ' + account);
            codeStartsWithPp = checkIneligibleReasonCode(account.Ineligible_Reason_Code__c);
            if(account.Eligible_Testing__c == false) {
                //Need to display general ineligible code info
                if(account.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property. Please contact your local Community Action Partnership, or call our offices for more information.';
                }
                else if(account.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Please contact out office for further assistance at 401-000-0000';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you  Thank you.';
                } else if(account.Ineligible_Reason_Code__c != 'DISC' || account.Ineligible_Reason_Code__c != 'COM' || !codeStartsWithPp){
                eligibilityStatus = 'thank you';
                } else{
                    eligibilityStatus = 'thank you';                    
                }
            } else if(account.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || account.Building_Type__c != 'Single-Family Home' || account.Square_Footage__c == '3000-3500 sq ft' || account.Square_Footage__c == '3500-6000 sq ft' || account.Square_Footage__c == '6000+ sq ft')){
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';                    
            } else {
                eligibilityStatus = 'Eligible';
                }}
        if(String.isNotBlank(cont.Gas_Utility_Number__c)) {
            Account gasAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Gas_Utility_Number__c LIMIT 1];
            System.debug('@@@ gasAcc: ' + gasAcc);
            codeStartsWithPp = checkIneligibleReasonCode(gasAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || gasAcc.Building_Type__c != 'Single-Family Home' || gasAcc.Square_Footage__c == '3000-3500 sq ft' || gasAcc.Square_Footage__c == '3500-6000 sq ft' || gasAcc.Square_Footage__c == '6000+ sq ft')){
                System.debug('@@@@ A');
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices. ';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == true && gasAcc.Ineligible_Reason_Code__c != 'DISC'){
                System.debug('@@@@ B');
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                System.debug('@@@@ C');
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
            } else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && gasAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                System.debug('@@@@ D');
                if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                    System.debug('@@@@ E');
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                }
                else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                    System.debug('@@@@ F');
                    eligibilityStatus = 'Due';
                }
                else if(codeStartsWithPp){
                    System.debug('@@@@ G');
                    eligibilityStatus = 'We are not able to schedule you';
                } else{
                    System.debug('@@@@ H');
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        System.debug('@@@@ I');
                        //Need to display general ineligible code info
                        if(gasAcc.Ineligible_Reason_Code__c == 'DISC'){
                            System.debug('@@@@ J');
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.';
                        }
                        else if(gasAcc.Ineligible_Reason_Code__c == 'COM'){
                            System.debug('@@@@ K');
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            System.debug('@@@@ L');
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.';
                        }
                        else{
                            System.debug('@@@@ M');
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
                        }}
                }
        }
        if(String.isNotBlank(cont.Electric_Utility_Number__c)) {
            Account elecAcc = [SELECT Eligible_Testing__c, Ineligible_Reason_Code__c, Building_Type__c, Square_Footage__c FROM Account WHERE Utility_Number__c =: cont.Electric_Utility_Number__c LIMIT 1];
            System.debug('@@@ elecAcc: ' + elecAcc);
            codeStartsWithPp = checkIneligibleReasonCode(elecAcc.Ineligible_Reason_Code__c);
            if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC' && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c != 'DISC'){
                eligibilityStatus = 'Eligible';
            }
            else if(cont.How_do_you_heat_your_home__c == 'Natural Gas' && elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                //Need to display DISC code info:
                eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
            } 
            else if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_You_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true && (cont.Part_of_Condo_Association__c == 'Yes' || elecAcc.Building_Type__c != 'Single-Family Home' || elecAcc.Square_Footage__c == '3000-3500 sq ft' || elecAcc.Square_Footage__c == '3500-6000 sq ft' || elecAcc.Square_Footage__c == '6000+ sq ft')){
                eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time.';
            }
            else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == true){
                eligibilityStatus = 'Eligible';
            } else  if(cont.How_do_you_heat_your_home__c != 'Natural Gas' && cont.How_do_you_heat_your_home__c != 'None' && elecAcc.Eligible_Testing__c == false){
                //Need to display general ineligible code info
                if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                    eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                }
                else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                    eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                }
                else if(codeStartsWithPp){
                    eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program.. Thank you.';
                } else {
                    eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance,';
                }} else {
                    if (cont.How_do_you_heat_your_home__c == 'None') {
                        //Need to display general ineligible code info
                        if(elecAcc.Ineligible_Reason_Code__c == 'DISC'){
                            eligibilityStatus = 'Due to your utility service rate code, we are not able to service your property.  Thank you.';
                        }
                        else if(elecAcc.Ineligible_Reason_Code__c == 'COM'){
                            eligibilityStatus = 'Due to the commercial rate code on this property, we are not able to schedule a residential No-Cost Energy Assessment.';
                        }
                        else if(codeStartsWithPp){
                            eligibilityStatus = 'We are not able to schedule you a No-Cost energy assessment due to the recent participation in the program. For further assistance, please contact our offices. Thank you.';
                        }else{
                            eligibilityStatus = 'Thank you for your inquiry, we are unable to complete your request at this time. For further assistance, please contact our offices.';
                        }}
            }
        }

        System.debug('@@@@ eligibilityStatus: ' + eligibilityStatus);

        return eligibilityStatus;
    }

    public static User getRunningUser() {
        Id runningUserId = UserInfo.getUserId();

        return [SELECT AccountId, ContactId, Account.BillingStreet, Account.BillingCity, Account.BillingState, Account.BillingCountry, Account.BillingPostalCode FROM User WHERE Id =: runningUserId];
    }

    public static Id createWorkOrder(User runningUser) {
        WorkType energyInHomeWt = [SELECT Id FROM WorkType WHERE Name = 'Energy Assessment - In Home' LIMIT 1];
        WorkOrder workOrder = new WorkOrder(AccountId=runningUser.AccountId, ContactId=runningUser.ContactId, Street=runningUser.Account.BillingStreet, WorkTypeId=energyInHomeWt.Id,
                City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry, PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert workOrder;
        } catch(DmlException e) {
            System.debug('Error in createWorkOrder: ' + e.getMessage());
        }

        return workOrder.Id;
    }

    public static Id createServiceAppointment(User runningUser, Id workOrderId) {
        ServiceAppointment serviceAppointment = new ServiceAppointment(ContactId=runningUser.ContactId, ParentRecordId=workOrderId, EarliestStartTime=Datetime.now().addMonths(1), DueDate=Datetime.now().addMonths(1),
            Street=runningUser.Account.BillingStreet, City=runningUser.Account.BillingCity, State=runningUser.Account.BillingState, Country=runningUser.Account.BillingCountry,
            PostalCode=runningUser.Account.BillingPostalCode);
        try {
            insert serviceAppointment;
        } catch(DmlException e) {
            System.debug('Error in createServiceAppointment: ' + e.getMessage());
        }

        return serviceAppointment.Id;
    }

    private static Boolean checkIneligibleReasonCode(String ineligibleReasonCode) {
        Boolean codeStartsWithPp = false;
        if(String.isNotBlank(ineligibleReasonCode)) {
            if(ineligibleReasonCode.startsWith('PP')) {
                codeStartsWithPp = true;
            }
        }

        return codeStartsWithPp;
    }

    private static void deleteWorkOrderAndServiceAppointment(Id workOrderId, Id serviceAppointmentId) {
        try {
            delete [SELECT Id FROM WorkOrder WHERE Id =: workOrderId];
            delete [SELECT Id FROM ServiceAppointment WHERE Id =: serviceAppointmentId];
        } catch(DmlException e) {
            System.debug('Error in deleteWorkOrderAndServiceAppointment: ' + e.getMessage());
        }
    }

    /*
    * Appointment booking returns the available slots for a service appointment, while considering scheduling policies, work rules, and service objectives.
    * */
    public static List<AppointmentBookingSlot> getSlots(Id serviceAppointmentId) {
        System.debug('@@@@ serviceAppointmentId: ' + serviceAppointmentId);
        ServiceAppointment serviceAppointment = [SELECT Id, AccountId, ContactId, EarliestStartTime, DueDate FROM ServiceAppointment WHERE Id =: serviceAppointmentId LIMIT 5];

        Id schedulingPolicyId = [SELECT Id, Name FROM FSL__Scheduling_Policy__c LIMIT 1].Id;

        Id operatingHoursId  = [SELECT Id, Name FROM OperatingHours WHERE Name = 'Energy Assessment Calendar' LIMIT 1].Id;

        Timezone tz = UserInfo.getTimeZone();
        System.debug('getting slots with....'+ serviceAppointment.Id + '//'+schedulingPolicyId+ '//'+operatingHoursId+ '//'+tz) ;
        List<FSL.AppointmentBookingSlot> slots = FSL.AppointmentBookingService.GetSlots(serviceAppointment.Id, schedulingPolicyId, operatingHoursId, tz, false);
        System.debug('slots: ' + slots);

        List<AppointmentBookingSlot> slotList = new List<AppointmentBookingSlot>();
        for(FSL.AppointmentBookingSlot slot : slots){
            DateTime slotStartDT = slot.interval.start;
            DateTime slotFinishDT = slot.interval.finish;
            Date slotStartDay = slotStartDT.date();
            
            if(slotStartDay > Date.today() ){
                AppointmentBookingSlot newSlot = new AppointmentBookingSlot();
                Interval times = new Interval();
                times.startDT = slot.interval.start;
                times.endDT = slot.interval.finish;
                newSlot.grade = slot.grade;
                newSlot.times = times;
                slotList.add(newSlot);
            }
        }
        System.debug('slotList:: '+ slotList);
        //I'm thinking they may want these ordered by rank, but not 100% sure. If so, we can do that with the comparable interface:
        //https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_comparable.htm --Chuck
        
        //return setToTimeZone(slotList);
        return slotList;
    }
    
    public static DateTime utcToUserTimezone(DateTime utcDT){
        DateTime userDT = utcDT;
        String utcDtString = utcDT.format('yyyy-MM-dd HH:mm:ss', 'UTC');
        //String utcDtString = utcDT.format('yyyy-MM-dd hh:mm a', 'UTC');

        System.debug('@@@@ str: '+utcDtString);
        userDT = DateTime.valueOf(utcDtString);
        System.debug('@@@@ DT: '+userDT);
        return userDT;
    }
    
    /*public static List<AppointmentBookingSlot> setToTimezone(List<AppointmentBookingSlot> slots){
        if(slots.isEmpty()){
            return slots;
        }
        String timeZone = UserInfo.getTimeZone().getID();

        for(AppointmentBookingSlot slot: slots){
            if(slot.times != NULL){
                System.debug('~~~~~~');
                System.debug('BEFORE: '+ slot.times.endDT);
                slot.times.startDT = Datetime.valueOf(slot.times.startDT);
                slot.times.endDT = Datetime.valueOf(slot.times.endDT);
                System.debug('AFTER: '+ slot.times.endDT.format());
            }
        }
        
        return slots;
    }*/
    
    

    public class CmpData {
        @AuraEnabled
        public Id workOrderId {get;set;}
        @AuraEnabled
        public Id serviceAppointmentId {get;set;}
        @AuraEnabled
        public List<AppointmentBookingSlot> slots {get;set;}
        @AuraEnabled
        public Boolean isEligibleCustomer {get;set;}
    }
    public class AppointmentBookingSlot {
        @AuraEnabled
        public Decimal grade {get;set;}
        @AuraEnabled
        public Interval times {get;set;}
    }
    public class Interval {
        @AuraEnabled
        public DateTime startDT {get;set;}
        @AuraEnabled
        public DateTime endDT {get;set;}
    }
}

Let me know if you face any issues.

If this solution helps, Please mark it as best answer.

Thanks,
This was selected as the best answer
mukesh guptamukesh gupta
Hi Bob,

Just simple 

Please add below line in your test class:-

Method name:- testScheduleServiceAppointment
add below line on Line number 138 in your test class and save and run your test class
FSL__Scheduling_Policy__c fslObj = [SELECT Id, Name FROM FSL__Scheduling_Policy__c WHERE Name = 'Customer First' LIMIT 1];

if you need any assistanse, Please let me know!!

Kindly mark my solution as the best answer if it helps you.

Thanks
Mukesh 
Bob 11Bob 11
Hi Sai,
I am getting the below error when i updated my class 
User-added image

Hi Mukesh,
I will try adding your code to my test class and recieved these errors below
User-added image
Sai PraveenSai Praveen (Salesforce Developers) 
Hi Bob,

Can you remove Public  access modifier in line 72 and try to save it.

Thanks,
 
Bob 11Bob 11
Hi Sai,
I updated that ection of code like this, but it is giving more errors when i try to deploy to production

 @AuraEnabled
    public static void scheduleServiceAppointment(Id serviceAppointmentId) {
         
        Id schedulingPolicyId;

        List<FSL__Scheduling_Policy__c> schlist= new List<FSL__Scheduling_Policy__c>();
        schlist=[SELECT Id, Name FROM FSL__Scheduling_Policy__c WHERE Name = 'New Scheduling Policy' LIMIT 1];

        if(schlist.size()<0)
        {
         schedulingPolicyId = schlist[0].Id;
        }
Sai PraveenSai Praveen (Salesforce Developers) 
Hi Bob,

Can you share what are those error. Are you getting error on the same line again?

Did your test class ran succesfully in developer console?

Thanks,
 
Bob 11Bob 11
Hi Sai,

here are the errors below. The test class did run successfully in my sandbox console and in the production console. I'm not sur eif i have the code right where i removed the public access method

User-added image
Sai PraveenSai Praveen (Salesforce Developers) 
Hi Bob,

The screenshot which you shared is not much clear . Check those lines in test class and change the assertion values accordingly.

This should resolve the issue and mainly the issue which you reported is resolved and this is issue with your test class implementation  and data and you have to change the assertion values based on it.

Let me know if you face any issues.

If this solution helps, Please mark it as best answer.

Thanks,
Bob 11Bob 11
It looks like it is giving me a not enough coverage error now

System.QueryException: List has no rows for assignment to SObject
Stack Trace: Class.advic_fsl_AppointmentBooking.getSlots: line 302, column 1 Class.advic_fsl_AppointmentBooking.getAppointmentSlots: line 21, column 1 Class.advic_fsl_AppointmentBookingTest.testGetAppointmentSlots: line 80, column 1

System.QueryException: List has no rows for assignment to SObject
Stack Trace: Class.advic_fsl_AppointmentBookingTest.testScheduleServiceAppointment: line 139, column 1