How to improve the coverage of this test class in Apex? - salesforce

I have created a test class with 51% code coverage till line no 34.
Further, I tried to satisfy if condition but I couldn't. Now I am not getting how to do with 100% code coverage.
Here is the Apex class:
public class AssignProjectController {
public String CaseIds;
public String status {get;set;}
public List<Project__c> activeProjects {get;set;}
public String keyWordSearched {get;set;}
public Id projectId {get;set;}
public AssignProjectController (){
CaseIds = ApexPages.currentPage().getParameters().get('id');
}
public void getProjects(){
status = '';
String searchQuery = 'FIND \'' + keyWordSearched + '*\' IN ALL FIELDS RETURNING Project__c (id,Name,Description__c where Status__c =\'Active\')';
try{
List<List<Project__c >> searchList = search.query(searchQuery);
activeProjects = searchList[0];
if(activeProjects.size() == 0) status = 'No search result found.';
}catch(Exception ex){
system.debug('ex..'+ex.getMessage());
}}}
public PageReference assignProjectToCases(){
List<Case__c> customSettingList = Case__c.getall().values();
List<String> settingRecordTypeList = new List<String>();
for(Case__c caseObj:customSettingList){
settingRecordTypeList.add(caseObj.Name);
}
List<RecordType> recordTypeListData = [SELECT Id FROM RecordType WHERE SObjectType = 'Case' and Name In : settingRecordTypeList];
if(CaseIds != null){
List<String> caseIDList = new List<String>();
caseIDList = CaseIds.split(',');
if([Select id from Case where Id In : caseIDList and RecordType.Id NOT In : recordTypeListData].size() > 0){
status = 'failed';
}else{
List<Case> cases = [Select id,Project__c,RecordType.Name from Case where Id In : caseIDList and RecordType.Id In : recordTypeListData];
if(cases.size() > 0){
for(case caseOb: cases){
caseOb.Project__c = projectId ;
}
try{
update cases ;
status = 'Changes are scheduled';
}catch(Exception ex){
system.debug('AssignProjectController :::'+ex.getMessage());
status = 'Something Went Wrong';
}}}}
return null;
}}
Here is the test class- which I tried to resolve
#isTest public class TestAssignProjectController {
public static Project__c insertProject(){
Project__c proObj = new Project__c();
proObj.Name = 'testProject';
proObj.Status__c = 'Active';
proObj.Description__c = 'for testing';
proObj.Internal_Email_Alias__c = 'a#test.com';
return proObj;
}
public static Account getAccount(){
Account accoObj = new Account();
accoObj.Name = 'testAcc';
accoObj.Location__c = 'testLocation';
accoObj.Type = 'CM';
accoObj.BillingCountry = 'United States';
return accoObj;
}
public static Contact insertContact(Account accObj){
Contact conObj = new Contact();
conObj.FirstName = 'test';
conObj.LastName = 'testLastname';
conObj.AccountId = accObj.Id;
conObj.Email = 'abc#gmail.com';
return conObj;
}
public static Id getTechTypeId(){
return Schema.SObjectType.Case.getRecordTypeInfosByName().get('Tech ').getRecordTypeId();
}
public static Case insertCase(String conId, String proId){
Case caseObj = new Case();
caseObj.Project__c = proId;
caseObj.ContactId = conId;
caseObj.Status = 'Open';
caseObj.Inquiry_Type__c = 'All';
caseObj.Subject = 'TestSubject';
caseObj.Description = 'TestDescription';
caseObj.Case_Is_Reopened__c = false;
caseObj.RecordTypeId = getTechTypeId();
return caseObj;
}
public static testmethod void testMethodExecution(){
AssignController asigncon = new AssignController ();
Project__c proObj = insertProject();
insert proObj;
System.assertEquals(proObj.Status__c,'Active');
Account accObj = getAccount();
insert accObj;
System.assertNotEquals(accObj.Id,null);
Contact conObj = insertContact(accObj);
insert conObj;
System.assertNotEquals(conObj.Id,null);
Case caseObj = insertCase(conObj.Id, proObj.Id);
insert caseObj;
system.debug(caseObj);
//Set baseURL & case ID
PageReference pageRef = Page.Assign;
pageRef.getParameters().put('id',caseObj.id+',');
AssignController asigncon1 = new AssignController ();
asigncon1.getProjects();
asigncon1.assignProjectToCases();
}}

If you are referring if(cases.size() > 0) this statement, then surely there is problem of inserting the case. Make sure that insert caseObj; is working and inserts data in Salesforce backend.
If there is no data in case object, the test method cannot cover the if statement.

Related

when clicked on button "reschedule scheduled service" spinner keeps on loading

