1

I'm trying to rewrite a formula I made in Process Builder and modify it to use on trigger. I did something similar to what I have in the process builder, but the account is not working as it should in the apex. (obviously I did something wrong, but I don't know what). First I will paste my trigger and then the formula on process builder.

trigger Trigger_CalculaBH_Estimativa on BMCServiceDesk__Incident__c (before update) {

for(BMCServiceDesk__Incident__c BMC_inc: Trigger.new){
    Try{
        If (BMC_inc.BMCServiceDesk__Status_ID__c == 'OPENED' && BMC_inc.BH_Estimativa__c <> NULL){
            //BMCServiceDesk__ConsoleLayoutDetail__c BMC_Layout = [SELECT Id,Name FROM BMCServiceDesk__ConsoleLayoutDetail__c WHERE name = 'Requisição - Banco de Horas'];
            
            // Verifica Ativo
            BMC_inc.Franquia_Restante_String__c = [SELECT Id,Name,Franquia_Restante_String__c
                                                   FROM BMCServiceDesk__BMC_BaseElement__c
                                                   WHERE Id =: BMC_inc.BMCServiceDesk__FKBMC_BaseElement__c limit 1][0].Franquia_Restante_String__c;
            
            String Estimativa = BMC_inc.BH_Estimativa__c; //string as time domain HH:MM (to test 00:30)
            String FranquiaRestanteIC = BMC_inc.Franquia_Restante_String__c; //String as time domain HH:MM (to test 50:00)
            
            List<String> FranquiaPartes = FranquiaRestanteIC.split(':');
            Integer FranquiaHrs = Integer.valueOf(FranquiaPartes[0]);
            Integer FranquiaMin = Integer.valueOf(FranquiaPartes[1]);
            //Decimal Franquia_Decimal = Decimal.valueOf(FranquiaPartes[0]) + (Decimal.valueOf(FranquiaPartes[1]) / 60.0); 
            
            List<String> EstimativaPartes = Estimativa.split(':');
            Integer EstimativaHrs = Integer.valueOf(EstimativaPartes[0]);
            Integer EstimativaMin = Integer.valueOf(EstimativaPartes[1]);                
            //Decimal Estimativa_Decimal = Decimal.valueOf(EstimativaPartes[0]) + (Decimal.valueOf(EstimativaPartes[1]) / 60.0); 
            
            Decimal FranquiaRestanteDom1 = Math.floor((Math.floor(FranquiaHrs) + (Math.mod(FranquiaMin, 1)*10/6))-Math.floor(EstimativaHrs)-(Math.mod(EstimativaMin, 1)*10/6));
            Decimal FranquiaRestanteDom2 = Math.mod(((FranquiaHrs + (Math.mod(FranquiaMin, 1)*10/6))-EstimativaHrs-(Math.mod(EstimativaMin, 1)*10/6)),1)*6/10;
            
            //update number field
            BMC_inc.Franquia_Restante_Calculada__c = (FranquiaRestanteDom1+FranquiaRestanteDom2);
        }
    } catch (Exception e) {
        Trigger.new[0].addError(e.getMessage());
    }
}
}

PROCESS BUILDER (BELOW)

Understand that in this formula I have two String fields written as HH: MM (1) Franquia_Banco_de_Horas_Variavel__c (2) Estimated_use_of_Bank_of_Hours__c

After doing the calculations by subtracting (1) - (2), I put this result in a string field. So, If I have Franquia_Banco_de_Horas_Variavel__c = 50:00; Estimated_use_of_Bank_of_Hours__c = 1:30; Result should be 48:30

FLOOR((  (FLOOR(
         [BMCServiceDesk__Incident__c].Contrato_de_Banco_de_Horas__r.Franquia_Banco_de_Horas_Variavel__c
      ) + 
      (
         MOD(
            [BMCServiceDesk__Incident__c].Contrato_de_Banco_de_Horas__r.Franquia_Banco_de_Horas_Variavel__c, 1
         ) * 10/6
      )
    )  - 
 FLOOR([BMCServiceDesk__Incident__c].Estimativa_de_uso_do_Banco_de_Horas__c) - 
 (MOD([BMCServiceDesk__Incident__c].Estimativa_de_uso_do_Banco_de_Horas__c, 1) * 10/6))
 )
 +     
 (
 MOD((  (FLOOR([BMCServiceDesk__Incident__c].Contrato_de_Banco_de_Horas__r.Franquia_Banco_de_Horas_Variavel__c) + 
      (
         MOD(
            [BMCServiceDesk__Incident__c].Contrato_de_Banco_de_Horas__r.Franquia_Banco_de_Horas_Variavel__c, 1
         ) * 10/6
      )
    )  - 
 FLOOR([BMCServiceDesk__Incident__c].Estimativa_de_uso_do_Banco_de_Horas__c) - 
 (MOD([BMCServiceDesk__Incident__c].Estimativa_de_uso_do_Banco_de_Horas__c, 1) * 10/6)), 1) * 6/10
)
1
  • You have a soql query in a for loop which is going to cause you a lot of headaches down the road - unfortunately your trigger is going to look pretty different from the process builder Mar 23 at 18:19
