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
Cesar Ramirez Vasquez005391619375684564Cesar Ramirez Vasquez005391619375684564 

Trigger not firing before insert ?? HELP

Hi i created a trigger that checks before inserting a record of type Factura__c, if the master-relationship field exist, and if it dont the trigger create a new one with the value contained in the field Empresa_Cliente__c.
The master relationship is between Factura__c (custom object) and Account. But when i try to save a record the trigger doesnt fire and i keep receiving the salesforce validation error (Error: No matches found.) in that field. Any suggestions this is my trigger :

trigger insertAcc on Factura__c (before insert) {
System.debug(Logginglevel.ERROR , ' ::::::: Empresa Cliente :::::::::::::' + trigger.New[0].Empresa_Cliente__c) ; 
List<Account> a = [select name, CodigoNAF__c from account where CodigoNAF__c = :trigger.New[0].Empresa_Cliente__c];
System.debug(Logginglevel.ERROR , ' ::::::: List :::::::::::::' + a) ; 
if (a == null){
Account acc = new Account();
acc.Name = trigger.New[0].Compania__c;
acc.CodigoNAF__c = trigger.New[0].Empresa_Cliente__r.CodigoNAF__c;
insert (acc);

System.debug(Logginglevel.ERROR , ' ::::::: acc :::::::::::::' + acc) ;
}

}
Just for information CodigoNAF__c is a custom field i created within Account object.
Carolina Ruiz MedinaCarolina Ruiz Medina
Hola Cesar,

He intentado entender un poco lo que deseabas hacer en tu trigger. Espero que el codigo que añado te sirva de ayuda :) 

Creo que es esto lo que necesitas:

trigger insertAcc on Factura__c (before insert) {



if(Trigger.isBefore)
{
    if(Trigger.isInsert)
    {
    
         /*
            1.-  I'm guessing that you would like to do this code in isInsert as you are using Trigger.New
            2.-  I'm gessing for this line of code that Empresa_cliente is a Lookup to an object called Empresa_Cliente
            and you would like to access to a field that is in it called CodigoNAF that after that you need to use
            to get the accounts that match the values of this
            trigger.New[0].Empresa_Cliente__r.CodigoNAF__c;  
        */
        
        List<Factura__c> facturas = Trigger.new;
        
        List<Id> empresaIds = new List<Id> (); 
        Map<Id, String> facturaEmpresaCompanias = new Map<Id,String> ();
        for(Factura__c f: facturas)
        {
            // for later use at the time to create accounts
            /*Notice!!! -- I'm guessing that 1 Empresa will have only one Company, if the same Empresa has different
            companies then I won't do anything! I'll STOP
            May be you could like to make it the other way round , if there is no CodigoNAF then do nothing, Stop!
            you can change this behaviour if you wish*/
            if(f.Empresa_Cliente__c!=null)
            {
                empresaIds.add(f.Empresa_Cliente__c);
               if( !facturaEmpresaCompanias.containsKey(f.Empresa_Cliente__c))
                   facturaEmpresaCompanias.put(f.Empresa_Cliente__c, f.Compania__c);
               else
               {
                  if(facturaEmpresaCompanias.containsKey(f.Empresa_Cliente__c) && facturaEmpresaCompanias.get(f.Empresa_Cliente__c)!= f.Compania__c)
                       throw new FacturaException('There is another Factura that contains a Empresa_Cliente with different Compania and that is not allowed. Lo sentimos. ');
               }
            }
            
        }
        
        List<Empresa_Cliente__c> empresas = [Select Id, CodigoNAF__c from Empresa_Cliente__c where Id IN : empresaIds];
        
        // Now I need to get the CodigoNAF__c for each empresa
        //I also need to set up each Compania with their CodigoNAF
        Map<String, String> companiaCodigoNAF = new Map<String, String> ();
       // Map<Id, String> empresasCodigos = new Map<Id, String> ();
        for(Empresa_Cliente__c e:empresas)
        {
            //empresasCodigos.put(e.Id,e.CodigoNAF__c);
            companiaCodigoNAF.put(facturaEmpresaCompanias.get(e.Id), e.CodigoNAF__c);
        }
        
        List<String> codigos = companiaCodigoNAF.values();
        
        List<Account> accounts = [select name, CodigoNAF__c from account where CodigoNAF__c IN :codigos];
       
        //throw new FacturaException('hola'+accounts);
        List<Account> newAccounts = new List<Account>();
       
       /* Now I create accounts for all the facturas?? that don't have account
       ( maybe you would like for all the codigos or for all the empresas.. that's for you to decide here and implement in the way you wish) 
       To have in count!!! OJO!!!
       if I create an account per each Factura, maybe you will have duplicate values
        then what I'll do is use Company, Codigo as map to check I don't create duplicate Accounts
       */
       if(accounts.isEmpty()) // accounts.isEmpty()
       {
           for(String compania: companiaCodigoNAF.keyset())
           {
              Account acc = new Account();
              acc.Name = compania;
              acc.CodigoNAF__c= companiaCodigoNAF.get(compania);
              newAccounts.add(acc);
           }
       }
       if(accounts.size() != codigos.size())
       {
           // you should also check which Codes have account Representation
       }
       
        insert newAccounts;

    } 
    else if(Trigger.isUpdate){}// you should do the same may be for Update? 
    else if(Trigger.isDelete) {}
}
else
{
    
}


public class FacturaException extends Exception {}


}

