I am working on a test class for a visualforce page/controller that is failing with the error message "System.QueryException: List has no rows for assignment to SObject".
The Controller class code is below.
public class OfferConvertController {
public Boolean blnDisplayError {get;set;}
public OfferConvertController(ApexPages.StandardController Controller) {
//Overloaded Constructor using a Controller as the argument
}
public PageReference OfferToConvert() {
PageReference returnPage = null;
try
{
ID offerId = ApexPages.CurrentPage().getparameters().get('id');
//Get the data from the offer object
Offer__c offerToConvert = [Select Contact__c, Contact__r.AccountId, Contact__r.OwnerId, Initial_Contribution__c, Name, Product_Name__c, Client_Name__c
From Offer__c Where id=:OfferId];
List<Opportunity> offerIdsInOpp = [Select Offer__c From Opportunity Where Offer__c=:offerId];
if(offerIdsInOpp.isEmpty())
{
if (String.isNotBlank(offerToConvert.Client_Name__c) && (offerToConvert.Client_Name__c.split('\\s+').size() > 1))
{
//Store the data in the Opportunity object fields
Opportunity o = new Opportunity();
o.ContactId = offerToConvert.Contact__c;
o.AccountId = offerToConvert.Contact__r.AccountId;
o.Amount = offerToConvert.Initial_Contribution__c;
o.Name = offerToConvert.Name;
o.Opportunity_Product_Family__c = offerToConvert.Product_Name__c;
o.Policy_Owner_Full_Name__c = offerToConvert.Client_Name__c;
o.Offer__c = offerToConvert.Id;
o.RecordTypeId = [SELECT Id from RecordType WHERE SobjectType = 'Opportunity' and DeveloperName = 'Offer' LIMIT 1].Id;
o.Source__c = 'New Offer';
o.StageName = 'Offer Application';
o.CloseDate = Date.today().addDays(30); //need to change later
//Insert new opportunity into the database
Database.insert(o);
//Change returnPage to the new opportunity
returnPage = new ApexPages.StandardController(o).view();
returnPage.setRedirect(true);
}
else
{
blnDisplayError = true;
ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.Error, 'Client Name Required');
ApexPages.addMessage(myMsg);
}
}
else
{
blnDisplayError = true;
ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.Error, 'Already an Opportunity for this Offer');
ApexPages.addMessage(myMsg);
}
}
catch(Exception e)
{
blnDisplayError= true;
ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.Error,e.getMessage());
ApexPages.addMessage(myMsg);
}
return returnPage;
}
}
For the offer id passed from the visualforce page, the code is trying to get the list of opportunities associated with the offer. When there are no opportunities, it is trying to create a new opportunity. In our Salesforce org, we have a before-update flow that assigns the Pricebook2Id of the Opportunity based on the record type of the Opportunity. For the record type of 'Offer' for Opportunity, the pricebook2Id should be the id corresponding to a custom pricebook called 'Investment'. However, this flow is failing with an error message since it cannot access the pricebook. I tried to populate the Pricebook2Id manually in the code with the below statement, but the SOQL is returning 0 rows and hence failing.
o.Pricebook2Id = [SELECT Id from Pricebook2 WHERE Name = 'Investment' and IsActive = true LIMIT 1].Id;
I am not sure why the above statement is returning 0 rows in the method OfferToConvert().
Any thoughts on what am I missing?
upsert new Pricebook2(Name = 'Investment') Name;
ought to work. If that does work, then I can write an answer explaining why.