I'm trying to create a visualforce page where a user can create multiple OrderItem records at the same time.
The error that I get is
OrderItem records Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] - Line: 138
I have 2 methods in the controller
obtenerProductos()
shows records of PriceBookEntryinsertarProductos()
checks these records and create records of OrderItem object but it doesn't work.
The other objects that I'm using are Opportunity, Order, PriceBook2 and Product2.
I think the problem is with the field PricebookEntryId
of the variable prAux
.
Visualforce
<apex:page standardController="Opportunity" extensions="CotizadorPrincipalController" lightningStylesheets="true" docType="html-5.0">
<apex:pageBlock title="Detalles de la Oportunidad">
<apex:form >
<apex:pageBlockSection columns="2">
<apex:pageblockSectionItem >Nombre<apex:outputField value="{!Opportunity.Name }"/></apex:pageblockSectionItem>
<apex:outputField value="{!Opportunity.Fecha_del_evento__c }"/>
<apex:outputField value="{!Opportunity.Total_de_Servicios_con_IVA__c }"/>
<apex:outputField value="{!Opportunity.Espacio__c }"/>
</apex:pageBlockSection>
<!-- Botón de regreso a la página de la Oportunidad -->
<a style="float:right;"><apex:commandButton value="Regresar a la Oportunidad" action="{!volver}"/></a>
</apex:form>
</apex:pageBlock>
<apex:pageBlock >
<apex:form >
<apex:pageBlockSection title="Seleccione el Servicio:" collapsible="false">
<apex:selectList value="{!servicioSeleccionado}" size="1">
<apex:actionSupport event="onchange" rerender="form"/>
<apex:selectOptions value="{!orders}"/>
</apex:selectList><br/>
<apex:commandButton value="Show Service" action="{!show}"/>
<apex:commandButton value="Mostrar Productos" action="{!obtenerProductos}"/>
</apex:pageBlockSection>
<apex:pageBlockSection title="Seleccione los productos a añadir:" columns="1">
<apex:pageBlockTable value="{!listaProductosParaAnadir}" var="wrpProductos">
<apex:column ><apex:inputCheckbox value="{!wrpProductos.check}"/></apex:column>
<apex:column value="{!wrpProductos.productosParaAnadir.Product2.Name}"/>
<apex:column headerValue="Precio por Unidad"><apex:inputField value="{!wrpProductos.productosParaAnadir.UnitPrice}"/></apex:column>
<apex:column headerValue="Cantidad"><apex:input type="number" value="{!wrpProductos.cantidad}"/></apex:column>
<apex:column value="{!wrpProductos.productosParaAnadir.Product2.IVA__c}"/>
</apex:pageBlockTable>
</apex:pageBlockSection>
<apex:pageBlockSection title="Añada productos no existentes en la base de datos:">
<apex:pageBlockTable value="{!listaProductosParaAnadirNoExistentes}" var="wrpProductosNoExist">
<apex:column ><apex:inputCheckbox value="{!wrpProductosNoExist.check}"/></apex:column>
<apex:column ><apex:inputField value="{!wrpProductosNoExist.productosParaAnadir.Product2.Name}"/></apex:column>
<apex:column headerValue="Precio por Unidad"><apex:inputField value="{!wrpProductosNoExist.productosParaAnadir.UnitPrice}"/></apex:column>
<apex:column headerValue="Cantidad"><apex:input type="number" value="{!wrpProductosNoExist.cantidad}"/></apex:column>
<apex:column headerValue="IVA"><apex:inputField value="{!wrpProductosNoExist.productosParaAnadir.Product2.IVA__c}"/></apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
<apex:pageBlockSection >
<apex:commandButton value="Insertar Productos" action="{!insertarProductos}"/>
</apex:pageBlockSection>
</apex:form>
</apex:pageBlock>
</apex:page>
Controller
public class CotizadorPrincipalController {
private final Opportunity opp;
private Map<String, Id> ordersMap;
private Map<String, Id> priceBookEntriesMap;
public String servicioSeleccionado {get;set;}
private String BASE_URL = System.URL.getSalesforceBaseUrl().toExternalForm() + '/';
private String BASE_URL2 = System.URL.getSalesforceBaseUrl().toExternalForm() + '/';
public List<OrderItem> listaProductos {get;set;}
public boolean check {get;set;}
public List<ProductosWrapper> listaProductosParaAnadir {get;set;}
public List<ProductosWrapper> listaProductosParaAnadirNoExistentes {get;set;}
//Clase del Wrapper de Productos del objeto OrderItem, de momento no se usa
//Clase del Wrapper de Productos del objeto PriceBookEntry
public class ProductosWrapper{
public PriceBookEntry productosParaAnadir {get;set;}
public Boolean check {get;set;}
public Integer cantidad {get; set;}
public productosWrapper(PriceBookEntry pbEntry){
productosParaAnadir = pbEntry.clone (false, false, false, false);
check = false;
cantidad = 0;
}
}
public CotizadorPrincipalController(ApexPages.StandardController stdController) {
this.opp = (Opportunity)stdController.getRecord();
this.ordersMap = new Map<String, Id>();
this.servicioSeleccionado = '';
this.listaProductos = new List<OrderItem>();
check = false;
listaProductosParaAnadir = new List<ProductosWrapper>();
listaProductosParaAnadirNoExistentes = new List<ProductosWrapper>();
system.debug('BASE_URL = ' + BASE_URL);
List<Order> ordersList = [SELECT Id, Name from Order where Oportunidad__c =: this.opp.Id];
this.servicioSeleccionado = ordersList.get(0).Name;
for(Order o: ordersList) {
this.ordersMap.put(o.Name, o.Id);
}
}
public void obtenerProductos(){
List<PriceBookEntry> listaPlantillasProductos = new List<PriceBookEntry>();
this.priceBookEntriesMap = new Map<String,Id>();
listaProductosParaAnadir.clear();
Opportunity oppActual = [SELECT Id, Espacio__c, Fecha_del_evento__c FROM Opportunity WHERE Id =: this.opp.Id];
Integer yearEvento = oppActual.Fecha_del_evento__c.year();
String yearEventoToString = String.valueOf(yearEvento);
System.debug('Fecha del evento = ' + oppActual.Fecha_del_evento__c);
System.debug('Año de variable year = ' + yearEvento);
System.debug('Año de variable year = ' + yearEventoToString);
listaPlantillasProductos = [SELECT UnitPrice, Product2.Name, Product2.IVA__c, Product2.Family, Product2Id, PriceBook2Id, PriceBook2.Espacio__c, PriceBook2.Ano__c
FROM PriceBookEntry
WHERE PriceBook2.Espacio__c != null AND PriceBook2.Espacio__c =: oppActual.Espacio__c
AND PriceBook2.Ano__c =: yearEventoToString];
System.debug('listaPlantillasProductos.size(): ' + listaPlantillasProductos.size());
if(!listaPlantillasProductos.isEmpty()){
for(PriceBookEntry pbe : listaPlantillasProductos){
this.priceBookEntriesMap.put(pbe.Product2.Name, pbe.Id);
}
ProductosWrapper wrp;
for (PriceBookEntry pbe : listaPlantillasProductos){
wrp = new productosWrapper(pbe);
if(pbe.Product2.Name == 'varios'){
listaProductosParaAnadirNoExistentes.add(wrp);
}else{
listaProductosParaAnadir.add(wrp);
}
System.debug('PriceBookEntry pbe Name: ' + pbe.Product2.Name);
}
for(ProductosWrapper pw : listaProductosParaAnadirNoExistentes){
System.debug('Nombre del producto NO existente = ' + pw.productosParaAnadir.Product2.Name);
}
for(ProductosWrapper pw : listaProductosParaAnadir){
System.debug('Nombre del producto Sí existente = ' + pw.productosParaAnadir.Product2.Name);
}
}
}
public void insertarProductos(){
List<OrderItem> listProductosServicioInsertar = new List<OrderItem>();
for(ProductosWrapper listado : listaProductosParaAnadir){
if(listado.cantidad > 0 && listado.cantidad != null){
System.debug('listado.cantidad = ' + listado.cantidad);
OrderItem prAux = new OrderItem();
prAux.Quantity = listado.cantidad;
system.debug('prAux.Quantity = ' + prAux.Quantity);
prAux.UnitPrice = listado.productosParaAnadir.UnitPrice;
system.debug('prAux.UnitPrice = ' + prAux.UnitPrice);
prAux.IVA__c = listado.productosParaAnadir.Product2.IVA__c;
system.debug('prAux.IVA__c = ' + prAux.IVA__c);
prAux.OrderId = this.OrdersMap.get(this.servicioSeleccionado);
system.debug('prAux.OrderId = ' + prAux.OrderId);
prAux.Oportunidad__c = this.opp.Id;
system.debug('prAux.Oportunidad__c = ' + prAux.Oportunidad__c);
//prAux.PricebookEntryId = listado.productosParaAnadir.Id; //Aquí falla ya que no existe el id
System.debug('this.priceBookEntriesMap.get(listado.productosParaAnadir.Product2.Name) = ' + this.priceBookEntriesMap.get(listado.productosParaAnadir.Product2.Name));
system.debug('listado.productosParaAnadir.Product2.Name = ' + listado.productosParaAnadir.Product2.Name);
prAux.PricebookEntryId = this.priceBookEntriesMap.get(listado.productosParaAnadir.Product2.Name);
System.debug('prAux.PricebookEntryId = ' + prAux.PricebookEntryId);
system.debug('listado.productosParaAnadir.Id = ' + listado.productosParaAnadir.Id);
listProductosServicioInsertar.add(prAux);
}
}
try {
if(!listProductosServicioInsertar.isEmpty()){
insert listProductosServicioInsertar;
}
}catch (Exception Exc){
System.debug('##Error: '+exc.getMessage() + ' - Line: '+exc.getLineNumber());
}
}
public List<SelectOption> getOrders() {
List<SelectOption> options = new List<SelectOption>();
for (String key: this.ordersMap.keySet()) {
options.add(new SelectOption(key, key));
}
return options;
}
public PageReference show() {
String serviceUrl = 'https://grupomonico--devconfigu.lightning.force.com/lightning/r/Order/[SERVICE_ID]/view';
serviceUrl = serviceUrl.replace('[SERVICE_ID]', this.ordersMap.get(this.servicioSeleccionado));
PageReference retURL = new PageReference(serviceUrl);
retURL.setRedirect(true);
return retURL;
}
//Método del botón 'Volver a la Oportunidad'
public PageReference volver() {
String serviceUrl = BASE_URL2 + this.opp.Id;
PageReference retURL = new PageReference(serviceUrl);
retURL.setRedirect(true);
return retURL;
}
//Método temporal, para borrar
public List<OrderItem> getProductosAnadidos(){
system.debug('método getProductosAnadidos, this.servicioSeleccionado: ' + this.servicioSeleccionado);
system.debug('método getProductosAnadidos, this.ordersMap.get(this.servicioSeleccionado): ' + this.ordersMap.get(this.servicioSeleccionado));
this.listaProductos = [SELECT Id, Product2.Name, UnitPrice, Quantity, TotalPrice, IVA__c, Precio_Total_con_IVA__c FROM OrderItem
WHERE OrderId =: this.ordersMap.get(this.servicioSeleccionado)];
return listaProductos;
}
}
System.debug
statements show? DoesprAux
have a value forPricebookEntryId
?