As you can see there are a lot of things that I was guessing only seen your code. This trigger that I implemented is bulkified in orde to process more than one Factura at the time. 
Please notice that the code is only a sample code, it is working in my org with the assumptions that I had after read your code.

I would recomend too to have a look to :
https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm
https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_qs_trigger.htm
https://developer.salesforce.com/page/Best_Practice%3A_Bulkify_Your_Code
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm

At the moment the trigger is creating an account when there is no accounts for the corresponding CogidosNAF. 

Hope it helps as template as least. 
If you have further queries let me know, I'll try to help.

Hasta pronto,
Carolina.
Cesar Ramirez Vasquez005391619375684564Cesar Ramirez Vasquez005391619375684564
Hola Carolina muchas gracias por tu respuesta ! Si entendiste todo casi exactamente como lo tengo; lo unico es que EmpresaCliente__c es el nombre del master-relationship en Factura__c con Account. El problema es que cuando trato manualmente de guardar una factura y en EmpresaCliente__c digito un Account que no existe me da error (Error: No matches found.) y no se ejecuta la accion por lo que el trigger no se dispara. Como puedo hacer para que el trigger se dispare aunque el codigo digitado en EmpresaCliente__c aun no exista en Accounts.
  De hecho esa es la funcionalidad que estoy tratando de buscar que si el valor digitado en EmpresaCliente__c no existe que se cree uno nuevo.
Espero tu respuesta ! Muchas Gracias !
Cesar Ramirez Vasquez005391619375684564Cesar Ramirez Vasquez005391619375684564
Oh vi que tenia varios errores en el trigger que postee arriva te adjunto una version actualizada:

trigger insertAcc on Factura__c (before insert) {
System.debug(Logginglevel.ERROR , ' ::::::: Empresa Cliente :::::::::::::' + trigger.New[0].Empresa_Cliente__c) ;
if(Trigger.isBefore)
  {
     if(Trigger.isInsert)
      {
   
List<Account> a = [select name, CodigoNAF__c from account where CodigoNAF__c = :trigger.New[0].Empresa_Cliente__c];
System.debug(Logginglevel.ERROR , ' ::::::: List :::::::::::::' + a) ; 
if (a == null){
Account acc = new Account();
acc.Name = trigger.New[0].Empresa_Cliente__c;
acc.CodigoNAF__c = trigger.New[0].Empresa_Cliente__c;
insert (acc);

System.debug(Logginglevel.ERROR , ' ::::::: acc :::::::::::::' + acc) ;
}

}


}
}

Carolina Ruiz MedinaCarolina Ruiz Medina
Hola Cesar,

Gracias. 

