1

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

  1. obtenerProductos() shows records of PriceBookEntry
  2. insertarProductos() 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;
    }
}
  • What do your System.debug statements show? Does prAux have a value for PricebookEntryId? – Kris Goncalves Jan 24 at 12:47
  • I think I found the problem. I found that order has a Pricebook2Id field that need to be populate to create OrderItem records linked to it. – Davidenserio Jan 25 at 8:42
  • You can answer your question and accept it as the answer to help others looking at this. – Kris Goncalves Jan 25 at 14:50
  • thanks for your help Kris – Davidenserio Jan 27 at 6:57
1

I think I found the problem. I found that order has a Pricebook2Id field that need to be populate to create OrderItem records linked to it.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.