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
Sudhir_MeruSudhir_Meru 

Error: Compile Error: Field is not writeable: Product2 at line 37 column 24

Hi, 

  I am getting error while saving trigger in below line 37. Please suggest me how to fix this issue. 

trigger Temp_Asset2_Opp on Temp_Assets__c (after insert )
{
  List<Temp_Assets__c> CurrentAsset = [Select Id, Name, Serial_Number__c, AccountId__c, Product__c, Service_Start_Date__c,
                                              Service_End_Date__c ,Install_Date__c ,Reseller__c,Distributor__c ,
                                              Incumbent_Reseller__c,Education__c,Expiry_Date__c,Existing_Opportunity__c,
                                              New_Opportunity__c,Expiry_Term__c,Bundle_Support__c 
                                       From Temp_Assets__c];

 
  for ( Temp_Assets__c TA : CurrentAsset )
  {
      // If New Opportunity is Created 
     if ( TA.Existing_Opportunity__c == NULL && TA.New_Opportunity__c != NULL )   
      {
         // Insert Opportunity with all mandatory fields
         Opportunity Opp = new Opportunity();
         Opp.Name      = [SELECT New_Opportunity__c From Temp_Assets__c Limit 1].New_Opportunity__c;            
         Opp.Type      = 'Existing Customer';
         Opp.AccountId = [SELECT AccountId__c From Temp_Assets__c Limit 1].AccountId__c;
         Opp.CloseDate = [SELECT Expiry_Date__c From Temp_Assets__c Limit 1].Expiry_Date__c;
         Opp.Government_Contract__c = 'None';
         Opp.StageName = 'Renewal';
         Opp.Lost_Reason__c = 'Other';
         Opp.Primary_Competitor__c = 'No Competitor';
         Opp.ForecastCategoryName = 'Pipeline';
         Opp.LeadSource = 'Renewal';
         Opp.Primary_Reseller__c    = [SELECT Reseller__c From Temp_Assets__c Limit 1].Reseller__c;
         Opp.Primary_Distributor__c = [SELECT Distributor__c From Temp_Assets__c Limit 1].Distributor__c;
         Opp.Renewal_Incumbant_Reseller__c =  'None';
         Opp.Renewal_K_12__c   =  'No';
        
         Insert Opp;
        
        // Insert into Opportunity Lines
         OpportunityLineItem OppL = new OpportunityLineItem(
            OpportunityId = Opp.Id,
            Product2 = TA.Product__c
           
           
          );
         Insert OppL;                       
        } 
       
       //If Existing Opportunity is selected   
      else if ( TA.Existing_Opportunity__c != NULL && TA.New_Opportunity__c == NULL )   
      {
     
      }

    
  }  
 
 
 
 
}


Vinit_KumarVinit_Kumar
The field is now Product2 but it is Product2Id hence change your code from

Product2 = TA.Product__c

to

Product2Id = TA.Product__c


Ajay_SFDCAjay_SFDC
Hi Sudhir ,
 As per saledforce documentation :
Product2Id is a read-only field available in API version 30.0 and later for OpportunityLineItem.
Use the PricebookEntryId field instead, specifying the ID of the PricebookEntry record.
Check this : https://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunitylineitem.htm


Thanks ,
 Ajay

Sudhir_MeruSudhir_Meru

Hi Ajay,


 I modified as mentioned below PricebookEntryId = TA.Product__c want to add Product from temp_asset__c object to opportunitylines will this work Please suggest.