trying to reschedule the calim but when clicked on button spinner keeps on rotating and unable to reschedule
see the screenshots for the error
Creatfurniturecontroller.js
createFurnitureServiceInfo : function(component) {
var scheduleServiceWrapper = component.get('v.scheduleService');
var scheduleServiceWrappperComments = scheduleServiceWrapper.Comments.replace(/\\/g, '');
var escapedComments = this.encodeSpecialCharacters(scheduleServiceWrappperComments);
scheduleServiceWrapper.Comments = escapedComments;
scheduleServiceWrapper.ButtonLabel = component.get('v.buttonLabel');
component.set('v.isLoading',true);
var isIndependentServicer = component.get('v.isIndependentServicerChecked');
var independentServicer = component.get('v.independentServicer');
var action = component.get('c.createFurnitureServices');
var parameters = {
"scheduleServiceJSON": JSON.stringify(scheduleServiceWrapper),
"independentServicerJSON": JSON.stringify(independentServicer),
"isIndependentServicer": isIndependentServicer
};
//console.log('params: ' + JSON.stringify(parameters));
action.setParams(parameters);
action.setCallback(this, function(response) {
component.set('v.isLoading',false);
var state = response.getState();
if (state === "SUCCESS") {
this.displayToast('Success', 'The service has been successfully scheduled.','success');
var navEvt = $A.get("e.force:navigateToSObject");
navEvt.setParams({
"recordId": response.getReturnValue(),
"slideDevName": "detail"
});
this.closeModal(component);
this.refreshFurnitureServiceRecord();
navEvt.fire();
} else {
console.error(response.getError());
this.displayToast('Error', 'Something went wrong, the service was NOT scheduled. Please verify zip code and additional address fields.','error');
}
});
$A.enqueueAction(action);
},
refreshFurnitureServiceRecord : function() {
window.setTimeout(
$A.getCallback(function() {
var refreshFurnitureServiceEvent = $A.get("e.c:refreshFurnitureServiceEvent");
refreshFurnitureServiceEvent.fire();
}), 2000
);
},
getDayOfWeek : function(serviceDate) {
var momentDate = moment(serviceDate);
var weekDay = momentDate.format('dddd');
return weekDay;
},
formatServiceDate : function(serviceDate) {
return serviceDate.substring(5, 7) + '/' + serviceDate.substring(8, 10) + '/' + serviceDate.substring(0, 4);
},
displayToast : function(title, message, type, mode){
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
title : title,
message: message,
duration:' 5000',
key: 'info_alt',
type: type,
mode: mode ? mode : 'pester'
});
toastEvent.fire();
},
getRelatedCase : function(component, event, helper) {
var workspaceAPI = component.find("workspace");
workspaceAPI.getFocusedTabInfo().then(function(response) {
//console.log(JSON.parse(JSON.stringify(response)));
var parentTabId = response.parentTabId;
workspaceAPI.getTabInfo({
tabId: parentTabId
}).then(function(parentTabResponse) {
var parentTabObjectAPIName = parentTabResponse.pageReference.attributes.objectApiName;
//console.log(parentTabObjectAPIName);
// If the parent tab is a Case record
if(parentTabObjectAPIName === "Case"){
var caseRecord = {
"recordId" : parentTabResponse.recordId,
"label" : parentTabResponse.title
}
component.set('v.caseRecord',caseRecord);
} else {
// If the parent tab is not a Case record
var relatedSubTabs = parentTabResponse.subtabs;
for (let i = 0; i < relatedSubTabs.length; i++) {
var subtab = relatedSubTabs[i];
var subTabObjectAPIName = subtab.pageReference.attributes.objectApiName;
if(subTabObjectAPIName === "Case"){
var caseRecord = {
"recordId" : subtab.recordId,
"label" : subtab.title
}
component.set('v.caseRecord',caseRecord);
}
}
}
helper.fetchCaseData(component, event, helper);
});
})
.catch(function(error) {
console.log(error);
});
},
isValidToSave : function(component, event, helper) {
var validityErrors = [];
var notPopulatedRequiredFields = [];
var isIndependentServicer = component.get('v.isIndependentServicerChecked');
try {
// validation for both: regular and independent servicer scheduling
let serviceDateField = isIndependentServicer ? component.find('serviceDate2') : component.find('serviceDate');
serviceDateField.reportValidity();
if (!serviceDateField.get('v.value')) validityErrors.push('Service Date must be selected.');
let addressField = isIndependentServicer ? component.find('addressField2a') : component.find('addressField');
addressField.reportValidity();
if (!addressField.get('v.value')) notPopulatedRequiredFields.push('address');
let zipCodeField = isIndependentServicer ? component.find('zipCodeField2') : component.find('zipCodeField');
zipCodeField.reportValidity();
if (!zipCodeField.get('v.value')) notPopulatedRequiredFields.push('zip code');
let stateField = isIndependentServicer ? component.find('stateField2') : component.find('stateField');
stateField.reportValidity();
if (!stateField.get('v.value')) notPopulatedRequiredFields.push('state');
let cityField = isIndependentServicer ? component.find('cityField2') : component.find('cityField');
cityField.reportValidity();
if (!cityField.get('v.value')) notPopulatedRequiredFields.push('city');
// validation for independent servicer scheduling
if (isIndependentServicer) {
var caseRecord = component.get('v.caseRecord');
if (!caseRecord || !caseRecord.Id) validityErrors.push('Selecting case related to service is required.');
if (!caseRecord.Independent_Servicer__r) {
validityErrors.push('Independent Servicer needs to be assigned to the selected Case.');
} else if (!caseRecord.Independent_Servicer__r.Servicer_Id__c) {
validityErrors.push('Independent Servicer assigned to the selected Case needs to have Servicer Id value.');
}
let callBackContactField = component.find('callBackContact');
callBackContactField.reportValidity();
if (!callBackContactField.get('v.value')) notPopulatedRequiredFields.push('contact');
let callBackNumberField = component.find('callBackNumber');
callBackNumberField.reportValidity();
if (!callBackNumberField.get('v.value')) {
notPopulatedRequiredFields.push('phone');
} else if (callBackNumberField.get('v.value').length != 10) {
validityErrors.push('Phone field must be 10 digits long.');
}
} else {
// validation for regular scheduling
var routeCode = component.get('v.selectedRouteCode');
if($A.util.isUndefinedOrNull(routeCode) || $A.util.isEmpty(routeCode) || routeCode.trim() == ''){
validityErrors.push('A Route code is required.');
}
var selectedAvailableAppointmentUnits = Number(component.get('v.selectedAppointmentUnits'));
var availableUnits = Number(component.get('v.scheduleService.AppointmentUnits'));
if(availableUnits > selectedAvailableAppointmentUnits){
validityErrors.push('There is not enough appointment units available for the selected service date.');
}
}
if (isIndependentServicer) {
if (notPopulatedRequiredFields.length > 0) validityErrors.push('You need to populate those fields on the selected case: ' + notPopulatedRequiredFields.join(', ') + '.');
} else {
if (notPopulatedRequiredFields.length > 0) validityErrors.push('You need to populate those fields: ' + notPopulatedRequiredFields.join(', ') + '.');
}
} catch(err) {
console.error(err);
}
return validityErrors;
},
isIndependentServicerCheckedChanged : function(component, event, helper) {
let checkboxValue = component.get('v.isIndependentServicerChecked');
try{
// If the checkbox was checked
if(checkboxValue){
// Set service date as current date
component.set('v.selectedServiceDate', new Date().toISOString().slice(0, 10));
let caseRecord = component.get('v.caseRecord');
let scheduleService = component.get('v.scheduleService');
// If this property is already filled, it means the service was already scheduled once, so we should consider data from POPS
if(scheduleService.Servicer){
let independentServicer = {
CustomerName : scheduleService.CustomerName,
Address : scheduleService.Address,
ZipCode : scheduleService.ZipCode,
State : scheduleService.State,
City : scheduleService.City,
ContactPhone : scheduleService.ContactPhone,
ContactPhoneExtension : scheduleService.ContactPhoneExtension,
Servicer : caseRecord.Independent_Servicer__r.Servicer_Id__c,
CaseId : caseRecord.Id
};
component.set('v.independentServicer',independentServicer);
} else {
// This means it's the first time creating the independent servicer furniture service, so we should consider data from the associated Case
let independentServicer = {
CustomerName : caseRecord.Call_Back_Contact__c,
Address : caseRecord.Shipping_Address_1__c,
ZipCode : caseRecord.Shipping_Postal_Code__c,
State : caseRecord.Shipping_State__c,
City : caseRecord.Shipping_City__c,
ContactPhone : caseRecord.Requested_Call_Back_Number__c,
ContactPhoneExtension : caseRecord.Requested_Call_Back_Number_Ext__c,
Servicer : caseRecord.Independent_Servicer__r.Servicer_Id__c,
CaseId : caseRecord.Id
};
component.set('v.independentServicer',independentServicer);
}
} else {
component.set('v.selectedServiceDate', null);
}
} catch (err) {
console.error(err);
}
}
})
Apex class
public without sharing class CreateFurnitureServicesCtrl {
#AuraEnabled
public static ScheduleServiceWrapper getScheduleServiceWrapper(String claimRecordId){
String[] claimFieldsList = new List<String>{
'Id', 'OrderNumber__c','AccountNumber__c', 'ClaimId__c'
};
Map<String,String> claimsFieldValueMap = new Map<String,String>();
claimsFieldValueMap.put('Id',claimRecordId);
Claims__x objClaims = nfm_ExternalClaimRequest.getClaims(claimFieldsList, claimsFieldValueMap, 'Id', 'ASC')[0];
String[] orderDetailsFieldsList = new List<String>{
'Id','CustomerZip__c','CustomerPhone__c','OrderState__c','OrderCity__c','CustomerState__c','CustomerCity__c','DistributionMethod__c',
'AccountNumber__c','OrderNumber__c','OrderZip__c', 'OrderPrimaryCallAhPhExt__c', 'CustomerName__c',
'CustomerAddress1__c','CustomerAddress2__c','OrderAddress1__c','OrderAddress2__c'
};
Map<String,String> orderDetailsFieldValueMap = new Map<String,String>();
orderDetailsFieldValueMap.put('OrderNumber__c',objClaims.OrderNumber__c);
OrderDetails__x objOrderDetails = nfm_ExternalOrderDetailsRequest.getOrders(orderDetailsFieldsList, orderDetailsFieldValueMap, 'Id', 'ASC', false)[0];
ScheduleServiceWrapper objScheduleServiceWrapper = new ScheduleServiceWrapper();
objScheduleServiceWrapper.NumberOfDays = 15;
objScheduleServiceWrapper.AppointmentUnits = 1;
objScheduleServiceWrapper.StartDate = String.valueOf(System.today());
objScheduleServiceWrapper.ClaimId = objClaims.ClaimId__c;
objScheduleServiceWrapper.ServiceDate = 'TBD';
objScheduleServiceWrapper.RouteCode = 'TBD';
objScheduleServiceWrapper.ServiceCode = 'TBD';
objScheduleServiceWrapper.Comments = ' ';
FurnitureServices__x objFurnitureServices = getPreviousFurnitureService(objClaims.ClaimId__c);
Set<String> customerDistributionSet = new Set<String>{'P','T'};
Set<String> orderDistributionSet = new Set<String>{'D','W','I','O'};
// Here we're verifying if a basic field is blank, so that means that the furnite service hasn't been scheduled yet
if(objFurnitureServices.InspectAddress1__c == null){
// In this case, the details are filled according to the Order's Delivery Method
objScheduleServiceWrapper.CustomerName = objOrderDetails.CustomerName__c;
objScheduleServiceWrapper.ContactName = objOrderDetails.CustomerName__c;
objScheduleServiceWrapper.ContactPhone = objOrderDetails.CustomerPhone__c;
if(customerDistributionSet.contains(objOrderDetails.DistributionMethod__c)){ // Customer
objScheduleServiceWrapper.City = objOrderDetails.CustomerCity__c;
objScheduleServiceWrapper.State = objOrderDetails.CustomerState__c;
objScheduleServiceWrapper.ZipCode = objOrderDetails.CustomerZip__c.substring(0,5);
objScheduleServiceWrapper.Address = objOrderDetails.CustomerAddress1__c + ' ' + nfm_Utils.ifNull(objOrderDetails.CustomerAddress2__c,'');
} else if(orderDistributionSet.contains(objOrderDetails.DistributionMethod__c)) { //Order
objScheduleServiceWrapper.City = objOrderDetails.OrderCity__c;
objScheduleServiceWrapper.State = objOrderDetails.OrderState__c;
objScheduleServiceWrapper.ZipCode = objOrderDetails.OrderZip__c.substring(0,5);
objScheduleServiceWrapper.ContactPhoneExtension = objOrderDetails.OrderPrimaryCallAhPhExt__c;
objScheduleServiceWrapper.Address = objOrderDetails.OrderAddress1__c + ' ' + nfm_Utils.ifNull(objOrderDetails.OrderAddress2__c,'');
}
} else {
// In this case, the details are filled according to the previous Furniture Service
objScheduleServiceWrapper.CustomerName = objFurnitureServices.InspectName__c;
objScheduleServiceWrapper.ContactName = objFurnitureServices.ContactDescription__c;
objScheduleServiceWrapper.ContactPhone = objFurnitureServices.ContactPhone__c;
objScheduleServiceWrapper.ContactPhoneExtension = objFurnitureServices.ContactPhoneExtension__c;
objScheduleServiceWrapper.Address = objFurnitureServices.InspectAddress1__c;
objScheduleServiceWrapper.City = objFurnitureServices.InspectCity__c;
objScheduleServiceWrapper.State = objFurnitureServices.InspectState__c;
objScheduleServiceWrapper.ZipCode = objFurnitureServices.InspectZip__c.substring(0,5);
}
objScheduleServiceWrapper.Servicer = nfm_Utils.ifNull(objFurnitureServices.Servicer__c,'');
return objScheduleServiceWrapper;
}
public class ScheduleServiceWrapper{
#AuraEnabled public String ClaimId{get;set;}
#AuraEnabled public String ZipCode{get;set;}
#AuraEnabled public String StartDate{get;set;}
#AuraEnabled public String ServiceDate{get;set;}
#AuraEnabled public String ServiceCode{get;set;}
#AuraEnabled public String RouteCode{get;set;}
#AuraEnabled public Integer NumberOfDays{get;set;}
#AuraEnabled public Integer AppointmentUnits{get;set;}
#AuraEnabled public String CustomerName{get;set;}
#AuraEnabled public String Address{get;set;}
#AuraEnabled public String Servicer{get;set;}
#AuraEnabled public String State{get;set;}
#AuraEnabled public String City{get;set;}
#AuraEnabled public String ContactName{get;set;}
#AuraEnabled public String ContactPhone{get;set;}
#AuraEnabled public String ContactPhoneExtension{get;set;}
#AuraEnabled public String Comments{get;set;}
#AuraEnabled public String ButtonLabel{get;set;}
}
public class IndependentServicerWrapper{
#AuraEnabled public String CustomerName{get;set;}
#AuraEnabled public String Address{get;set;}
#AuraEnabled public String State{get;set;}
#AuraEnabled public String City{get;set;}
#AuraEnabled public String ZipCode{get;set;}
#AuraEnabled public String ContactPhone{get;set;}
#AuraEnabled public String ContactPhoneExtension{get;set;}
#AuraEnabled public String Servicer{get;set;}
#AuraEnabled public String CaseId{get;set;}
}
#AuraEnabled
public static String createFurnitureServices(String scheduleServiceJSON, String independentServicerJSON, Boolean isIndependentServicer){
ScheduleServiceWrapper objScheduleServiceWrapper = (ScheduleServiceWrapper) System.JSON.deserialize(scheduleServiceJSON, ScheduleServiceWrapper.class);
IndependentServicerWrapper objIndependentServicerWrapper = !isIndependentServicer ? null : (IndependentServicerWrapper) System.JSON.deserialize(independentServicerJSON, IndependentServicerWrapper.class);
JSONGenerator jsonGenerator = JSON.createGenerator(false);
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField('ClaimId__c', objScheduleServiceWrapper.ClaimId);
jsonGenerator.writeObjectField('Comments__c','[' + System.today().format() + '][' + nfm_Utils.userAlias + '] ' + objScheduleServiceWrapper.Comments);
String inspectDateYear = objScheduleServiceWrapper.ServiceDate.substring(0,4);
String inspectDateMonth = objScheduleServiceWrapper.ServiceDate.substring(5,7);
String inspectDateDay = objScheduleServiceWrapper.ServiceDate.substring(8,10);
jsonGenerator.writeObjectField('InspectDate__c', inspectDateMonth + '/' + inspectDateDay + '/'+ inspectDateYear);
if (!isIndependentServicer) {
//specific fields
jsonGenerator.writeObjectField('InspectName__c', objScheduleServiceWrapper.CustomerName);
jsonGenerator.writeObjectField('ServiceCode__c', objScheduleServiceWrapper.ServiceCode);
jsonGenerator.writeObjectField('RouteCode__c', objScheduleServiceWrapper.RouteCode);
jsonGenerator.writeObjectField('AppointmentUnits__c', String.valueOf(objScheduleServiceWrapper.AppointmentUnits));
//common fields
jsonGenerator.writeObjectField('InspectAddress1__c', objScheduleServiceWrapper.Address);
jsonGenerator.writeObjectField('InspectAddress2__c', '');
jsonGenerator.writeObjectField('InspectCity__c', objScheduleServiceWrapper.City);
jsonGenerator.writeObjectField('InspectState__c', objScheduleServiceWrapper.State);
jsonGenerator.writeObjectField('InspectZip__c', objScheduleServiceWrapper.ZipCode);
jsonGenerator.writeObjectField('ContactPhone__c', objScheduleServiceWrapper.ContactPhone);
jsonGenerator.writeObjectField('ContactPhoneExtension__c', nfm_Utils.IfNull(objScheduleServiceWrapper.ContactPhoneExtension,''));
}
if (isIndependentServicer) {
//specific fields
String servicerCode = Test.isRunningTest() ? '12345' : objIndependentServicerWrapper.Servicer;
jsonGenerator.writeObjectField('Servicer__c', servicerCode); //servicer 5-digit code
//common fields
jsonGenerator.writeObjectField('InspectAddress1__c', objIndependentServicerWrapper.Address);
jsonGenerator.writeObjectField('InspectAddress2__c', '');
jsonGenerator.writeObjectField();
jsonGenerator.writeObjectField('InspectCity__c', objIndependentServicerWrapper.City);
jsonGenerator.writeObjectField('InspectState__c', objIndependentServicerWrapper.State);
jsonGenerator.writeObjectField('InspectZip__c', objIndependentServicerWrapper.ZipCode);
jsonGenerator.writeObjectField('InspectName__c', objIndependentServicerWrapper.CustomerName);
jsonGenerator.writeObjectField('ContactPhone__c', objIndependentServicerWrapper.ContactPhone);
jsonGenerator.writeObjectField('ContactPhoneExtension__c', nfm_Utils.IfNull(objIndependentServicerWrapper.ContactPhoneExtension,''));
}
String jsonBody = '\'' + jsonGenerator.getAsString() + '\'';
String jsonResult = nfm_FurnitureServicesCallout.upsertFurnitureServicesCallout(jsonBody);
String result = '';
if(!Test.isRunningTest()){
Map<String, Object> jsonResultMap = (Map<String, Object>) JSON.deserializeUntyped(jsonResult);
String[] furnitureServicesFieldsList = new List<String>{ 'ExternalId','Id','AppointmentUnits__c','InspectAddress1__c','InspectName__c','InspectDate__c' };
Map<String,String> furnitureServicesFieldValueMap = new Map<String,String>();
furnitureServicesFieldValueMap.put('ClaimId__c', String.valueOf(jsonResultMap.get('ClaimId')));
FurnitureServices__x objFurnitureServices = nfm_ExternalFurnitureServicesRequest.getFurnitureServices(furnitureServicesFieldsList, furnitureServicesFieldValueMap, 'Id', 'ASC')[0];
UserActivityController.createRecord(objScheduleServiceWrapper.ButtonLabel, 'Claim', objScheduleServiceWrapper.ClaimId);
if(isIndependentServicer){
updateServiceAssignedDate(objIndependentServicerWrapper.CaseId, Date.newInstance(Integer.valueOf(inspectDateYear), Integer.valueOf(inspectDateMonth), Integer.valueOf(inspectDateDay)));
}
return objFurnitureServices.Id;
} else {
result = 'ok';
}
return result;
}
public static FurnitureServices__x getPreviousFurnitureService(String claimId){
Map<String,String> furnitureServicesFieldValueMap = new Map<String,String>();
furnitureServicesFieldValueMap.put('ClaimId__c', claimId);
return nfm_ExternalFurnitureServicesRequest.getFurnitureServices(SObjectUtils.getAllFieldsAPINames('FurnitureServices__x'), furnitureServicesFieldValueMap, 'Id', 'ASC')[0];
}
#AuraEnabled
public static List<FurnitureServiceRoutes__x> getFurnitureServiceRoutes(String startDate,String numberOfDays,String zipCode){
String[] furnitureServiceRoutesFieldsList = new List<String>{
'Id', 'NumberOfDays__c', 'RouteCode__c', 'RouteDescription__c', 'ServiceCode__c', 'StartDate__c', 'ZipCode__c'
};
Map<String,String> furnitureServiceRoutesFieldValueMap = new Map<String,String>();
furnitureServiceRoutesFieldValueMap.put('NumberOfDays__c',numberOfDays);
furnitureServiceRoutesFieldValueMap.put('StartDate__c',startDate);
furnitureServiceRoutesFieldValueMap.put('ZipCode__c',zipCode);
return nfm_ExternalFurnitureServiceRoutesReq.getFurnitureServiceRoutes(furnitureServiceRoutesFieldsList, furnitureServiceRoutesFieldValueMap, 'RouteCode__c', 'ASC');
}
#AuraEnabled
public static List<FurnitureServiceAppointments__x> getFurnitureServiceAppointments(String startDate,String numberOfDays,String zipCode, String routeCode){
String[] furnitureServiceAppointmentsFieldsList = new List<String>{
'Id', 'AppointmentUnits__c', 'ServiceDate__c', 'StartDate__c', 'ZipCode__c','RouteCode__c'
};
Map<String,String> furnitureServiceAppointmentsFieldValueMap = new Map<String,String>();
furnitureServiceAppointmentsFieldValueMap.put('NumberOfDays__c',numberOfDays);
furnitureServiceAppointmentsFieldValueMap.put('StartDate__c',startDate);
furnitureServiceAppointmentsFieldValueMap.put('ZipCode__c',zipCode);
furnitureServiceAppointmentsFieldValueMap.put('RouteCode__c',routeCode);
return nfm_ExternalFurnitureServiceAppRequest.getFurnitureServiceAppointments(furnitureServiceAppointmentsFieldsList, furnitureServiceAppointmentsFieldValueMap, 'RouteCode__c', 'ASC');
}
#AuraEnabled
public static Boolean hasAccessToIndependentServicerPermset(){
Id userId = UserInfo.getUserId();
String permsetApiName = 'Custom_Contact_Center_Support_Team';
return nfm_Utils.isPermsetAssignedToUser(userId, permsetApiName);
}
**#AuraEnabled
public static Case retrieveCaseObject(Id caseId){
return [
SELECT
Id, Shipping_Address_1__c, Shipping_Address_2__c, Shipping_City__c, Shipping_State__c,
Shipping_Postal_Code__c, Call_Back_Contact__c, Requested_Call_Back_Number__c,
Requested_Call_Back_Number_Ext__c ,Independent_Servicer__r.Id, Independent_Servicer__r.Servicer_Id__c, Independent_Servicer__r.Name
FROM Case
WHERE Id = :caseId
LIMIT 1
];
}**
public static void updateServiceAssignedDate(Id caseId, date newDate){
Case objCase = [SELECT Id, Service_Assigned_Date__c FROM Case WHERE Id = :caseId LIMIT 1];
objCase.Service_Assigned_Date__c = newDate;
update objCase;
}
}
method to fetch case record
fetchCaseData : function(component, event, helper) {
var caseRecord = component.get('v.caseRecord');
var newCaseId = caseRecord.recordId;
var retrieveCaseAction = component.get('c.retrieveCaseObject');
var actionParams = {'caseId':newCaseId};
retrieveCaseAction.setParams(actionParams);
retrieveCaseAction.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var result = response.getReturnValue();
//console.log('RESULT: ' + JSON.stringify(result));
var currentCaseRecord = component.get('v.caseRecord');
result.label = currentCaseRecord.label;
result.recordId = currentCaseRecord.recordId;
component.set('v.caseRecord', result);
component.set('v.isLoading', false);
} else {
console.log(response.getError());
}
});
$A.enqueueAction(retrieveCaseAction);
},
when clicked on reschedule spinner should not spin continuously
enter image description here
enter image description here
should be able to reschedule
Needs more info (but too long for comment).
Which JS function is called when that button (quick action?) is clicked? It doesn't look like you followed the customary {!c.doInit} naming convention.
You pasted a lot of code, servicer_id__c appears in 3 places. Next time try to cut the useless pieces until you're left with Minimal Reproducible Example.
Check Apex Developer Console for errors / problems, maybe one of the functions genuinely returns null / throws error:
lack of permissions to run this apex class
really bad data (Case without some lookup populated?)
maybe you carefully created a wrapper class to hold stuff returned from apex - but you forgot to mark every field as public and #AuraEnabled
I suspect the bad code is around places like caseRecord.Independent_Servicer__r.Servicer_Id__c in isIndependentServicerCheckedChanged. You don't check if the middle part is null. A ternary operator or optional chaining could make it easier to spot.
Enable Setup -> Debug mode (if not done already) and next time just click that error logged in JavaScript console. You'll be taken to the line in source code where it happened. It won't look exactly like your source code (SF transpiles a bit and merges multiple files into 1) but it should be close enough for you to recognise and fix the mistake. Or at least put some breakpoints / watches.

