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
jbroquistjbroquist 

Set Master-Detail Relationship Field on Custom Object

I have a custom object called Merchant_Analysis__c which has a master-detail relationship with Opportunity. There is a field on the custom object called Opportunity__c which is just a reference to the parent Opportunity. I have a simple javascript button on the Opportunity called  New Merchant Analysis which simply passes the opportunity id to the visualforce controller via GET.

 

In my save method for the controller I set the Merchant_Analysis__c.Opportunity__c field to the ID of the Opportunity

 

public analysisController()

{

String oid = System.currentPageReference().getParameters().get('id');

 

if(oid != null && oid != '')

{

Opportunity o = [select id,name from Opportunity WHERE id=:oid];

this.oppID = o.id;

}

}

public PageReference save()

{

analysis.Opportunity__c = oppID;

analysis.recordtypeid = recType;

insert analysis;

 

PageReference analysisPage = new PageReference('/' + analysis.id);

analysisPage.setRedirect(true);

 

return analysisPage;

}

 

 The variable oppID is a public class level String variable that holds the Opportunity ID. For some reason when I run my test methods I get the following error:

 

System.SObjectException: Field is not writeable: Merchant_Analysis__c.Opportunity__c

 I've checked all the field level securities and everything to make sure Opportunity__c is not read only anywhere. For some reason I cannot figure out how to get past this error or even what is causing it.

 

Does anyone know how I can set the the relationship field of a Custom Object with a Master-Detail Relationship?

 

 

Any help would be great, as this problem has been plaguing me for too long now.

 

 

Thanks,

Jonathan 

 

 

 

Message Edited by jbroquist on 02-26-2009 11:52 AM
Message Edited by jbroquist on 02-26-2009 11:52 AM
danielfnzdanielfnz

For Opportunity__c to be visible to the controller you might need to bind it to a hidden inputField

 

 

<apex:inputHidden value="{!analysis.Opportunity__c}"/>

 

Hopefully that works,

 

Dan

 

jbroquistjbroquist
I'm still receiving the same error. Placing the hidden input field didn't seem to work ...
VisualForceVisualForce

Hi..

  I think in ur test method or apex class u are updated new opportunity value for Merchant Analysis...

Can u post ur sample code..

 

jbroquistjbroquist

Here ya go ... 

 

 

static testMethod void testSave()

{

analysisController controller = new analysisController();

String recType = '012400000005QI0AAM';

 

Opportunity o = new Opportunity(name='test opp',stagename='test stage',closedate=System.today());

insert o;

Merchant_Analysis__c a = new Merchant_Analysis__c();

a.Opportunity__c = o.id;

a.recordtypeid=recType;

insert a;

PageReference testPage = new PageReference('/' + a.id);

testPage.setRedirect(true);

controller.oppID = o.id;

controller.recType = recType;

controller.analysis = a;

String ref0 = testPage.getUrl();

String ref1 = controller.save().getUrl();

System.assertEquals(ref0,ref1);

} 

VisualForceVisualForce

Hi..

 In ur post 

"I have a simple javascript button on the Opportunity called  New Merchant Analysis which simply passes the opportunity id to the visualforce controller via GET."

       You are passing Opportunity Id to the VF page, but in ur test method u r passing Merchant_Analysis__c Id. (   PageReference testPage = new PageReference('/' + a.id);   )

     try with opportunity ID - PageReference testPage = new PageReference('/' + o.id);

 If u still get error post ur controller code here..

 

 

 

Message Edited by VisualForce on 03-01-2009 09:33 PM
jbroquistjbroquist

I'm passing the Opportunity ID in order to create a relationship between the new Merchant Analysis object being created and that particular Opportunity. In my test method I compare the URL's of the new Analysis to determine whether or not it was successfully inserted. The problem that is generating the errors has to do with the way I set the relationship. I have tried querying the Opportunity and storing it in a public variable for reference and setting the Opportunity__r field on the custom object to that Opportunity. While that works, it doesn't solve the problem of the Opportunity__c field being required. I believe that it is required because of the Master-Detail relationship between it and the Opportunity object.

 

Now the problem I run into while setting the Opportunity__c field is that when I pass the ID in to that field I get an error saying that the field is not writeable.  The weird thing is ... that the code runs and executes fine. The relationship gets set and the new Analysis inserted. BUT when I try to get my code to the 75% code coverage the tests are throwing back errors telling me I can't write to the Opportunity__c field. 

 

Unless someone knows how to get around writing to the custom relationship field, I don't know what else there is to do other than re-design how our system works without the Master-Detail relationship. 

pierpipierpi

Hi Jonathan,

I just saw the post and probably you have already figured out how to workaround it.  However, here are my findings (I'm relatively new to SF and I'm working at something similar to the problem you faced):

 

 

  1. The reference in the detail record to the master record is required and can not be changed (look at the description of a master-detail field when you try to create a new one - i.e. "Once the value of the relationship field has been saved, it cannot be changed.").
  2. The reference to the master object can not even be set to the same value.  If you try to update the record setting its reference to the current master you will get the same exception (i.e. let's say the analysis child/detail record already exist and it's master reference Opportunity__c is set to X, if you explicitly set it again - analysis.Opportunity__c = X; - you will get the exception).

 

In your test code do not insert (i.e. comment it out) the custom object Merchant_Analysis__c,just pass the reference to the non inserted object to your controller.  If the controller save() operation can be invoked to both save an new record and edit an existent one you would need a different logic in the implementation (according to whether it is a save due to new or edit operation).  If the save operation is triggered by a edit operation you should use "update analysis" and you should not reset the reference to the master record. 

 

As I said, most likely you have already figured out the issue but just in case I hope that what i wrote makes sense and is helpful.

 

Cheers

Pierpi