-
ChatterFeed
-
0Best Answers
-
0Likes Received
-
0Likes Given
-
2Questions
-
2Replies
Send a PDF File through HTTP Callout
I'm going to show to my users a Screen flow where they can create a case with a PDF related to the case using the "File upload" flow component.
When the case is created i'm going to use an Invocable action to send the case information like caseNumber, caseReason and the related PDF file to an endpoint of an external system (django framework).
This is what im doing:
Any thoughts?
When the case is created i'm going to use an Invocable action to send the case information like caseNumber, caseReason and the related PDF file to an endpoint of an external system (django framework).
This is what im doing:
public with sharing class CrearComentarioVM { @invocableMethod(label='Crear Comentario en VM') public static list<ResultadoEndpoint> crearComentario(list<DatosRecibidosFlow> comentarioCreado) { //find the file ContentVersion cv = [SELECT VersionData FROM ContentVersion WHERE Id =: comentarioCreado[0].contentVersion WITH SECURITY_ENFORCED LIMIT 1]; blob pdfBlob = cv.VersionData; String encode64 = EncodingUtil.base64Encode(pdfBlob); //request body BodyJson body = new BodyJson(); for(DatosRecibidosFlow d : comentarioCreado){ body.archivo = encode64; body.ticket_salesforce_id = d.ticket_salesforce_id; body.accion = d.accion; body.descripcion = d.descripcion; body.salesforce_id = d.salesforce_id; } //request HttpRequest request = new HttpRequest(); request.setMethod('POST'); request.setEndpoint('callout:NamedVM/tickets/api/crear-seguimiento/'); request.setHeader('Accept','application/json'); request.setHeader('Content-type','application/json;charset=UTF-8'); request.setBody(JSON.serialize(body)); System.debug(request); System.debug(request.getBody()); //send request Http http = new Http(); HttpResponse response = http.send(request); //handle response if (response.getStatusCode() == 201) { System.debug('Response CodeStatus: ' + response.getStatusCode()); String responseBody = response.getBody(); RespuestaCrearComentarioVM ticket = RespuestaCrearComentarioVM.parse(responseBody); ResultadoEndpoint r = new ResultadoEndpoint(); r.idVM = ticket.vm_id; r.responseCode = response.getStatusCode(); list<ResultadoEndpoint> regresarRespuesta = new list<ResultadoEndpoint>(); regresarRespuesta.add(r); return regresarRespuesta; }else { System.debug('Response CodeStatus: ' + response.getStatusCode()+ ' response '+response.getStatus()); resultadoEndpoint r = new resultadoEndpoint(); r.responseCode = response.getStatusCode(); r.idVM = 0; list<resultadoEndpoint> regresarRespuesta = new list<resultadoEndpoint>(); regresarRespuesta.add(r); return regresarRespuesta; } } //inner class for JSON Body to VM public class BodyJson{ public String ticket_salesforce_id; public String accion; public String descripcion; public String salesforce_id; public String archivo; } //inner class for handle VM response public class ResultadoEndpoint{ @InvocableVariable(label='El ID Generado por el VM') public Integer idVM; @InvocableVariable(label='La respuesta del Endpoint') public Integer responseCode; } //inner class to handle input flow data public class DatosRecibidosFlow{ @InvocableVariable(label='El ID SF ContentVersion') public Id contentVersion; @InvocableVariable(label='El ID SF del Caso relacionado') public String ticket_salesforce_id; @InvocableVariable(label='El valor de AccionVM') public String accion; @InvocableVariable(label='El comentario escrito') public String descripcion; @InvocableVariable(label='El ID SF del Comentario creado') public String salesforce_id; } }
Any thoughts?
- Arturo Alamilla
- July 25, 2023
- Like
- 0
Batch Class Test to Production problem.
Hello everybody.
I'm a new salesforce developer, and i'm facin my first real world problem in my company.
We have a custom object named "Solicitudes__c", is the detail side of a master relationship of another custom object.
I was asked to calculate the time between stages (Picklist field named "Etapas_de_solicitud__c" with 10 values).
My solution is use History object records to calculate the first date to enter one stage, and the last day touching that same stage for every stage. I had to create some sample records and move them through all stages.
Later i came out with this apex class:
Then i came out with an batch apex class:
And create a Test class:
The problem is that when i'm trying to validate in production i see this problem: "System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.
Stack Trace: External entry point"
Any suggestions?
I'm a new salesforce developer, and i'm facin my first real world problem in my company.
We have a custom object named "Solicitudes__c", is the detail side of a master relationship of another custom object.
I was asked to calculate the time between stages (Picklist field named "Etapas_de_solicitud__c" with 10 values).
My solution is use History object records to calculate the first date to enter one stage, and the last day touching that same stage for every stage. I had to create some sample records and move them through all stages.
Later i came out with this apex class:
public with sharing class SolicitudesTiempos { public static void tiempos(List<Solicitudes__c> solicitudes) { //transform the List to Set of Ids set<id> solicitudesIds = new set<Id>(); for(solicitudes__c s : solicitudes){ solicitudesIds.add(s.id); } //list used to update the Solicitudes__c records lateer List<Solicitudes__c> solicitudesActualizar = new List<Solicitudes__c>(); //gather all Solicitudes__History records. list<Solicitudes__History> historialBuscado = [SELECT ParentId, NewValue, OldValue, CreatedDate FROM Solicitudes__History WHERE ParentId =: solicitudesIds AND Field = 'Etapas_de_Solicitud__c' WITH SECURITY_ENFORCED ORDER BY CreatedDate ASC]; // lists to store the history changes, accordingly. list<Solicitudes__History> historialCotizacion = new list<Solicitudes__History>(); list<Solicitudes__History> historialAceptacion = new list<Solicitudes__History>(); list<Solicitudes__History> historialPreanalisis = new list<Solicitudes__History>(); list<Solicitudes__History> historialDocumentos = new list<Solicitudes__History>(); list<Solicitudes__History> historialCarga = new list<Solicitudes__History>(); list<Solicitudes__History> historialPendienteAnalizar = new list<Solicitudes__History>(); list<Solicitudes__History> historialComite = new list<Solicitudes__History>(); list<Solicitudes__History> historialCondicionada = new list<Solicitudes__History>(); list<Solicitudes__History> historialAutorizada = new list<Solicitudes__History>(); list<Solicitudes__History> historialPendientedeFirma = new list<Solicitudes__History>(); // loop throughout all solicitudes__history to store the appropiate history record to a list. for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Cotización' || s.OldValue == 'Cotización'){ historialCotizacion.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Aceptación' || s.OldValue == 'Aceptación'){ historialAceptacion.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Preanálisis' || s.OldValue == 'Preanálisis'){ historialPreanalisis.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Documentos' || s.OldValue == 'Documentos'){ historialDocumentos.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Aviso a sebas' || s.OldValue == 'Aviso a sebas'){ historialCarga.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'pendiente de analizar' || s.OldValue == 'pendiente de analizar'){ historialPendienteAnalizar.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'comite' || s.OldValue == 'comite'){ historialComite.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'condicionado' || s.OldValue == 'condicionado'){ historialCondicionada.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'autorizada' || s.OldValue == 'autorizada'){ historialAutorizada.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'pendiente de firma' || s.OldValue == 'pendiente de firma'){ historialPendientedeFirma.add(s); } } // loop to calcule every Solicitudes__c record time on each stage. for(Id s : solicitudesIds){ Decimal tiempoCotizacion = SolicitudesTiempos.calcularTiempo(historialCotizacion, s); Decimal tiempoAceptacion = SolicitudesTiempos.calcularTiempo(historialAceptacion, s); Decimal tiempoPreanalisis = SolicitudesTiempos.calcularTiempo(historialPreanalisis, s); Decimal tiempoDocumentos = SolicitudesTiempos.calcularTiempo(historialDocumentos, s); Decimal tiempoCarga = SolicitudesTiempos.calcularTiempo(historialCarga, s); Decimal tiempoPendienteAnalizar = SolicitudesTiempos.calcularTiempo(historialPendienteAnalizar, s); Decimal tiempoComite = SolicitudesTiempos.calcularTiempo(historialComite, s); Decimal tiempoCondicionado = SolicitudesTiempos.calcularTiempo(historialCondicionada, s); Decimal tiempoAutorizada = SolicitudesTiempos.calcularTiempo(historialAutorizada, s); Decimal tiempoPendienteFirma = SolicitudesTiempos.calcularTiempo(historialPendientedeFirma, s); //store each calculation to the record's field and add it to a collection to update later. Solicitudes__c solicitud = new Solicitudes__c(Id = s, Tiempo_cotizacion__c=tiempoCotizacion, Tiempo_Aceptacion__c=tiempoAceptacion, Tiempo_preanalisis__c=tiempoPreanalisis, Tiempo_Documentos__c=tiempoDocumentos, Tiempo_Carga__c=tiempoCarga, Tiempo_Por_analizar__c=tiempoPendienteAnalizar, Tiempo_Comite__c=tiempoComite, Tiempo_Condicionada__c=tiempoCondicionado, Tiempo_Autorizada__c=tiempoAutorizada, Tiempo_Pendiente_Firma__c=tiempoPendienteFirma); //add the new record to a collection to update later. solicitudesActualizar.add(solicitud); } //update the records update solicitudesActualizar; } //method to calculate time between stages. private static Decimal calcularTiempo (list<Solicitudes__History> historial, Id solicitudId){ if(historial.size()>0 && historial != null){ dateTime date1; dateTime date2; Decimal minutos; for(Solicitudes__History hist : historial){ if(hist.ParentId == solicitudId && date1 == null){ date1 = hist.CreatedDate; }else if(hist.ParentId == solicitudId && date1 != null){ date2 = hist.CreatedDate; } } if(date1 != null && date2 != null){ Long firstDate = date1.getTime(); Long finalDate = date2.getTime(); Decimal segundos = (finalDate-firstDate)/1000; minutos = segundos/60; return minutos; }else{ return 0.00; } }else{ return 0.00; } } }
Then i came out with an batch apex class:
public class SolicitudesTiemposBatch implements Database.Batchable<SObject> { public Database.QueryLocator start(Database.BatchableContext bc) { String query = 'SELECT Id FROM Solicitudes__c '+ 'WHERE CreatedDate >= 2022-01-01T00:00:00Z '+ 'ORDER BY CreatedDate ASC'; return DataBase.getQueryLocator(query); } public void execute(Database.BatchableContext bc, List<Solicitudes__c> scope){ SolicitudesTiempos.tiempos(scope); } public void finish(database.BatchableContext bc){ } }
And create a Test class:
@isTest public class SolicitudesTiemposBatchTest { @isTest(SeeAllData=true) static void test(){ Test.startTest(); SolicitudesTiemposBatch solicitudesBatch = new SolicitudesTiemposBatch(); Database.executeBatch(solicitudesBatch, 200); Test.stopTest(); System.assertEquals(199,[SELECT count() FROM Solicitudes__C], '199 solicitudes'); } }And i get enough coverage to deploy production.
The problem is that when i'm trying to validate in production i see this problem: "System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.
Stack Trace: External entry point"
Any suggestions?
- Arturo Alamilla
- May 18, 2023
- Like
- 0
Send a PDF File through HTTP Callout
I'm going to show to my users a Screen flow where they can create a case with a PDF related to the case using the "File upload" flow component.
When the case is created i'm going to use an Invocable action to send the case information like caseNumber, caseReason and the related PDF file to an endpoint of an external system (django framework).
This is what im doing:
Any thoughts?
When the case is created i'm going to use an Invocable action to send the case information like caseNumber, caseReason and the related PDF file to an endpoint of an external system (django framework).
This is what im doing:
public with sharing class CrearComentarioVM { @invocableMethod(label='Crear Comentario en VM') public static list<ResultadoEndpoint> crearComentario(list<DatosRecibidosFlow> comentarioCreado) { //find the file ContentVersion cv = [SELECT VersionData FROM ContentVersion WHERE Id =: comentarioCreado[0].contentVersion WITH SECURITY_ENFORCED LIMIT 1]; blob pdfBlob = cv.VersionData; String encode64 = EncodingUtil.base64Encode(pdfBlob); //request body BodyJson body = new BodyJson(); for(DatosRecibidosFlow d : comentarioCreado){ body.archivo = encode64; body.ticket_salesforce_id = d.ticket_salesforce_id; body.accion = d.accion; body.descripcion = d.descripcion; body.salesforce_id = d.salesforce_id; } //request HttpRequest request = new HttpRequest(); request.setMethod('POST'); request.setEndpoint('callout:NamedVM/tickets/api/crear-seguimiento/'); request.setHeader('Accept','application/json'); request.setHeader('Content-type','application/json;charset=UTF-8'); request.setBody(JSON.serialize(body)); System.debug(request); System.debug(request.getBody()); //send request Http http = new Http(); HttpResponse response = http.send(request); //handle response if (response.getStatusCode() == 201) { System.debug('Response CodeStatus: ' + response.getStatusCode()); String responseBody = response.getBody(); RespuestaCrearComentarioVM ticket = RespuestaCrearComentarioVM.parse(responseBody); ResultadoEndpoint r = new ResultadoEndpoint(); r.idVM = ticket.vm_id; r.responseCode = response.getStatusCode(); list<ResultadoEndpoint> regresarRespuesta = new list<ResultadoEndpoint>(); regresarRespuesta.add(r); return regresarRespuesta; }else { System.debug('Response CodeStatus: ' + response.getStatusCode()+ ' response '+response.getStatus()); resultadoEndpoint r = new resultadoEndpoint(); r.responseCode = response.getStatusCode(); r.idVM = 0; list<resultadoEndpoint> regresarRespuesta = new list<resultadoEndpoint>(); regresarRespuesta.add(r); return regresarRespuesta; } } //inner class for JSON Body to VM public class BodyJson{ public String ticket_salesforce_id; public String accion; public String descripcion; public String salesforce_id; public String archivo; } //inner class for handle VM response public class ResultadoEndpoint{ @InvocableVariable(label='El ID Generado por el VM') public Integer idVM; @InvocableVariable(label='La respuesta del Endpoint') public Integer responseCode; } //inner class to handle input flow data public class DatosRecibidosFlow{ @InvocableVariable(label='El ID SF ContentVersion') public Id contentVersion; @InvocableVariable(label='El ID SF del Caso relacionado') public String ticket_salesforce_id; @InvocableVariable(label='El valor de AccionVM') public String accion; @InvocableVariable(label='El comentario escrito') public String descripcion; @InvocableVariable(label='El ID SF del Comentario creado') public String salesforce_id; } }
Any thoughts?
- Arturo Alamilla
- July 25, 2023
- Like
- 0
Batch Class Test to Production problem.
Hello everybody.
I'm a new salesforce developer, and i'm facin my first real world problem in my company.
We have a custom object named "Solicitudes__c", is the detail side of a master relationship of another custom object.
I was asked to calculate the time between stages (Picklist field named "Etapas_de_solicitud__c" with 10 values).
My solution is use History object records to calculate the first date to enter one stage, and the last day touching that same stage for every stage. I had to create some sample records and move them through all stages.
Later i came out with this apex class:
Then i came out with an batch apex class:
And create a Test class:
The problem is that when i'm trying to validate in production i see this problem: "System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.
Stack Trace: External entry point"
Any suggestions?
I'm a new salesforce developer, and i'm facin my first real world problem in my company.
We have a custom object named "Solicitudes__c", is the detail side of a master relationship of another custom object.
I was asked to calculate the time between stages (Picklist field named "Etapas_de_solicitud__c" with 10 values).
My solution is use History object records to calculate the first date to enter one stage, and the last day touching that same stage for every stage. I had to create some sample records and move them through all stages.
Later i came out with this apex class:
public with sharing class SolicitudesTiempos { public static void tiempos(List<Solicitudes__c> solicitudes) { //transform the List to Set of Ids set<id> solicitudesIds = new set<Id>(); for(solicitudes__c s : solicitudes){ solicitudesIds.add(s.id); } //list used to update the Solicitudes__c records lateer List<Solicitudes__c> solicitudesActualizar = new List<Solicitudes__c>(); //gather all Solicitudes__History records. list<Solicitudes__History> historialBuscado = [SELECT ParentId, NewValue, OldValue, CreatedDate FROM Solicitudes__History WHERE ParentId =: solicitudesIds AND Field = 'Etapas_de_Solicitud__c' WITH SECURITY_ENFORCED ORDER BY CreatedDate ASC]; // lists to store the history changes, accordingly. list<Solicitudes__History> historialCotizacion = new list<Solicitudes__History>(); list<Solicitudes__History> historialAceptacion = new list<Solicitudes__History>(); list<Solicitudes__History> historialPreanalisis = new list<Solicitudes__History>(); list<Solicitudes__History> historialDocumentos = new list<Solicitudes__History>(); list<Solicitudes__History> historialCarga = new list<Solicitudes__History>(); list<Solicitudes__History> historialPendienteAnalizar = new list<Solicitudes__History>(); list<Solicitudes__History> historialComite = new list<Solicitudes__History>(); list<Solicitudes__History> historialCondicionada = new list<Solicitudes__History>(); list<Solicitudes__History> historialAutorizada = new list<Solicitudes__History>(); list<Solicitudes__History> historialPendientedeFirma = new list<Solicitudes__History>(); // loop throughout all solicitudes__history to store the appropiate history record to a list. for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Cotización' || s.OldValue == 'Cotización'){ historialCotizacion.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Aceptación' || s.OldValue == 'Aceptación'){ historialAceptacion.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Preanálisis' || s.OldValue == 'Preanálisis'){ historialPreanalisis.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Documentos' || s.OldValue == 'Documentos'){ historialDocumentos.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'Aviso a sebas' || s.OldValue == 'Aviso a sebas'){ historialCarga.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'pendiente de analizar' || s.OldValue == 'pendiente de analizar'){ historialPendienteAnalizar.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'comite' || s.OldValue == 'comite'){ historialComite.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'condicionado' || s.OldValue == 'condicionado'){ historialCondicionada.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'autorizada' || s.OldValue == 'autorizada'){ historialAutorizada.add(s); } } for(Solicitudes__History s : historialBuscado){ if(s.NewValue == 'pendiente de firma' || s.OldValue == 'pendiente de firma'){ historialPendientedeFirma.add(s); } } // loop to calcule every Solicitudes__c record time on each stage. for(Id s : solicitudesIds){ Decimal tiempoCotizacion = SolicitudesTiempos.calcularTiempo(historialCotizacion, s); Decimal tiempoAceptacion = SolicitudesTiempos.calcularTiempo(historialAceptacion, s); Decimal tiempoPreanalisis = SolicitudesTiempos.calcularTiempo(historialPreanalisis, s); Decimal tiempoDocumentos = SolicitudesTiempos.calcularTiempo(historialDocumentos, s); Decimal tiempoCarga = SolicitudesTiempos.calcularTiempo(historialCarga, s); Decimal tiempoPendienteAnalizar = SolicitudesTiempos.calcularTiempo(historialPendienteAnalizar, s); Decimal tiempoComite = SolicitudesTiempos.calcularTiempo(historialComite, s); Decimal tiempoCondicionado = SolicitudesTiempos.calcularTiempo(historialCondicionada, s); Decimal tiempoAutorizada = SolicitudesTiempos.calcularTiempo(historialAutorizada, s); Decimal tiempoPendienteFirma = SolicitudesTiempos.calcularTiempo(historialPendientedeFirma, s); //store each calculation to the record's field and add it to a collection to update later. Solicitudes__c solicitud = new Solicitudes__c(Id = s, Tiempo_cotizacion__c=tiempoCotizacion, Tiempo_Aceptacion__c=tiempoAceptacion, Tiempo_preanalisis__c=tiempoPreanalisis, Tiempo_Documentos__c=tiempoDocumentos, Tiempo_Carga__c=tiempoCarga, Tiempo_Por_analizar__c=tiempoPendienteAnalizar, Tiempo_Comite__c=tiempoComite, Tiempo_Condicionada__c=tiempoCondicionado, Tiempo_Autorizada__c=tiempoAutorizada, Tiempo_Pendiente_Firma__c=tiempoPendienteFirma); //add the new record to a collection to update later. solicitudesActualizar.add(solicitud); } //update the records update solicitudesActualizar; } //method to calculate time between stages. private static Decimal calcularTiempo (list<Solicitudes__History> historial, Id solicitudId){ if(historial.size()>0 && historial != null){ dateTime date1; dateTime date2; Decimal minutos; for(Solicitudes__History hist : historial){ if(hist.ParentId == solicitudId && date1 == null){ date1 = hist.CreatedDate; }else if(hist.ParentId == solicitudId && date1 != null){ date2 = hist.CreatedDate; } } if(date1 != null && date2 != null){ Long firstDate = date1.getTime(); Long finalDate = date2.getTime(); Decimal segundos = (finalDate-firstDate)/1000; minutos = segundos/60; return minutos; }else{ return 0.00; } }else{ return 0.00; } } }
Then i came out with an batch apex class:
public class SolicitudesTiemposBatch implements Database.Batchable<SObject> { public Database.QueryLocator start(Database.BatchableContext bc) { String query = 'SELECT Id FROM Solicitudes__c '+ 'WHERE CreatedDate >= 2022-01-01T00:00:00Z '+ 'ORDER BY CreatedDate ASC'; return DataBase.getQueryLocator(query); } public void execute(Database.BatchableContext bc, List<Solicitudes__c> scope){ SolicitudesTiempos.tiempos(scope); } public void finish(database.BatchableContext bc){ } }
And create a Test class:
@isTest public class SolicitudesTiemposBatchTest { @isTest(SeeAllData=true) static void test(){ Test.startTest(); SolicitudesTiemposBatch solicitudesBatch = new SolicitudesTiemposBatch(); Database.executeBatch(solicitudesBatch, 200); Test.stopTest(); System.assertEquals(199,[SELECT count() FROM Solicitudes__C], '199 solicitudes'); } }And i get enough coverage to deploy production.
The problem is that when i'm trying to validate in production i see this problem: "System.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.
Stack Trace: External entry point"
Any suggestions?
- Arturo Alamilla
- May 18, 2023
- Like
- 0