+1 vote
34 views
by (163k points)

I have a visualforce page on the work order object with a form that is getting filled out. The form lists out all of the assets on an order. A user is able to fill out information for each asset, click the save button, and all of the info is saved to the asset record. Each asset also has a related case. I am trying to enter in the install date for each asset and have that value save to the install date field on the related ticket. I was able to query the install date field from the related ticket and put it on the visualforce page, but when I click the save button it doesn't save the value of the install date field on the related ticket. I have also tried putting the install date field from the asset on the visualforce page, enter in the install date on the asset, then when the save button is click the install date value is saved to the asset and pushes to the install date field on the related ticket. When I try this I get an error that says

"SObject row was retrieved via SOQL without querying the requested field: Asset.New_Equipment_Setup_and_Install_Ticket__r Error is in expression '{!saveSerialIdNumber}' in component apex:commandButton in page installupdateassetworkorder: Class.installUpdateAssetWorkOrderClass.saveSerialIdNumber: line 59, column 1."

Here is my visualforce page for the form that is being filled out:

   <apex:page docType="html-5.0" standardController="WorkOrder" extensions="installUpdateAssetWorkOrderClass" id="thePage">     
   
   <apex:form id="theForm"> 
       
        <apex:pageblock id="Assets">
            
                <apex:pageBlockTable rows="" id="pbt0" value="{!WorkOrder.Assets__r}" var="asset">
            
                <apex:column headerClass="textAlignCenter" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" style="width:16.66666666666667%;" headerValue="Product Code"><!-- to take the label dynamically -->
                    <apex:inputText style="width:94%;" disabled="true" styleClass="setupModelForId" value="{!asset.Product_Code_for_Paperless_Install_Docs__c}"></apex:inputText>
                </apex:column>
            
                
                
                <apex:column headerClass="textAlignCenter" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" style="width:20%;" headerValue="ID Number"><!-- to take the label dynamically -->
                    <apex:inputText style="width:94%;" styleClass="idNumber" value="{!asset.New_Asset_Install_LOC_ID_Number__c}">
                        <apex:actionSupport event="onchange" action="{!updateIdNumber}"/>
                    </apex:inputText>
                </apex:column>
                
                    
                    
                <apex:column headerClass="textAlignCenter" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" style="width:16.66666666666667%;" headerValue="B/W Meter"><!-- to take the label dynamically -->
                    <apex:inputText required="true" styleClass="bwMeter" style="width:94%;" value="{!asset.New_Asset_Install_B_W_Meter__c}"  />
                </apex:column>
                
                <apex:column headerClass="textAlignCenter" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" style="width:16.66666666666667%;" headerValue="Color Meter"><!-- to take the label dynamically -->
                    <apex:inputText styleClass="colorMeter" style="width:94%;" value="{!asset.New_Asset_Install_Color_Meter__c}"  />
                </apex:column>
                
                <apex:column headerClass="textAlignCenter" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" style="width:16.66666666666667%;" headerValue="I.P. Address"><!-- to take the label dynamically -->
                    <apex:inputText styleClass="ipAddress" style="width:94%;" value="{!asset.New_Asset_Install_Equipment_IP_Address__c}"  />
                </apex:column>
                
                <apex:column headerClass="textAlignCenter" style="width:16.66666666666667%;" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" headerValue="Install Date">
                    <apex:inputField id="installDate" styleClass="installDate" value="{!asset.Install_Date__c}"/>
                </apex:column>
                
                <apex:column headerClass="textAlignCenter" style="width:16.66666666666667%;"  headerValue="Install Date">
                    <apex:outputText value="{!asset.New_Equipment_Setup_and_Install_Ticket__r.Install_Date__c}" rendered="false"/>
                 </apex:column>
                    
                 <apex:column headerClass="textAlignCenter" style="width:16.66666666666667%;" rendered="{!asset.SBQQ__RequiredByAsset__c == null}" styleClass="" headerValue=""><!-- to take the label dynamically -->
                        <apex:inputText disabled="true" style="" styleClass="setupIdNumber" value="{!asset.New_Asset_Setup_LOC_ID__c}"  />
                 </apex:column>
                    
                    
            
            </apex:pageBlockTable>
            
       </apex:pageblock>
       
    </apex:form>
    