Facing problem to cover test class 75% coverage

This is my batch class. I am facing a problem in the test class.
So please give me some solution on it. How to write this condition into class or how to write a test class for this.
I have this batch class created:
public class processBatch implements database.Batchable<object>, Database.AllowsCallouts, Scheduable{
public string AccountURL;
public String ProcessURL;
Public String Key;
private class JsonUpsertResult
{
List<Database.Error> Error {get;set;}
string SFDCId{get;set;}
String visibleID{get;set;}
Boolean is Created {get;set;}
Boolean isSuccess {get;set;}
}
public ProcessBatch(){
SAP_Details__c SAP = SAP_Details__c. getOrgDefaults();
AccountURL =SAP.Account_API_URL__c;
ProcessURL =SAP.process_API_URL__c;
Key =SAP.API_Key__c;
system.debug('API:' + ProcessURL + '-' + Key);
}
public Iterable<Object> start (Database.BatchableContext BC) {
List<Object> results =new List <Object>();
http http = new http();
httpRequest request =new HttpRequest();
system.debug('API:' '+ ProcessURL+' -' + Key);
request.setEndpoint(ProcessURL);
request.setMethod('POST');
request.setHeader('Authorization', Key);
request.setHeader('Accept', '*/*');
request.setHeader ('content-type', 'application/json');
}';
request.setBody(filters);
HttpResponse response =http.send(request);
if(responce.getStatusCode() == 200){
SAPProcessJsonApex2 gt = {SAPProcessJSON2Apex2) JSON.deserialize(response.getBody(), SAPProcessJSON2Apex.class);
List<SAPProcessJson2Apex.Result> res =gt.result;
system.debug('Size of Result: ' + res.size());
results = res;
}
return results;
}
public void execute (Database. BatchableContext BC, List<object> scope){
List<JSON2Apex.Results) accountResults = new List<JSON2Apex.Results>;
List<Process__c> ProcessToUpsert = new List<Process__c> ();
List<Process_Agent__c> CollectivesToupsert = new List<Process_Agent__c> ();
List<Department__c> departmentToupdate = new List<Department__c> ();
List<JSON2Apex.Results) revisedAccRes = new List JSON2Apex.Results> ();
List<SAPprocessJSON2Apex2.Results res = (List<SAPprocessJSO2Apex2.Results>) scope();
List<SAPprocessJSON2Apex2.Results revisedRes = nen List<SAPprocessJSONApex2.Results> ();
for (SAPprocessJSON2Apex2.Results r: res) {
SAPprocessJSON2Apex2.Document doc = r. document: List<SAPprocessJSON2 Apex2. Companies) comp = doc.companies;
List<SAPprocessJSON2Apex2.Companies> comp = doc.companies;
List<String> processTypes = doc.processTypes;
Lisk<String> categories = doc.categories;
Process__c pr = new Process__c ();
pr.Visibleprocess_No__c = doc.processId;
pr.Visible_method__c = 'SAP';
pr.process_Description__c = doc.description;
pr.Amount__c = doc.Amount;
pr.Construction_Type__c = doc.constructionType;
if(doc.phase == 'First planning'){
pr.Division=='First planning!';
} else if(doc.phase == 'Quotation'){
pr.Division == 'Main Step Quotation;
} else if(doc.phase = 'Contract Get') {
pr. Division== ' Main Step Agricultural';
}
pr.process_Full Name = doc.title;
pr.Name = doc.title.left (80);
if (categories.size() > 0){
if(categories [0] == 'Factory' || categories [0] = 'Storage' ){
pr.Sector__c = 'Industrial';
}else if(categories [0] == 'Packaging/Storage') {
pr. Type_of_Sector_c = 'Warehouse';
}else if(categories[0] == 'Shops and Retail' || categories [0]=='Any Showrooms') {
pr.Sector__c = 'Commercial';
}
if(pr.Sector__c != null && doc.Amount >= 50000){
ProcessToUpsert.ada (p);
revisedRes.ada (r);
} } }
public void finish (Database.BatchableContext BC) {
}
public void execute (SchedulableContext sc) {
database.executeBatch (new ProcessBatch (), 30);
}
}
&& d.Amount__c>= 50000 Whenever I write this condition in my class then my test class covers only 35%, and when I remove this condition it covers 80%. This condition is correct according to the requirement.
Test Class
#isIest (SeeAllData = true)
public class ProcessBatchTest {
#isTest public static void processBatchTest () {
Test.setMock (HttpCalloutMock.class, new HttpMock());
ProcessBatch pb = new ProcessBatch();
Test.startTest();
database.executeBatch (pb,30);
Test.stopTest();
You control the HttpMock class that pretends it returns results from SAP callout in the test. Nothing stops you from going there and making it return 2 records (1 with amount below 50K, 1 with amount above), or multiple statuses or whatever else you need.

Call Apex Method from the Custom Button

I created a Apex Class like
Public class test_Controller
{
Public test_Controller() { }
Public void send(set<id> oppIds)
{
List<Oppurtunity> OppLst =[Select Name from Opportunity where id IN: oppIds];
Private static string integration_key = 'abcd';
Private static string account_id = 'efgh';
Public string signer_email { get; set; }
Public string signer_name { get; set; }
Public string email_message { get; set; }
Public string output { get; set; }
Public string envelope_id { get; set; }
Public string error_code { get; set; }
Public string error_message { get; set; }
Private static string ds_server = 'callout:DocuSign_Legacy_Demo/api/3.0/dsapi.asmx';
Private static string trace_value = 'SFDC_004_SOAP_email_send'; // Used for tracing API calls
Private static string trace_key = 'X-ray';
Private DocuSignTK.APIServiceSoap api_sender = new DocuSignTK.APIServiceSoap();
configure_sender();
do_send(OppLst);
}
Private void configure_sender()
{
api_sender.endpoint_x = ds_server;
api_sender.inputHttpHeaders_x = new Map<String, String>();
String auth = '<DocuSignCredentials><Username>{!$Credential.Username}</Username>'
+ '<Password>{!$Credential.Password}</Password>'
+ '<IntegratorKey>' + integration_key + '</IntegratorKey></DocuSignCredentials>';
api_sender.inputHttpHeaders_x.put('X-DocuSign-Authentication', auth);
}
Private void do_send(List<Oppurtunity> OppurLst)
{
if (integration_key == 'xxx-xxxx-xxxx' ||
account_id == 'xxxx-xxxx-xxxx')
{
error_message = 'Please configure the Apex class DS_Recipe_Send_Env_Email_Controller with your integration key and account id.';
error_code = 'CONFIGURATION_PROBLEM';
return;
}
String file_contents = '<html><h1>Quote Document</h1>' + get_lorem(OppurLst)
+ '<p> </p>'
+ '<p>Signature: <span style="color:white;">signer1sig</span></p>'
+ '<p>Date: <span style="color:white;">signer1date</span></p></html>';
DocuSignTK.Document document = new DocuSignTK.Document();
document.ID = 1;
document.Name = 'Quote Document';
document.FileExtension = 'html';
document.pdfBytes = EncodingUtil.base64Encode(Blob.valueOf(file_contents));
DocuSignTK.Recipient recipient = new DocuSignTK.Recipient();
recipient.Email = '';
recipient.UserName = '';
recipient.ID = 1;
recipient.Type_x = 'Signer';
recipient.RoutingOrder = 1;
DocuSignTK.Tab signHereTab = new DocuSignTK.Tab();
signHereTab.Type_x = 'SignHere';
signHereTab.AnchorTabItem = new DocuSignTK.AnchorTab();
signHereTab.AnchorTabItem.AnchorTabString = 'signer1sig'; // Anchored for doc 1
signHereTab.AnchorTabItem.XOffset = 8;
signHereTab.RecipientID = 1;
signHereTab.Name = 'Please sign here';
signHereTab.ScaleValue = 1;
signHereTab.TabLabel = 'signer1sig';
DocuSignTK.Tab dateSignedTab = new DocuSignTK.Tab();
dateSignedTab.Type_x = 'DateSigned';
dateSignedTab.AnchorTabItem = new DocuSignTK.AnchorTab();
dateSignedTab.AnchorTabItem.AnchorTabString = 'signer1date'; // Anchored for doc 1
dateSignedTab.AnchorTabItem.YOffset = -6;
dateSignedTab.RecipientID = 1;
dateSignedTab.Name = 'Date Signed';
dateSignedTab.TabLabel = 'date_signed';
DocuSignTK.Envelope envelope = new DocuSignTK.Envelope();
envelope.Subject = 'Please sign the Quote Document';
envelope.AccountId = account_id;
envelope.Tabs = new DocuSignTK.ArrayOfTab();
envelope.Tabs.Tab = new DocuSignTK.Tab[2];
envelope.Tabs.Tab.add(signHereTab);
envelope.Tabs.Tab.add(dateSignedTab);
envelope.Recipients = new DocuSignTK.ArrayOfRecipient();
envelope.Recipients.Recipient = new DocuSignTK.Recipient[1];
envelope.Recipients.Recipient.add(recipient);
envelope.Documents = new DocuSignTK.ArrayOfDocument();
envelope.Documents.Document = new DocuSignTK.Document[1];
envelope.Documents.Document.add(document);
if (String.isNotBlank(email_message))
{
envelope.EmailBlurb = email_message;
}
try
{
DocuSignTK.EnvelopeStatus result = api_sender.CreateAndSendEnvelope(envelope);
envelope_id = result.EnvelopeID;
System.debug('Returned successfully, envelope_id = ' + envelope_id);
}
catch (CalloutException e)
{
System.debug('Exception - ' + e);
error_code = 'Problem: ' + e;
error_message = error_code;
}
}
Private Boolean no_error()
{
return (String.isEmpty(error_code));
}
Private static String get_lorem(List<Oppurtunity> OLst)
{
String lorem = 'Hello World';
return lorem;
}
}
And I am trying to call the send Method from the Apex from the Custom Button like
{!REQUIRESCRIPT("/soap/ajax/41.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/41.0/apex.js")}
sforce.apex.execute("test_Controller","send",{oppIds:"{!Opportunity.Id}"});
When I try to execute the button I get the following error message:
A Problem with the OnClick JavaScript for this button or link was
encountered: {faultcode:''soapenv:Client', faultstring:'No operation
available for request
{http://soap.sforce.com/schemas/package/test_Controller}send, please
check the WSDL for the service.'}'
I am new to Salesforce and Apex scripting. Any help is greatly appreciated.
Your method is expecting a list of Ids.
Public void send(set<id> oppIds)
So I am guessing that maybe you need to send it as an array?
sforce.apex.execute("test_Controller","send",{oppIds:["{!Opportunity.Id}"]});
You need to expose this method as a webservice and it needs to be static
webservice static void send(List<Id> oppIds) {
}
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_and_ajax.htm

System.TypeException: Invalid integer salesforce test class error in controller

i have a visual force page which is used as a view to send a custom sms to the leads generated in salesforce.The year field is a number field on salesforce. Posting the controller and test class error. Also mentioning the error line.
Controller :-
//Class to send Message to Lead or Account
public class nmSendSMS
{
//Name of Lead or Account
public string strName{get;set;}
public Lead objLead {get;set;}
public String defaultNumbersToBeAdded;
public String leadYear{get;set;}
//Mobile number of lead of account
public string strMobile{get;set;}
public String messageToBeSent{get;set;}
public List<SelectOption> getYear{get;set;}
public string strSMSBody{get;set;}
//To disable fields if data is not available
String session,statusOfLead,stringOfMobileNumbers;
public nmSendSMS()
{
objLead = new Lead();
leadYear ='';
defaultNumbersToBeAdded = '9820834921,9920726538';
messageToBeSent = '';
stringOfMobileNumbers= '';
}
//Method to send SMS
public PageReference SendSMS()
{
if(leadYear!='' || messageToBeSent!='')
{
session = objLead.nm_Session__c;
integer lengthOfCommaSeperatedNumbers;
String finalString ='';
statusOfLead = objLead.Status;
list<lead> leadNumbersList = [select MobilePhone from Lead where Status=:statusOfLead and nm_Session__c=:session and nm_Year__c=:integer.valueOf(leadYear)];
for(Lead obj :leadNumbersList)
{
stringOfMobileNumbers = obj.MobilePhone+','+stringOfMobileNumbers;
}
System.debug('stringOfMobileNumbers -->'+stringOfMobileNumbers);
lengthOfCommaSeperatedNumbers = stringOfMobileNumbers.length();
finalString = stringOfMobileNumbers.substring(0,lengthOfCommaSeperatedNumbers-1);
finalString = finalString + defaultNumbersToBeAdded;
System.debug('Final String--->'+finalString+'Message To Be Sent-->'+messageToBeSent);
String response = SMSSenderWebService.sendSMSForNotContactedLead(finalString,messageToBeSent);
System.debug('Response-->'+response);
}
else
{
ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Warning,'Please Mention all the fields For Lead Search'));
return null;
}
return null;
}
public List<SelectOption> getYear()
{
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('2016','2016'));
options.add(new SelectOption('2017','2017'));
options.add(new SelectOption('2018','2018'));
options.add(new SelectOption('2019','2019'));
return options;
}
}
Test Class:-
#isTest
public class nmSendSMSTracker
{
public static Lead obj;
public static nm_Centers__c objLearningCenter;
public static nm_Program__c program;
public static nm_EligiblityCriteria__c eligibility ;
static testMethod void tesMethod()
{
LoadData();
PageReference pg = new PageReference('/apex/nmSendSMS');
Test.setCurrentPage(pg);
Test.StartTest();
nmSendSMS smsSend = new nmSendSMS();
smsSend.getYear();
smsSend.objLead = obj;
smsSend.messageToBeSent ='Hello Vikas';
smsSend.SendSMS();
Test.StopTest();
}
static void LoadData()
{
nm_EscalationMatrix__c objCustomSeetings3 = new nm_EscalationMatrix__c();
objCustomSeetings3.name='0-1 Week';
objCustomSeetings3.nm_LCEscalationTime__c='22:45';
objCustomSeetings3.nm_RemidertoIC__c='22:45';
objCustomSeetings3.nm_HOEscalationTime__c='20:56';
objCustomSeetings3.nm_RemidertoHO__c='22:45';
insert objCustomSeetings3;
nm_EscalationMatrix__c objCustomSeetings = new nm_EscalationMatrix__c();
objCustomSeetings.name='2-4 Months';
objCustomSeetings.nm_LCEscalationTime__c='20:45';
objCustomSeetings.nm_RemidertoIC__c='21:45';
objCustomSeetings.nm_HOEscalationTime__c='20:56';
objCustomSeetings.nm_RemidertoHO__c='21:45';
insert objCustomSeetings;
nm_EscalationMatrix__c objCustomSeetings2 = new nm_EscalationMatrix__c();
objCustomSeetings2.name='3-6 Week';
objCustomSeetings2.nm_LCEscalationTime__c='20:34';
objCustomSeetings2.nm_RemidertoIC__c='21:45';
objCustomSeetings2.nm_HOEscalationTime__c='20:56';
objCustomSeetings2.nm_RemidertoHO__c='21:45';
insert objCustomSeetings2;
nm_Holidays__c objHoliday = new nm_Holidays__c();
objHoliday.Name='Holi';
objHoliday.nm_Date__c=system.today();
insert objHoliday;
// profile objprofile =[SELECT Id FROM Profile WHERE Name='System Administrator'];
user usr = [Select id from user limit 1];
SystemConfiguration__c objSystemConfiguration=new SystemConfiguration__c();
objSystemConfiguration.name='test';
objSystemConfiguration.nm_BusinessHoursStartTime__c='012213';
objSystemConfiguration.nm_BusinessHoursEndTime__c='0234533';
insert objSystemConfiguration;
Recordtype rt=[select id from Recordtype where sobjectType='nm_Centers__c' AND name ='Learning Center'];
objLearningCenter = new nm_Centers__c();
objLearningCenter.RecordTypeID =rt.id;
objLearningCenter.nm_CenterCode__c ='002';
objLearningCenter.nm_CenterCity__c='Delhi';
objLearningCenter.nm_City__c='Delhi';
objLearningCenter.nm_StateProvince__c='Delhi';
objLearningCenter.nm_Street__c='Laxmi Ngar';
objLearningCenter.nm_PostalCode__c='110091';
insert objLearningCenter;
program = new nm_Program__c();
program.nmIsActive__c = true;
program.nm_ProgramCode__c = 'test';
program.nm_ProgramDuration__c= 2.0;
program.nm_ProgramName__c = 'Post grad diploma finance';
program.nm_ProgramValidity__c = 4;
program.nm_TotalSemesters__c = 4;
program.nm_Type__c = 'Post Graduate Diploma Program';
insert program;
eligibility = new nm_EligiblityCriteria__c();
eligibility.Name = 'Bachelors degree';
eligibility.nm_EligiblityCriteria__c = 'bjhwbghbjgw';
eligibility.Experience_Required_In_Year__c= 2;
eligibility.Graduation_Percentage__c = 6;
eligibility.Graduation_Required__c = true;
insert eligibility;
obj = new Lead();
obj.Email='amit.kumar#saasfocus.com';
obj.MobilePhone='8377985721';
obj.FirstName='sandy';
obj.LastName='babar';
obj.nm_BloodGroup__c='B+';
obj.nm_Gender__c='male';
obj.nm_FathersName__c='subhash';
obj.nm_MothersName__c='kalpana';
obj.nm_StateProvince_P__c='maharashtra';
obj.nm_Nationality__c='Indian';
obj.nm_Street_P__c='xyz';
obj.nm_LocalityName__c='mohitep';
obj.nm_SelfLearningMaterial__c='Send to my shipping address';
obj.Status='Cold';
obj.nm_Session__c = 'January';
obj.nm_NameofBoard__c='CBSE';
obj.nm_EligiblityCriteria__c = eligibility.id;
obj.nm_Program__c = program.id;
obj.nm_InformationCenter__c =objLearningCenter.id;
obj.nm_10thPercentage__c=77.00;
obj.nm_NameofBoard__c='ICSC';
obj.nm_YearofCompletion__c='2000';
obj.nm_NameofSchool__c='nutan';
obj.nm_Class12OrDiploma__c='HSC';
obj.nm_NameofBoard12__c='LCSC';
obj.nm_YearofCompletion12__c='2002';
obj.nm_NameofSchool12__c='dfg';
obj.nm_Stream__c='adw';
obj.nm_BachelorsDegreeName__c='gfc';
obj.nm_Specialization__c='gf';
obj.nm_NameofUniversity__c='G K university';
obj.nm_BachelorsDegreePercentage__c=55.00;
obj.nm_GraduationDegreeMode__c='fgc';
obj.nm_YearofCollegeCompletion__c='2006';
obj.LeadSource='Web';
obj.OwnerId=usr.id;
insert obj;
}
}
Error Message:
System.TypeException: Invalid integer:
Class.nmSendSMS.SendSMS: line 37, column 1
Class.nmSendSMSTracker.tesMethod: line 19, column 1
List<Lead> leadNumbersList = [select MobilePhone from Lead where nm_Year__c=:leadYear];
Works for me and I get the correct Lead(s) in the list