1

There are a lot of things that could improve this trigger, and I advise you to look up some trigger frameworks.

Also my solution here doesn't help with the logic calculating dates and times - I'm really just about getting the SOQL out of the loop and getting you started.

First, you extract the id you are querying in a small pre-loop (sometimes you can avoid this, but not this time as you are not querying on the primary id of the trigger object)

Set<Id> baseElementIds = new Set<Id>();
for(BMCServiceDesk__Incident__c BMC_inc: Trigger.new){
    baseElementIds.add(BMC_inc.BMCServiceDesk__FKBMC_BaseElement__c);
}

Then you make the query based on your set of Ids:

Map<Id,BMCServiceDesk__Incident__c> baseElementById = new Map<Id,BMCServiceDesk__Incident__c>(
    [SELECT Id,Name,Franquia_Restante_String__c
     FROM BMCServiceDesk__BMC_BaseElement__c
     WHERE Id IN :baseElementIds]
);

Then you can proceed to your regular loop, sans the SOQL:

for(BMCServiceDesk__Incident__c BMC_inc: Trigger.new){

    //if we don't have a base element, go to next item in loop
    if (!baseElementById.containsKey(BMC_inc.BMCServiceDesk__FKBMC_BaseElement__c)){
      continue;
    }
    //ok, we have the string we want
    BMC_inc.Franquia_Restante_String__c =  baseElementById.get(BMC_inc.BMCServiceDesk__FKBMC_BaseElement__c);
    try{
        if (BMC_inc.BMCServiceDesk__Status_ID__c == 'OPENED' && BMC_inc.BH_Estimativa__c != NULL){
            
            String Estimativa = BMC_inc.BH_Estimativa__c; //string as time domain HH:MM (to test 00:30)
            String FranquiaRestanteIC = BMC_inc.Franquia_Restante_String__c; //String as time domain HH:MM (to test 50:00)
            
            List<String> FranquiaPartes = FranquiaRestanteIC.split(':');
            Integer FranquiaHrs = Integer.valueOf(FranquiaPartes[0]);
            Integer FranquiaMin = Integer.valueOf(FranquiaPartes[1]);
            //Decimal Franquia_Decimal = Decimal.valueOf(FranquiaPartes[0]) + (Decimal.valueOf(FranquiaPartes[1]) / 60.0); 
            
            List<String> EstimativaPartes = Estimativa.split(':');
            Integer EstimativaHrs = Integer.valueOf(EstimativaPartes[0]);
            Integer EstimativaMin = Integer.valueOf(EstimativaPartes[1]);                
            //Decimal Estimativa_Decimal = Decimal.valueOf(EstimativaPartes[0]) + (Decimal.valueOf(EstimativaPartes[1]) / 60.0); 
            
            Decimal FranquiaRestanteDom1 = Math.floor((Math.floor(FranquiaHrs) + (Math.mod(FranquiaMin, 1)*10/6))-Math.floor(EstimativaHrs)-(Math.mod(EstimativaMin, 1)*10/6));
            Decimal FranquiaRestanteDom2 = Math.mod(((FranquiaHrs + (Math.mod(FranquiaMin, 1)*10/6))-EstimativaHrs-(Math.mod(EstimativaMin, 1)*10/6)),1)*6/10;
            
            //update number field
            BMC_inc.Franquia_Restante_Calculada__c = (FranquiaRestanteDom1+FranquiaRestanteDom2);
        }
    } catch (Exception e) {
        BMC_inc.addError(e.getMessage());
    }
}

That should get you a good ways along.

2
  • Trigger.new[0].addError(e.getMessage()); should be BMC_inc.addError(e.getMessage());. Otherwise you're putting the error on the wrong record, and may actually cause a TOO_MANY_RETRIES error.
    – sfdcfox
    Mar 23 at 18:58
  • Good catch - I'll update my code Mar 23 at 19:00

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .