You need to sign in to do that
Don't have an account?
Jean Grey 10
Invalid Id error
Please help, I am getting the following errors when I run the unit test:
FATAL_ERROR System.StringException: Invalid id:
and
FATAL_ERROR External entry point
referencing the submit method in my class.
Class:
public class ContractExtension {
//private final Hearing_Aids__c ha;
public final Contact con;
public List<Hearing_Aids__c> haList {get; set;}
public List<Hearing_Aids__c> haSelectedList {get; set;}
public List<WrapperClass> hearingAidWrappers {get; set;}
public Boolean hearingAidSelection {get; set;}
public Boolean productSelection {get; set;}
public List<SelectOption> classOptions {get; set;}
public String classSelection {get; set;}
public ContractExtension(ApexPages.StandardController stdController) {
if (!Test.isRunningTest()) {
stdController.addFields(new List<String>{'Account.Id','Price_Book__c'});
hearingAidSelection = true;
classOptions = new List<SelectOption>();
classOptions.add(new SelectOption('Gold','Gold'));
classOptions.add(new SelectOption('Silver','Silver'));
classSelection = 'Gold';
}
//get current contact record
con = (Contact)stdController.getRecord();
haList = [ SELECT Id, Name, Battery__c, Class__c, Contact__c, Ear__c, Has_Accessory__c, Invoice_Date__c, Quantity__c, Opportunity__c,
Is_Accessory__c, Manufacturer__c, Manufacturer_Warranty_Expiration__c, Model__c, Related_Hearing_Aid__c,
Serial_Number__c, Related_Hearing_Aid__r.ID, Related_Hearing_Aid__r.Name, SKU__c
FROM Hearing_Aids__c
WHERE Contact__c = :con.ID AND Opportunity__c = null];
hearingAidWrappers = new List<WrapperClass>();
for(Hearing_Aids__c ha : haList){
hearingAidWrappers.add(new WrapperClass(ha));
}
}
public void hearingAidSelectionProceed(){
hearingAidSelection = false;
integer i = 0;
while (i < hearingAidWrappers.size()){
if(hearingAidWrappers[i].associateWithNewContract == false){
hearingAidWrappers.remove(i);
}
i++;
}
productSelection = true;
getProductOptions();
}
public PageReference cancel(){
return new PageReference('/' + con.Id);
}
public void getProductOptions(){
Set<String> classSet = new Set<String>();
//Put each wrapperclass into the three sets
for(WrapperClass wc : hearingAidWrappers){
classSet.add(wc.hearingAid.Class__c);
}
//query for the product2 records
List<Product2> prodList = [SELECT Id, Name, ProductCode, Class__c, Type__c FROM Product2 WHERE Class__c IN :classSet AND Type__c = :classSelection AND isActive = true];
//Organize into Map of List of Product2 records with the id being the combination of class and tier
Map<String,List<Product2>> prodMap = new Map<String,List<Product2>>();
for(Product2 prod : prodList){
if(prodMap.containsKey(prod.Class__c)){
prodMap.get(prod.Class__c).add(prod);
} else {
prodMap.put(prod.Class__c, new List<Product2>{prod});
}
}
//Loop through each Wrapper class again and see if you can find an existing match from the product2 map. If so, add them all as selectoptions on the wrapper class list of select options
for(WrapperClass wc : hearingAidWrappers){
if(prodMap.containsKey(wc.hearingAid.Class__c)){
for(Product2 prod : prodMap.get(wc.hearingAid.Class__c)){
wc.productOptions.add(new SelectOption(prod.Id, prod.Name));
}
}
}
}
//Submit
public PageReference submit(){
Map<Id,PricebookEntry> pricebookEntriesMap = getPricebookEntries();
//Create new opportunity
Opportunity opp = new Opportunity();
opp.AccountId = con.Account.Id;
opp.Contact__r.Id = con.Id;
opp.Name = 'Test Opp';
opp.StageName = 'Closed Won';
opp.CloseDate = System.today();
insert opp;
//Now that it has been inserted, we are taking the auto number field and setting it as the name
Opportunity updatedOpp = [SELECT Id, Contract__c, AccountId, Contact__c, Name, StageName, CloseDate FROM Opportunity WHERE Id = :opp.Id];
opp.Name = updatedOpp.Contract__c;
update opp;
insert getOlisToInsert(updatedOpp, pricebookEntriesMap);
//create contact role on opportunity to relate to contact
OpportunityContactRole ocr = new OpportunityContactRole();
ocr.ContactId = con.Id;
ocr.IsPrimary = True;
ocr.OpportunityId = opp.Id;
insert ocr;
//Return to the newly created opportunity
return new PageReference('/' + opp.Id);
}
/**
* Method to ge the matching pricebookentry records in order to save the correct information on the OLI
* @return Returns a map of Id and PricebookEntry, the Id is the Product2Id
*/
public Map<Id,PricebookEntry> getPricebookEntries(){
Map<Id,PricebookEntry> pricebookEntriesMap = new Map<Id,PriceBookEntry>();
Set<Id> prodIdSet = new Set<Id>();
for(WrapperClass wrapper : hearingAidWrappers){
prodIdSet.add(wrapper.selectedProduct);
}
Id newLeafPricebookId = [SELECT Id FROM Pricebook2 WHERE Name = 'New Leaf' LIMIT 1].Id;
for(PricebookEntry pbe : [SELECT Id, Pricebook2Id, Product2Id, ProductCode, UnitPrice FROM PriceBookEntry WHERE isActive = true AND Product2Id IN :prodIdSet AND Pricebook2Id = :newLeafPricebookId]){
pricebookEntriesMap.put(pbe.Product2Id, pbe);
}
return pricebookEntriesMap;
}
/**
* Method to return all of the newly created opportunity line items and update the hearing aids
* @param opp Parent Opp
* @param pricebookEntriesMap Map of pricebook entries in order to
* @return List of opportunity line items to be updated.
*/
public List<OpportunityLineItem> getOlisToInsert (Opportunity opp, Map<Id,PricebookEntry> pricebookEntriesMap){
List<Hearing_Aids__c> hearingAidsToUpdate = new List<Hearing_Aids__c>();
List<OpportunityLineItem> oliListToInsert = new List<OpportunityLineItem>();
//Create new opportunity line items (each hearing aid and accessory)
Integer i = 1;
for(WrapperClass wrapper : hearingAidWrappers){
Boolean contractAssigned = false;
PricebookEntry pbe = priceBookEntriesMap.get(wrapper.selectedProduct);
OpportunityLineItem oli = new OpportunityLineItem();
oli.OpportunityId = opp.Id;
oli.Quantity = 1;
oli.SKU__c = wrapper.hearingAid.SKU__c;
oli.TotalPrice = pbe.UnitPrice;
oli.Ear__c = wrapper.hearingAid.Ear__c;
oli.PriceBookEntryId = pbe.Id;
oli.Contact_related__c = wrapper.hearingAid.Contact__c;
oli.Manufacturer__c = wrapper.hearingAid.Manufacturer__c;
oli.Model__c = wrapper.hearingAid.Model__c;
//Loop through the hearing aids and give priority to left, then right, then the accessories after that
//Note, this will not ensure that all Left ears are 1 and Right ears are 2, becuase if we have two lefts,
//then the first would receieve 1, and the second could receive anything after that (and after a right ear too).
//This will work properly in the normal flow.
if(wrapper.hearingAid.Is_Accessory__c == false && wrapper.hearingAid.Ear__c == 'Left'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == false && wrapper.hearingAid.Ear__c == 'Right'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == true && wrapper.hearingAid.Ear__c == 'Left'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == true && wrapper.hearingAid.Ear__c == 'Right'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else {
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
}
oliListToInsert.add(oli);
wrapper.hearingAid.Opportunity__c = opp.Id;
hearingAidsToUpdate.add(wrapper.hearingAid);
}
update hearingAidsToUpdate;
return oliListToInsert;
}
//Wrapper class to hold each instance of a hearing aid conversion to an opportunity line item. This is also where the extra variables that need to be
//associated with the hearing aid live.
public class wrapperClass {
public Hearing_Aids__c hearingAid {get; set;}
public Boolean associateWithNewContract {get; set;}
public List<SelectOption> productOptions {get; set;}
public String selectedProduct {get; set;}
public wrapperClass(Hearing_Aids__c ha){
hearingAid = ha;
associateWithNewContract = true;
productOptions = new List<SelectOption>();
selectedProduct = '';
}
}
}
Test: @isTest(seeAllData=true)
private class ContractExtensionTest {
static testMethod void validateOpp() {
Test.startTest();
Account acc = new Account(Name = 'TestAccount');
insert acc;
Contact con = new Contact(LastName='Test',AccountId=acc.ID,RecordTypeId='0127A0000008l3I',Patient_ID__c='1234');
insert con;
ApexPages.StandardController setCon = new ApexPages.StandardController(con);
Hearing_Aids__c hal = new Hearing_Aids__c(Contact__c = con.ID, Class__c = 'TIER 1 (BAS)', Ear__c = 'Left', Manufacturer__c = 'TestManu',Model__c = 'TestModel', Serial_Number__c = '12345');
insert hal;
Hearing_Aids__c haa = new Hearing_Aids__c(Contact__c = con.ID, Class__c = 'Accessory', Ear__c = 'Left', Manufacturer__c = 'TestManu',Model__c = 'TestModel', Serial_Number__c = '12345');
insert haa;
ContractExtension ce = new ContractExtension(setCon);
ce.hearingAidSelectionProceed();
ce.getProductOptions();
//ce.getPricebookEntries();
ce.submit();
List<Opportunity> opp = new List<Opportunity>([SELECT AccountId FROM Opportunity WHERE Contact__c= :con.ID AND CloseDate = Today]);
List<OpportunityLineItem> oli = new List<OpportunityLineItem>([SELECT ID,Manufacturer__c,Model__c,Ear__c,Contact_related__c,OpportunityId FROM OpportunityLineItem WHERE Contact_related__c= :con.ID]);
System.debug('debug line 1 Opp: '+opp+' Oli: '+oli);
Opportunity opp1 = opp.get(0);
OpportunityLineItem oli1 = oli.get(0);
//update opp;
//update oli;
update con;
System.debug('debug line 2 Opp: '+opp+' Oli: '+oli);
System.assertEquals(hal.Manufacturer__c,oli1.Manufacturer__c);
System.assertEquals(hal.Model__c,oli1.Model__c);
System.assertEquals(hal.Ear__c,oli1.Ear__c);
}
}
FATAL_ERROR System.StringException: Invalid id:
and
FATAL_ERROR External entry point
referencing the submit method in my class.
Class:
public class ContractExtension {
//private final Hearing_Aids__c ha;
public final Contact con;
public List<Hearing_Aids__c> haList {get; set;}
public List<Hearing_Aids__c> haSelectedList {get; set;}
public List<WrapperClass> hearingAidWrappers {get; set;}
public Boolean hearingAidSelection {get; set;}
public Boolean productSelection {get; set;}
public List<SelectOption> classOptions {get; set;}
public String classSelection {get; set;}
public ContractExtension(ApexPages.StandardController stdController) {
if (!Test.isRunningTest()) {
stdController.addFields(new List<String>{'Account.Id','Price_Book__c'});
hearingAidSelection = true;
classOptions = new List<SelectOption>();
classOptions.add(new SelectOption('Gold','Gold'));
classOptions.add(new SelectOption('Silver','Silver'));
classSelection = 'Gold';
}
//get current contact record
con = (Contact)stdController.getRecord();
haList = [ SELECT Id, Name, Battery__c, Class__c, Contact__c, Ear__c, Has_Accessory__c, Invoice_Date__c, Quantity__c, Opportunity__c,
Is_Accessory__c, Manufacturer__c, Manufacturer_Warranty_Expiration__c, Model__c, Related_Hearing_Aid__c,
Serial_Number__c, Related_Hearing_Aid__r.ID, Related_Hearing_Aid__r.Name, SKU__c
FROM Hearing_Aids__c
WHERE Contact__c = :con.ID AND Opportunity__c = null];
hearingAidWrappers = new List<WrapperClass>();
for(Hearing_Aids__c ha : haList){
hearingAidWrappers.add(new WrapperClass(ha));
}
}
public void hearingAidSelectionProceed(){
hearingAidSelection = false;
integer i = 0;
while (i < hearingAidWrappers.size()){
if(hearingAidWrappers[i].associateWithNewContract == false){
hearingAidWrappers.remove(i);
}
i++;
}
productSelection = true;
getProductOptions();
}
public PageReference cancel(){
return new PageReference('/' + con.Id);
}
public void getProductOptions(){
Set<String> classSet = new Set<String>();
//Put each wrapperclass into the three sets
for(WrapperClass wc : hearingAidWrappers){
classSet.add(wc.hearingAid.Class__c);
}
//query for the product2 records
List<Product2> prodList = [SELECT Id, Name, ProductCode, Class__c, Type__c FROM Product2 WHERE Class__c IN :classSet AND Type__c = :classSelection AND isActive = true];
//Organize into Map of List of Product2 records with the id being the combination of class and tier
Map<String,List<Product2>> prodMap = new Map<String,List<Product2>>();
for(Product2 prod : prodList){
if(prodMap.containsKey(prod.Class__c)){
prodMap.get(prod.Class__c).add(prod);
} else {
prodMap.put(prod.Class__c, new List<Product2>{prod});
}
}
//Loop through each Wrapper class again and see if you can find an existing match from the product2 map. If so, add them all as selectoptions on the wrapper class list of select options
for(WrapperClass wc : hearingAidWrappers){
if(prodMap.containsKey(wc.hearingAid.Class__c)){
for(Product2 prod : prodMap.get(wc.hearingAid.Class__c)){
wc.productOptions.add(new SelectOption(prod.Id, prod.Name));
}
}
}
}
//Submit
public PageReference submit(){
Map<Id,PricebookEntry> pricebookEntriesMap = getPricebookEntries();
//Create new opportunity
Opportunity opp = new Opportunity();
opp.AccountId = con.Account.Id;
opp.Contact__r.Id = con.Id;
opp.Name = 'Test Opp';
opp.StageName = 'Closed Won';
opp.CloseDate = System.today();
insert opp;
//Now that it has been inserted, we are taking the auto number field and setting it as the name
Opportunity updatedOpp = [SELECT Id, Contract__c, AccountId, Contact__c, Name, StageName, CloseDate FROM Opportunity WHERE Id = :opp.Id];
opp.Name = updatedOpp.Contract__c;
update opp;
insert getOlisToInsert(updatedOpp, pricebookEntriesMap);
//create contact role on opportunity to relate to contact
OpportunityContactRole ocr = new OpportunityContactRole();
ocr.ContactId = con.Id;
ocr.IsPrimary = True;
ocr.OpportunityId = opp.Id;
insert ocr;
//Return to the newly created opportunity
return new PageReference('/' + opp.Id);
}
/**
* Method to ge the matching pricebookentry records in order to save the correct information on the OLI
* @return Returns a map of Id and PricebookEntry, the Id is the Product2Id
*/
public Map<Id,PricebookEntry> getPricebookEntries(){
Map<Id,PricebookEntry> pricebookEntriesMap = new Map<Id,PriceBookEntry>();
Set<Id> prodIdSet = new Set<Id>();
for(WrapperClass wrapper : hearingAidWrappers){
prodIdSet.add(wrapper.selectedProduct);
}
Id newLeafPricebookId = [SELECT Id FROM Pricebook2 WHERE Name = 'New Leaf' LIMIT 1].Id;
for(PricebookEntry pbe : [SELECT Id, Pricebook2Id, Product2Id, ProductCode, UnitPrice FROM PriceBookEntry WHERE isActive = true AND Product2Id IN :prodIdSet AND Pricebook2Id = :newLeafPricebookId]){
pricebookEntriesMap.put(pbe.Product2Id, pbe);
}
return pricebookEntriesMap;
}
/**
* Method to return all of the newly created opportunity line items and update the hearing aids
* @param opp Parent Opp
* @param pricebookEntriesMap Map of pricebook entries in order to
* @return List of opportunity line items to be updated.
*/
public List<OpportunityLineItem> getOlisToInsert (Opportunity opp, Map<Id,PricebookEntry> pricebookEntriesMap){
List<Hearing_Aids__c> hearingAidsToUpdate = new List<Hearing_Aids__c>();
List<OpportunityLineItem> oliListToInsert = new List<OpportunityLineItem>();
//Create new opportunity line items (each hearing aid and accessory)
Integer i = 1;
for(WrapperClass wrapper : hearingAidWrappers){
Boolean contractAssigned = false;
PricebookEntry pbe = priceBookEntriesMap.get(wrapper.selectedProduct);
OpportunityLineItem oli = new OpportunityLineItem();
oli.OpportunityId = opp.Id;
oli.Quantity = 1;
oli.SKU__c = wrapper.hearingAid.SKU__c;
oli.TotalPrice = pbe.UnitPrice;
oli.Ear__c = wrapper.hearingAid.Ear__c;
oli.PriceBookEntryId = pbe.Id;
oli.Contact_related__c = wrapper.hearingAid.Contact__c;
oli.Manufacturer__c = wrapper.hearingAid.Manufacturer__c;
oli.Model__c = wrapper.hearingAid.Model__c;
//Loop through the hearing aids and give priority to left, then right, then the accessories after that
//Note, this will not ensure that all Left ears are 1 and Right ears are 2, becuase if we have two lefts,
//then the first would receieve 1, and the second could receive anything after that (and after a right ear too).
//This will work properly in the normal flow.
if(wrapper.hearingAid.Is_Accessory__c == false && wrapper.hearingAid.Ear__c == 'Left'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == false && wrapper.hearingAid.Ear__c == 'Right'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == true && wrapper.hearingAid.Ear__c == 'Left'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else if(wrapper.hearingAid.Is_Accessory__c == true && wrapper.hearingAid.Ear__c == 'Right'){
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
} else {
oli.Contract__c = opp.Contract__c + '-' + i;
i++;
}
oliListToInsert.add(oli);
wrapper.hearingAid.Opportunity__c = opp.Id;
hearingAidsToUpdate.add(wrapper.hearingAid);
}
update hearingAidsToUpdate;
return oliListToInsert;
}
//Wrapper class to hold each instance of a hearing aid conversion to an opportunity line item. This is also where the extra variables that need to be
//associated with the hearing aid live.
public class wrapperClass {
public Hearing_Aids__c hearingAid {get; set;}
public Boolean associateWithNewContract {get; set;}
public List<SelectOption> productOptions {get; set;}
public String selectedProduct {get; set;}
public wrapperClass(Hearing_Aids__c ha){
hearingAid = ha;
associateWithNewContract = true;
productOptions = new List<SelectOption>();
selectedProduct = '';
}
}
}
Test: @isTest(seeAllData=true)
private class ContractExtensionTest {
static testMethod void validateOpp() {
Test.startTest();
Account acc = new Account(Name = 'TestAccount');
insert acc;
Contact con = new Contact(LastName='Test',AccountId=acc.ID,RecordTypeId='0127A0000008l3I',Patient_ID__c='1234');
insert con;
ApexPages.StandardController setCon = new ApexPages.StandardController(con);
Hearing_Aids__c hal = new Hearing_Aids__c(Contact__c = con.ID, Class__c = 'TIER 1 (BAS)', Ear__c = 'Left', Manufacturer__c = 'TestManu',Model__c = 'TestModel', Serial_Number__c = '12345');
insert hal;
Hearing_Aids__c haa = new Hearing_Aids__c(Contact__c = con.ID, Class__c = 'Accessory', Ear__c = 'Left', Manufacturer__c = 'TestManu',Model__c = 'TestModel', Serial_Number__c = '12345');
insert haa;
ContractExtension ce = new ContractExtension(setCon);
ce.hearingAidSelectionProceed();
ce.getProductOptions();
//ce.getPricebookEntries();
ce.submit();
List<Opportunity> opp = new List<Opportunity>([SELECT AccountId FROM Opportunity WHERE Contact__c= :con.ID AND CloseDate = Today]);
List<OpportunityLineItem> oli = new List<OpportunityLineItem>([SELECT ID,Manufacturer__c,Model__c,Ear__c,Contact_related__c,OpportunityId FROM OpportunityLineItem WHERE Contact_related__c= :con.ID]);
System.debug('debug line 1 Opp: '+opp+' Oli: '+oli);
Opportunity opp1 = opp.get(0);
OpportunityLineItem oli1 = oli.get(0);
//update opp;
//update oli;
update con;
System.debug('debug line 2 Opp: '+opp+' Oli: '+oli);
System.assertEquals(hal.Manufacturer__c,oli1.Manufacturer__c);
System.assertEquals(hal.Model__c,oli1.Model__c);
System.assertEquals(hal.Ear__c,oli1.Ear__c);
}
}
Hi Jean,
Please use this under submit function : -
opp.Contact__c = con.Id;
Instead opp.Contact__r.Id = con.Id;
Please let me know in cas eof any help :)
Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com
All Answers
ok? Name should be text but not sure what "Contract__c" in the Opportunity is.
Hi Nahuel, the Contract__c is an auto-number, could that be the problem?
Hi Jean,
Please use this under submit function : -
opp.Contact__c = con.Id;
Instead opp.Contact__r.Id = con.Id;
Please let me know in cas eof any help :)
Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com