</apex:page>

Here is my apex class with the save button:

public class installUpdateAssetWorkOrderClass {

private ApexPages.StandardController controller;

public List<WorkOrderLineItem> WorkOrderLineItems{get;set;}

public List<WorkOrderLineItem> WorkOrderLineItemsSupplies{get;set;}

public List<Asset> Assets{get;set;}

public List<Case> Cases{get;set;}

public WorkOrder WorkOrders {get;set;} 

public WorkOrder wo {get;set;} 

 

//Constructor 

 public installUpdateAssetWorkOrderClass(ApexPages.StandardController controller) {
    this.controller = controller;
     


    wo = (WorkOrder)controller.getRecord();      
     
    WorkOrders = [SELECT id FROM WorkOrder WHERE id=: wo.id LIMIT 1];  

    Assets = [SELECT id, Install_Date__c, New_Equipment_Setup_and_Install_Ticket__r.Install_Date__c, Product2.Serialized__c, New_Equipment_Setup_and_Install_Ticket__c, Show_in_MultiMachine_Delivery_Acceptance__c,SerialNumber,Name,Delivery_Address__c,Product_Code_Display__c,Product_Description_Display__c FROM Asset where Work_Order__c = :WorkOrders.id]; 
 
    Cases = [SELECT id, AssetId,Asset.Name,Install_Date__c, Cheater_Left_On_Sight__c FROM Case WHERE Work_Order__c = : WorkOrders.id];
 
 } 

//update ID number
public void updateIdNumber(){
    for(Asset assetObj : (list<Asset>) ((WorkOrder) controller.getRecord()).Assets__r){
       if(assetObj.SBQQ__RequiredByAsset__c == null){
        assetObj.Name = assetObj.New_Asset_Install_LOC_ID_Number__c;
        } 
    } 
    update ((WorkOrder) controller.getRecord()).Assets__r;
    
}

public void saveSerialIdNumber() {
    
    for(Asset assetObj : (list<Asset>) ((WorkOrder) controller.getRecord()).Assets__r){
        
        assetObj.SerialNumber = assetObj.New_Asset_Install_LOC_Serial_Number__c;
        
        assetObj.New_Equipment_Setup_and_Install_Ticket__r.Install_Date__c = assetObj.Install_Date__c;
         
    }
   
    
    update ((WorkOrder) controller.getRecord()).Assets__r;
    
    controller.save();
    
    
}

 

}

Any help would be greatly appreciated. Thanks!

1 Answer

+1 vote
by (163k points)
 
Best answer

Assuming line 59 is this line:

assetObj.New_Equipment_Setup_and_Install_Ticket__r.Install_Date__c = assetObj.Install_Date__c;

Then the issue is that the relationship object New_Equipment_Setup_and_Install_Ticket__r doesn't exist in the controller's object state. This leads us to how assetObj is defined

for(Asset assetObj : (list<Asset>) ((WorkOrder) controller.getRecord()).Assets__r){

and in turn, this leads us to the controller.getRecord().

In VF, the object returned by getRecord() will only include fields that have explicit VF page markup (i.e. an apex:inputField, apex:outputField, apex:variable, etc). Your form only references via VF components fields on Asset.

This is all described here in the VF Doc

Note that only the fields that are referenced in the associated Visualforce markup are available for querying on this SObject. All other fields, including fields from any related objects, must be queried using a SOQL expression.

Tip You can work around this restriction by including a hidden component that references any additional fields that you want to query. Hide the component from display by setting the component's rendered attribute to false.

So, either re-query for the related record in the controller or use the hidden field approach.

Welcome to Memory Exceeded, where you can ask questions and receive answers from other members of the community.
...