Dapper table valued parameter as a property?

I have a stored proc like this:
CREATE PROCEDURE [dbo].[Organisation_Insert]
#OrganisationXId uniqueidentifier
,#Enabled bit
,#Timezone nvarchar(50)
,#MinimumValue float
,#Rules ReminderRuleType READONLY ...
ReminderRuleType is a user defined type.
In my app I have this:
class OrganisationDTO
{
private readonly IOrganisationDocument _orgDoc;
public long OrganisationId { get { return _orgDoc.OrganisationId; } }
public Guid OrganisationXId { get { return _orgDoc.OrganisationXId; } }
public string TimeZone { get { return _orgDoc.TimeZone; } }
public bool Enabled { get { return _orgDoc.Enabled; } }
public decimal MinimumValue { get { return _orgDoc.MinimumValue; } }
public RuleTableValuedParameters Rules { get; private set; }
public OrganisationDTO(IOrganisationDocument orgDoc)
{
_orgDoc = orgDoc;
Rules = new RuleTableValuedParameters("#Rules", _orgDoc.Rules);
}
}
RuleTableValuedParameters implements SqlMapper.IDynamicParameters which has an AddParameters method.
When I execute the query, the #Rules parameter is never passed (using SQLProfiler). I can also see that AddParameters is never called.
Is this possible to do?
Thanks
Here's a simplified example based on your code that shows it working just fine; AddParameters is invoked correctly, and the values are conveyed to the stored procedure. As a side note: if you are using DataTable for your TVPs, the library supports that directly with no additional code needed.
public void SO29596645_TvpProperty()
{
try { connection.Execute("CREATE TYPE SO29596645_ReminderRuleType AS TABLE (id int NOT NULL)"); }
catch { }
connection.Execute(#"create proc #SO29596645_Proc (#Id int, #Rules SO29596645_ReminderRuleType READONLY)
as begin select #Id + ISNULL((select sum(id) from #Rules), 0); end");
var obj = new SO29596645_OrganisationDTO();
int val = connection.Query<int>("#SO29596645_Proc", obj.Rules, commandType: CommandType.StoredProcedure).Single();
// 4 + 9 + 7 = 20
val.IsEqualTo(20);
}
class SO29596645_RuleTableValuedParameters : Dapper.SqlMapper.IDynamicParameters {
private string parameterName;
public SO29596645_RuleTableValuedParameters(string parameterName)
{
this.parameterName = parameterName;
}
public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
{
Console.WriteLine("> AddParameters");
SqlCommand lazy = (SqlCommand)command;
lazy.Parameters.AddWithValue("Id", 7);
DataTable table = new DataTable {
Columns = {{"Id", typeof(int)}},
Rows = {{4}, {9}}
};
lazy.Parameters.AddWithValue("Rules", table);
Console.WriteLine("< AddParameters");
}
}
class SO29596645_OrganisationDTO
{
public SO29596645_RuleTableValuedParameters Rules { get; private set; }
public SO29596645_OrganisationDTO()
{
Rules = new SO29596645_RuleTableValuedParameters("#Rules");
}
}
Here's the full working DynamicParameter that I created:
public class OrganisationDynamicParameter : SqlMapper.IDynamicParameters
{
private readonly IOrganisation _orgModel;
public OrganisationDynamicParameter(IOrganisation orgModel)
{
_orgModel = orgModel;
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
SqlParameter p;
var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure;
p = sqlCommand.Parameters.Add("#OrganisationXId", SqlDbType.UniqueIdentifier);
p.Value = _orgModel.OrganisationXId;
p = sqlCommand.Parameters.Add("#Enabled", SqlDbType.Bit);
p.Value = _orgModel.Enabled;
p = sqlCommand.Parameters.Add("#Timezone", SqlDbType.NVarChar, 50);
p.Value = _orgModel.TimeZone;
p = sqlCommand.Parameters.Add("#MinimumValue", SqlDbType.Float);
p.Value = _orgModel.MinimumValue;
List<SqlDataRecord> ruleList = _orgModel.Rules.Select(MapRuleData).ToList();
if (ruleList.Count > 0)
{
p = sqlCommand.Parameters.Add("#Rules", SqlDbType.Structured);
p.Direction = ParameterDirection.Input;
p.TypeName = "ReminderRuleType";
p.Value = ruleList;
}
}
protected SqlDataRecord MapRuleData(IReminderRule value)
{
var rec = new SqlDataRecord(new[]
{
new SqlMetaData("RuleId", SqlDbType.BigInt),
new SqlMetaData("OrganisationId", SqlDbType.BigInt),
new SqlMetaData("Name", SqlDbType.NVarChar, 200),
new SqlMetaData("OffsetDays", SqlDbType.Int),
new SqlMetaData("SubjectTemplate", SqlDbType.NVarChar, -1),
new SqlMetaData("BodyTemplate", SqlDbType.NVarChar, -1)
});
rec.SetInt64(0, value.RuleId);
rec.SetInt64(1, value.OrganisationId);
rec.SetString(2, value.Name);
rec.SetInt32(3, value.OffsetDays);
rec.SetString(4, value.SubjectTemplate);
rec.SetString(5, value.BodyTemplate);
return rec;
}
}
I use this thusly:
public IOrganisation CreateOrganisation(IOrganisation organisation)
{
var dtoOrg = new OrganisationDynamicParameter(organisation);
return ExecuteSPReturningOrganisation("Organisation_Insert", dtoOrg);
}
protected IOrganisation ExecuteSPReturningOrganisation(string query, object parameters)
{
using (IDbConnection con = ConnectionFactory.CreateOpenConnection())
{
using (
SqlMapper.GridReader multi = con.QueryMultiple(query, parameters,
commandType: CommandType.StoredProcedure))
{
OrganisationModel org = multi.Read<OrganisationModel>().SingleOrDefault();
if (org != null)
{
org.Rules = multi.Read<ReminderRuleModel>().ToArray();
}
return org;
}
}
}
Cheers

Resources