trigger Temp_Asset2_Opp on Temp_Assets__c (after insert )
{
  List<Temp_Assets__c> CurrentAsset = [Select Id, Name, Serial_Number__c, AccountId__c, Product__c, Service_Start_Date__c,
                                              Service_End_Date__c ,Install_Date__c ,Reseller__c,Distributor__c ,
                                              Incumbent_Reseller__c,Education__c,Expiry_Date__c,Existing_Opportunity__c,
                                              New_Opportunity__c,Expiry_Term__c,Bundle_Support__c 
                                       From Temp_Assets__c];

 
  for ( Temp_Assets__c TA : CurrentAsset )
  {
      // If New Opportunity is Created 
     if ( TA.Existing_Opportunity__c == NULL && TA.New_Opportunity__c != NULL )   
      {
         // Insert Opportunity with all mandatory fields
         Opportunity Opp = new Opportunity();
         Opp.Name      = [SELECT New_Opportunity__c From Temp_Assets__c Limit 1].New_Opportunity__c;            
         Opp.Type      = 'Existing Customer';
         Opp.AccountId = [SELECT AccountId__c From Temp_Assets__c Limit 1].AccountId__c;
         Opp.CloseDate = [SELECT Expiry_Date__c From Temp_Assets__c Limit 1].Expiry_Date__c;
         Opp.Government_Contract__c = 'None';
         Opp.StageName = 'Renewal';
         Opp.Lost_Reason__c = 'Other';
         Opp.Primary_Competitor__c = 'No Competitor';
         Opp.ForecastCategoryName = 'Pipeline';
         Opp.LeadSource = 'Renewal';
         Opp.Primary_Reseller__c    = [SELECT Reseller__c From Temp_Assets__c Limit 1].Reseller__c;
         Opp.Primary_Distributor__c = [SELECT Distributor__c From Temp_Assets__c Limit 1].Distributor__c;
         Opp.Renewal_Incumbant_Reseller__c =  'None';
         Opp.Renewal_K_12__c   =  'No';
        
         Insert Opp;
        
        // Insert into Opportunity Lines
         OpportunityLineItem OppL = new OpportunityLineItem(
            OpportunityId = Opp.Id,
            PricebookEntryId = TA.Product__c
            //Quantity
           
          );
         Insert OppL;                       
        } 
       
       //If Existing Opportunity is selected   
      else if ( TA.Existing_Opportunity__c != NULL && TA.New_Opportunity__c == NULL )   
      {
     
      }

    
  }  
  
 
}


Thanks

Sudhir

Ajay_SFDCAjay_SFDC
Hi Sudhir ,

I think you need to query on pricebook :

List<PriceBookEntry> priceBookList = [SELECT Id, Product2Id, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id='certain_id' AND PriceBook2.isStandard=true LIMIT 1];

I suggest : Add all the Productid from Temp_Asset__c to a set .

Like : set<Id > setProdId= new set<Id>(); 
           List<Opportunity> lstopp = new List<Opportunity>();
          for ( Temp_Assets__c TA : CurrentAsset )
                { // Your Logic        
                   // Create the opportunity object and add it into list
                  // Never do any DML in for loop

                   lstOpp.add(Opp);
                   setProdId.add(TA.Product__c);
                  
                  }


List<PriceBookEntry> priceBookList = [SELECT Id, Product2Id, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id=setProdId AND PriceBook2.isStandard=true LIMIT 1];
 

I am not sure how its going to work . As you have not followed the proper structure for writing the code . Because in your code you have written queries inside for loop which is not a good practice .

Thanks ,
 Ajay

Mikola SenykMikola Senyk
You need a Map<Id,Id> where key = Prodiuct2id and value = PriceBookEntry.Id.
You can build certain map with the following code:
List<PricebookEntry> pbeList = [
    SELECT Id, Product2Id FROM PricebookEntry
    WHERE Product2Id IN :prodIds
    AND Pricebook2.isStandard=true
];
Map<Id,Id> prodToPbe = new Map<Id,Id>();
for (PricebookEntry pbEntry: pbeList) {
    prodToPbe.put(pbEntry.Product2Id, pbEntry.Id);
}
where prodIds - set of product ID or List of products.
After that you can use the following code to create OpportunityLineItem:
OpportunityLineItem OppL = new OpportunityLineItem(
    OpportunityId = Opp.Id,
    PricebookEntryId = prodToPbe.get(TA.Product__c)
    // other fields ...

);