Varias cositas a tener en cuenta :) 
- Este trigger que me pones solamente funcionaría con la factura numero 1. Si hubiese mas facturas no las procesaria.
- Si haces un insert por cada Factura procesada, rapidamente te daras contra los gobernors limits.
Solucion a esto : Bulkification. El trigger que te pase usa mapas, hace 1 consulta para todas las facturas, y 1 insert para todas las facturas: https://developer.salesforce.com/page/Best_Practice%3A_Bulkify_Your_Code
- La consulta podria devolver mas de una cuenta
- Si las cuentas son menos que las empresa cliente que pasaria
- CodigoNAF que clase de campo es? Lookup? a que?
- IMPORTANTE Empresa_Cliente_c que clase de campo es? Es un master detail a Account? 
   Si es un Master detail a Account, eso significa que cada vez que crees una factura este campo debe tener valor. No puedes crear nuevos registros con este campo vacio.  : http://www.salesforce.com/us/developer/docs/api/Content/relationships_among_objects.htm
- Si lo que quieres es que se cree factura independientemente de que el campo se rellene o no debes usar Lookup field.
-  Si Empresa_Cliente_c es un master detail a Account guardara el Id de Account aunque en SF UI muestre el nombre, luego lo que puedes hacer para recoger las cuentas es [SELECT Id ,Name , CodigoNAF__c FROM Account where Id In :empresaClientes] siendo empresaClientes una lista de Ids que provienen de los campos Empresa_cliente de cada Factura.
- <<De hecho esa es la funcionalidad que estoy tratando de buscar que si el valor digitado en EmpresaCliente__c no existe que se cree uno nuevo.>> Como sabes que el valor digitado en EmpresaCliente no existe? No existe cuando la escoges en SF UI ? 
- Aparte de trigger puedes echarle un vistazillo a Workflows que quizas te sirvan: http://help.salesforce.com/apex/HTViewHelpDoc?id=creating_workflow_rules.htm

Espero que te sirva , ya me cuentas :)

Hasta pronto,
Carolina.


Carolina Ruiz MedinaCarolina Ruiz Medina
Re Hola :)

Acabo de ver tus preguntas, 
Parece que tu caso de negocio es :

Has implementado una UI ( VF + Controllador) para Factura. Esta factura tiene una Master- Detail a Account que se llama Empresa_Cliente. 

Si dicha Account  que se debe de guardar en Factura ( detail of Account) con CodigoNAF_c no existe se debe de crear.

Para ello, entonces antes de insertar la Factura debes comprobar que esa cuenta no existe -- eso lo debes hacer en tu controllador, y si no existe crearla en tu controllador.
una vez alli debes  creada la cuenta, te creas tu factura por codigo , como creo lo estas haciendo y luego lo mandas a base de datos. 
No necesitarias un trigger a no ser que quieras validar algo. 
Recuerda!
 - Governor limits :https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_gov_limits.htm
 - Bulkifica tu codigo 


Si lo que realmente quieres es que todo se haga en el trigger debes de cambiar tu campo a Lookup.

Ahora si que si creo que todo tiene mas sentido :) 

Ah! Echale un vistazo a este link, es sobre patrones de codigo te puede ayudar mucho a la hora de empezar a escibir codigo :) 
https://github.com/financialforcedev/fflib-apex-common


Hasta pronto,
Carolina.


Cesar Ramirez Vasquez005391619375684564Cesar Ramirez Vasquez005391619375684564
Hola Carolina, gracias de nuevo muy completa tu respuesta. Te comento el problema a fondo; en realidad cree un trigger porque usamos un software aparte en el cual facturamos y todos los dias en la noche con el dataloader y unas tareas programadas sincronizamos esas facturas y empresas con salesforce. El proiblema radica en que el software deja guardar codigos de compañias que no han sido creadas entonces cuando en la noche se ejecutan las tareas programadas muchas facturas no entran al sistema porque el Account al cual esta relacionadas no existe aun.

Entonces mi idea era hacer un trigger que checara si el Account existe y si no que creara uno nuevo y se lo asignara a la factura para que ninguna me rebote cuando haga la sincronizacion. El valor Empresa_Cliente__c (nombre del master-relationship en el objeto Factura__c) siempre tiene un valor nunca esta vacio per este valor apunta al codigo_NAF del Account; no se si me explico asi es esta mapeado en el dataloader Empresa_Cliente__c=Empresa_Cliente__r\:Codigo_NAF__c. Este campo es un master-detail porque ocupo los roll up summaries en varios reportes :( sino ya lo hubiera cambiado a lookup.

Gracias, espero tu respuesta !1