<< Clic para mostrar Tabla de Contenidos >> Cómo integrar Bizagi con Salesforce |
Introducción
La integración de Bizagi con un CRM como Salesforce, es soportada a través de más de una alternativa.
Esta sección presenta un ejemplo de cómo presentar en Bizagi todos los prospectos (leads) almacenados en Salesforce, mientras permite al mismo usuario crear un nuevo prospecto basado en la información ya ingresada en Bizagi:
Alternativas
Para algunos escenarios donde quiera que Bizagi se conecte a sus sistemas corporativos de CRM, ya sea para traer información (i.e., Prospectos, Cuentas, Oportunidades o Contactos) o para crear nuevos registros, usted cuenta con estas funcionalidades:
1. Conector de servicios Web de Bizagi
Le permite conectarse a servicios Web compatibles con SOAP sin necesidad de programar.
Para más información sobre el conector de servicios Web, consulte Invocar servicios externos desde Bizagi.
2. Librería de componentes de Bizagi
Le permite crear su propios componentes codificados y empaquetarlos en Bizagi, de tal forma que puede extender sus reglas de negocio usando dichos componentes directamente
Para más información sobre la funcionalidad de la Librería de Componentes de Bizagi, consulte Integrar APIs o código personalizado en Bizagi.
Aunque la opción preferida es usualmente el conector de servicios Web, para este artículo que involucra servicios de Salesforce, esta alternativa no es optima. Más adelante se describe cuándo es mejor usar cada una. |
API de Salesforce
Como Salesforce se ofrece como un servicio en la nube el cual tiene un API que puede ser accedido por Internet, se requiere el uso de un ID de sesión dinámica para invocar todos sus métodos (por razones de seguridad en la nube, para restringir invocaciones de sus servicios en una franja de tiempo en la cuál dicho ID de sesión es válido).
El API de Salesforce basado en SOA utiliza un endpoint de autenticación que está separado del endpoint de servicio, lo cual implica que la lógica detrás sigue un flujo similar al usado por aquellos basados en OAuth exchanges (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_login.htm).
Por lo tanto, utilizar el conector de Servicios Web no es óptimo ya que obtener un ID de sesión dinámico significa que necesita invocar primero el método de autenticación de Salesforce (a través de una autenticación con usuario, contraseña y un token de seguridad) para después, invocar el método deseado.
Para este ejemplo, el conector de servicios web puede resultar en tener que más de un llamado desde Bizagi a Salesforce y no se siguen las buenas prácticas del manejo de transacciones o de altos aspectos de seguridad cuando se manejan IDs de sesión.
Debido a lo anterior, en esta guía vamos a invocar Salesforce a través de su API de SOAP, pero a través de la librería de componentes.
Para esta funcionalidad, desarrollaremos un componente personalizado que maneje el ID de sesión y todos los aspectos relacionados con el mecanismo de autenticación, como se encuentra disponible en Salesforce.
Antes de empezar
Antes de empezar con la integración ilustrada por esta guía, asegúrese de tener una cuenta válida en Salesforce.
Cuando lo haga, observe que necesita otorgar acceso a su máquina, de tal forma que se permita usar su cuenta de Salesforce, como se requiere por las políticas de seguridad de Salesforce.
Usted puede autorizar dicho acceso a su cuenta de Salesforce y configurar un token de seguridad, directamente en Ajustes Personales (Personal settings) presentados en su portal de Salesforce (i.e., https://na22.salesforce.com/_ui/system/security/ResetApiTokenEdit?retURL=%2Fui%2Fsetup%2FSetup%3Fsetupid%3DPersonalInfo&setupid=ResetApiToken).
¿Qué necesita hacer?
Adicionalmente a los requisitos de Salesforce, la siguiente lista ilustra un esquema de pasos que necesitan ser llevados a cabo para integrarse con Salesforce:
1. Cree su propio componente que se conecte a Salesforce
Este paso se hace fuera de Bizagi, utilice el IDE de su elección, por ejemplo Visual Studio, para producir una librería (una dll para la plataforma).
2. Registre el componente en Bizagi Studio
En este paso, utilice Bizagi Studio para importar la librería en su proyecto de Bizagi.
3. Configure una regla de negocio que invoque el componente
En este paso, utilice los métodos en dicho componente, de tal forma que puede invocar Salesforce desde cualquier punto de sus procesos de Bizagi.
Para completar estos pasos, necesitará haber incluido en su modelo de datos de su proceso e interfaces de usuario, las definiciones apropiadas ya sea para enviar información a Salesforce o para guardar la entrante.
Ejemplo
Para ilustrar cómo integrarse con Salesforce, partiremos de tener el proceso de Peticiones, quejas y reclamos como el que se encuentra disponible en Bizagi Xchange (https://www.bizagi.com/es/plataforma/xchange).
El objetivo principal de este proceso es asignar responsabilidades y hacer un seguimiento a los comentarios ingresados ya sea en una petición, una queja, un reclamo o una sugerencia; para manejarlos acordemente en toda la organización.
Como ejemplo, asumiremos que las peticiones de entrada son estrictamente sugerencias:
1.La persona a cargo de analizar la sugerencia ("Solucionador del caso", asignado a la tarea Analizar sugerencia) debe poder escoger crear un nuevo prospecto con los datos del solicitante.
2.Bizagi presentará una tabla con los prospectos actuales en Salesforce para el Solucionador del caso para usarla como una referencia en tiempo real.
Una vez la sugerencia ha sido analizada y asumiendo que el solicitante debe ser creado como un nuevo prospecto, Bizagi persistirá esta información en Salesforce.
Con todo, en esta guía se ejecutarán estos 2 puntos de integración con Salesforce agregando la configuración a la plantilla de proceso existente en las actividades Enviar Respuesta y Analizar Sugerencia.
La actividad Enviar Respuesta será el punto de integración donde Bizagi traerá todos los prospectos desde Salesforce (i.e una lectura), mientras que la actividad Analizar Sugerenciay será el punto de integración donde Bizagi enviará el nuevo prospecto (i.e una escritura).
Para seguir los pasos presentados en esta sección y tener una aplicación completamente funcional de su lado, se le sugiere descargar e instalar la plantilla del proceso de Peticiones, Quejas y Reclamos desde Process Xchange. Para más información sobre esta plantilla de proceso y cómo puede ser descargada y utilizada sin costa, consulte Bizagi Process Xchange. |
Pasos
Los siguientes pasos y componentes son desarrollados como un ejemplo orientado a la plataforma.
1. Cree su propio componente que conecte con Salesforce
El primer paso antes de siquiera empezar a desarrollar el componente, es asegurarse de que ha preparado todo lo necesario para conectarse con Salesforce.
Adicionalmente, tener una cuenta y un token de seguridad como se describe antes en la sección Antes de empezar, también necesitará primero guardar la definición de dichos servicios haciéndolos disponibles para el API de SOAP de su cuenta de Salesforce.
El almacenado de la definición (el WSDL actual) se hace en su máquina local y debe ser almacenado por un Servidor Web de IIS en ejecución.
Esta guía se basa en el ejemplo provisto por Salesforce en https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_quickstart_steps.htm, aunque se realizaron algunos ajustes. Tenga en cuenta que Salesforce puede actualizar su documentación, su soporte del API o sus prácticas recomendadas en cualquier momento sin previo aviso. Para información sobre el API SOAP de Salesforce o mayor documentación sobre sus objetos y específicos, consulte https://developer.salesforce.com/page/Sample_SOAP_Messages. |
1.1 Localice el WSDL
Localice el WSDL iniciando sesión en el portal de Salesforce y después escribiendo API en el cuadro de búsqueda.
Dentro de los resultados de la búsqueda, busque la página Develop API:
1.2 Guarde el WSDL
Una vez la en la página API WSDL, descargue y guarde localmente el archivo WSDL generado por los Servicios Empresariales de Salesforce, utilizando la opción "guardar enlace como..." de su navegador:
Observe que este archivo debe tener la extensión .wsdl (además, el nombre completo para este archivo es "enterprise.wsdl").
1.3 Aloje el archivo en el IIS
Para hacer que el archivo esté disponible via web, guarde este archivo en la ruta local del inicio del IIS en C:\inetpub\wwwroot\.
La siguiente imagen muestra el archivo enterprise.wsdl almacenado en C:\inetpub\e wwwroot\LocalWS\:
1.4 Modifique el WSDL
Este paso es necesario para resolver un problema conocido que tiene Salesforce con respecto a sus definiciones WSDL.
Modifique el WSDL e incluya esta línea adicional:
<xsd:attribute name="tmp" type="xsd:string" />
dentro del la definición del elemento ListViewRecord.
Esto significa que debe cambiar la definición original:
<complexType name="ListViewRecord">
<sequence>
<element name="columns" type="tns:ListViewRecordColumn" maxOccurs="unbounded"/>
</sequence>
</complexType>
Por esta:
<complexType name="ListViewRecord">
<sequence>
<element name="columns" type="tns:ListViewRecordColumn" maxOccurs="unbounded"/>
</sequence>
<xsd:attribute name="tmp" type="xsd:string" />
</complexType>
1.5 Verifique que el WSDL puede ser accedido desde web
En este punto, usted debe poder acceder a este WSDL a través del protocolo HTTP.
Use http://localhost/[RUTA_DE_SU_WSDL] desde el navegador de su elección, para verificar que el WSDL es accesible por web y que su estructura es un XML consistente después de haberlo modificado.
Como se especificó anteriormente, la siguiente imagen usa la carpeta LocalWS y por lo tanto, tiene el WSDL accesible en http://localhost/LocalWS/enterprise.wsdl:
1.6 Cree un nuevo proyecto de Visual Studio
Ahora que tiene todo lo necesario en Saleforce, proceda a crear el componente.
Para esto, cree una nuevo proyecto de clase de librería en la versión 4.0 del framework de .NET:
1.7 Agregue la referencia al servicio al WSDL
Como se describe en la documentación de Salesforce, agregue una referencia al servicio (service referenc) que apuntan al WSDL alojado en el IIS:
Observe que el namespace de la referencia del servicio ara este ejemplo, se llama sforce2.
Aunque usted puede darle que nombre que desee, tenga en cuenta que nombre sforce2 será referenciado en pasos adicionales en esta guía.
1.8 Agregue otras librerías
Incluya otras librerías necesarias, en especial la librería System.ServiceModel:
1.9 Ajuste los parámetros del buffer
Todos los proyectos .NET utilizan por defecto unos parámetros de buffer configurados con valores bajos, dirigidos a transacciones de pequeñas cantidades de datos.
Asegúrese de ajustar dichos parámetros de tal forma que pueda permitirle a su aplicación transmitir una cantidad mayor de datos (debe ajustarlos de manera medible para un entorno de producción, ya que estos ajustes son parte de las medidas de seguridad que mitigan los ataques de denegación de servicio).
Debido a que el ejemplo de Salesforce va a buscar todas los prospectos (aunque un aproximado de 22 registros), pero junto con una gran cantidad de información de metadatos, proceda a modificar los parámetros de la memoria: maxBufferSize, maxReceivedMessageSize y maxBufferPoolSize.
Para esto, edite el elemento binding que se encuentra directamente en el archivo app.config de su proyecto, de tal forma que utilice los siguientes valores (o como medidas de acuerdo a la información esperada que usted va a manejar):
<binding name="SoapBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="524288">
<security mode="Transport" />
</binding>
1.10 Codifique el componente
Incluya el código para Class.cs de su proyecto de clase de librería.
Usted puede usar el siguiente código basado en la documentación de inicio rápido de Salesforce(https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_quickstart_steps_walk_through_code.htm):
![]() | Ver código aquí using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; using System.Xml.Linq; using MySalesforceLibrary.sforce2; namespace MySalesforceLibrary { public class Class1 { private static SoapClient loginClient; private static SoapClient client; private static SessionHeader header; private static EndpointAddress endpoint; #region public Methods #region Tests everything this component supports public void Test(String userName, String password, String securityToken, String objectType, String firstName, String lastName, String company, String email) { if (login(userName, password, securityToken)) { describeGlobals(objectType); queryLeads(); createLead(firstName, lastName, company, email); logout(); } } #endregion #region Tests the connection and fetching metadata public void Connect(String userName, String password, String securityToken, String objectType) { if (login(userName, password, securityToken)) { describeGlobals(objectType); logout(); } } #endregion #region Runs a query which fetches all leads public String Query(String userName, String password, String securityToken) { String results = "<ClaimandComplaintRequest>"; if (login(userName, password, securityToken)) { results += queryLeads(); logout(); } return results + "</ClaimandComplaintRequest>"; } #endregion #region Creates a Lead public String Create(String userName, String password, String securityToken, String firstName, String lastName, String company, String email) { String confirmationId = "0"; if (login(userName, password, securityToken)) { confirmationId = createLead(firstName, lastName, company, email); logout(); } return confirmationId; } #endregion #endregion #region private Methods #region login private bool login(String userName, String password, String securityToken) { // Create a SoapClient specifically for logging in loginClient = new SoapClient(); LoginResult lr = null; try { Console.WriteLine("\nLogging in...\n"); lr = loginClient.login(null, userName, password + securityToken); } catch (Exception e) { Console.WriteLine("An unexpected error has occurred: " + e.Message + "\nStack trace: " + e.StackTrace); } // Check if the password has expired if (lr.passwordExpired) { Console.WriteLine("An error has occurred. Your password has expired."); return false; } // On successful login, cache session info and API endpoint info endpoint = new EndpointAddress(lr.serverUrl); header = new SessionHeader(); header.sessionId = lr.sessionId; // Create and cache an API endpoint client client = new SoapClient("Soap", endpoint); printUserInfo(lr, lr.serverUrl); return true; } #endregion #region printLogin private void printUserInfo(LoginResult lr, String authEP) { try { GetUserInfoResult userInfo = lr.userInfo; Console.WriteLine("UserID: " + userInfo.userId); Console.WriteLine("User Full Name: " + userInfo.userFullName); Console.WriteLine("User Email: " + userInfo.userEmail); Console.WriteLine(); Console.WriteLine("SessionID: " + lr.sessionId); Console.WriteLine("Auth End Point: " + lr.serverUrl); Console.WriteLine("Service End Point: " + lr.serverUrl); Console.WriteLine(); } catch (Exception e) { Console.WriteLine("An unexpected error has occurred: " + e.Message + "\nStack trace: " + e.StackTrace); } } #endregion #region describeGlobals private void describeGlobals(String myObjectType) { #region describeGlobalSample try { // describeGlobal() returns an array of object results that includes the object names that are available to the logged-in user. DescribeGlobalResult dgr; client.describeGlobal(header, null, out dgr); Console.WriteLine("\nDescribe Global Results:\n"); // Loop through the array echoing the object names for (int i = 0; i < dgr.sobjects.Length; i++) { Console.WriteLine(dgr.sobjects[i].name); } } catch (Exception e) { Console.WriteLine("An exception has occurred: " + e.Message + "\nStack trace: " + e.StackTrace); } #endregion #region describeSObjectSample try { string objectType = myObjectType; // Call describeSObjects() passing in an array with one object type name DescribeSObjectResult[] dsrArray; client.describeSObjects(header, null, null, new string[] { objectType }, out dsrArray); // Loop all fetched occurrences; possibly just one in this sample for (int arrayCount = 0; arrayCount < dsrArray.Length; arrayCount++) { DescribeSObjectResult dsr = dsrArray[arrayCount]; // Get some object properties Console.WriteLine("\n\nObject Name: " + dsr.name); if (dsr.custom) Console.WriteLine("Custom Object"); // Get the permissions on the object if (dsr.label != null) Console.WriteLine("Label: " + dsr.label); if (dsr.createable) Console.WriteLine("Createable"); if (dsr.deletable) Console.WriteLine("Deleteable"); if (dsr.queryable) Console.WriteLine("Queryable"); if (dsr.replicateable) Console.WriteLine("Replicateable"); if (dsr.retrieveable) Console.WriteLine("Retrieveable"); if (dsr.searchable) Console.WriteLine("Searchable"); if (dsr.undeletable) Console.WriteLine("Undeleteable"); if (dsr.updateable) Console.WriteLine("Updateable"); Console.WriteLine("Number of fields: " + dsr.fields.Length); //Retrieve metadata for each field for (int i = 0; i < dsr.fields.Length; i++) { // Get the field and Write some field properties Field field = dsr.fields[i]; Console.WriteLine("Field name: " + field.name); Console.WriteLine("\tField Label: " + field.label); //This next property indicates that this field is searched when using the name search group in SOSL if (field.nameField) Console.WriteLine("\tThis is a name field."); if (field.restrictedPicklist) Console.WriteLine("This is a RESTRICTED picklist field."); Console.WriteLine("\tType is: " + field.type.ToString()); if (field.length > 0) Console.WriteLine("\tLength: " + field.length); if (field.scale > 0) Console.WriteLine("\tScale: " + field.scale); if (field.precision > 0) Console.WriteLine("\tPrecision: " + field.precision); if (field.digits > 0) Console.WriteLine("\tDigits: " + field.digits); if (field.custom) Console.WriteLine("\tThis is a custom field."); // Write the permissions of this field if (field.nillable) Console.WriteLine("\tCan be nulled."); if (field.createable) Console.WriteLine("\tCreateable"); if (field.filterable) Console.WriteLine("\tFilterable"); if (field.updateable) Console.WriteLine("\tUpdateable"); // If this is a picklist field, show the picklist values if (field.type.Equals(fieldType.picklist)) { Console.WriteLine("\tPicklist Values"); for (int j = 0; j < field.picklistValues.Length; j++) Console.WriteLine("\t\t" + field.picklistValues[j].value); } // If this is a foreign key field (reference), show the values if (field.type.Equals(fieldType.reference)) { Console.WriteLine("\tCan reference these objects:"); for (int j = 0; j < field.referenceTo.Length; j++) Console.WriteLine("\t\t" + field.referenceTo[j]); } Console.WriteLine(""); } } } catch (Exception e) { Console.WriteLine("An exception has occurred: " + e.Message + "\nStack trace: " + e.StackTrace); } #endregion } #endregion #region queryLeads private String queryLeads() { string myXML = @"<Leads>"; try { String soqlQuery = "SELECT Id, FirstName, LastName, Company, State, Email, Status, CreatedDate FROM Lead ORDER BY LastName"; //String soqlQuery = "SELECT FirstName, LastName, OwnerId FROM Lead ORDER BY LastName"; QueryResult qr; client.query(header, null, null, null, soqlQuery, out qr); bool done = false; if (qr.size > 0) { Console.WriteLine("Logged-in user can see " + qr.records.Length + " records."); while (!done) { Console.WriteLine(""); sObject[] records = qr.records; for (int i = 0; i < records.Length; i++) { //Contact con = (Contact)records[i]; Lead lead = (Lead)records[i]; string fName = lead.FirstName; string lName = lead.LastName; if (fName == null) Console.WriteLine("Record #" + (i + 1) + ": " + lName); else Console.WriteLine("Record #" + (i + 1) + ": " + lName + ", " + fName); myXML += "<Lead><Name>" + lName + ", " + fName + "</Name><Company>" + lead.Company + "</Company><StateProvince>" + lead.State + "</StateProvince><Email>" + lead.Email + "</Email><LeadStatus>" + lead.Status + "</LeadStatus><CreatedDate>" + String.Format("{0:yyyy-MM-ddTHH:mm:ssZ}", lead.CreatedDate) + "</CreatedDate><LeadID>" + lead.Id + "</LeadID></Lead>"; } if (qr.done) done = true; else { client.queryMore(header, null, qr.queryLocator, out qr); } } } else Console.WriteLine("No records found."); } catch (Exception e) { Console.WriteLine("\nFailed to execute query succesfully," + "error message was: \n{0}", e.Message); } /*XDocument xdoc = new XDocument(); xdoc = XDocument.Parse(myXML); return xdoc;*/ return myXML + "</Leads>"; } #endregion #region createLead private String createLead(String FirstName, String LastName, String Company, String Email) { String confirmationId = "0"; try { Lead myNewLead = new Lead(); /*myNewLead.Description = "incoming from Bizagi"; myNewLead.Salutation = "Mr";*/ myNewLead.FirstName = FirstName; myNewLead.LastName = LastName; myNewLead.Company = Company; myNewLead.Email = Email; sObject[] objects = { myNewLead }; SaveResult[] results; LimitInfo[] limitinfo; client.create( header, null, null, null, null, null, null, null, null, null, null, null, objects, out limitinfo, out results ); SaveResult tmp = results[0]; if (tmp.success) { Console.WriteLine("Created lead Id is: " + tmp.id + "."); confirmationId = tmp.id; } } catch (Exception e) { Console.WriteLine("\nFailed to execute query succesfully," + "error message was: \n{0}", e.Message); } return confirmationId; } #endregion #region logout private void logout() { try { client.logout(header); Console.WriteLine("Logged out."); } catch (Exception e) { Console.WriteLine("An unexpected error has occurred: " + e.Message + "\nStack trace: " + e.StackTrace); } Console.WriteLine("\nPress ENTER to continue..."); Console.ReadLine(); } #endregion #endregion } } |
Observe que la clase llamada Class1 ofrece 2 métodos que sirven como puntos de entrada para la lógica que Bizagi necesitará para el uso desde una perspectiva de procesos.
Estos métodos son:
•public String Query(String userName, String password, String securityToken): trae todos los prospectos a partir de los parámetros de autenticación.
•public String Create(String userName, String password, String securityToken, String firstName, String lastName, String company, String email): crea un nuevo prospecto a partir de los parámetros de autenticación y los 4 campos básicos y obligatorios del nuevo prospecto: el nombre, apellido, la compañía para la que trabaja y una dirección de correo electrónico.
Tanto el nombre de la clase (Class1) coom cada uno de los métodos anteriores, serán referenciados por el mismo nombre en pasos posteriores.
Considere que todo el código es provisto como es, principalmente como un código de ejemplo que ilustra una posibilidad cuando se integra con Salesforce. Usted puede realizar las modificaciones pertinentes para extender la funcionalidad en ella (i.e, considerar la administración de contactos, Oportunidades o cuentas, considerar cambios en las APIS o resoluciones a problemas introducidos directamente por Salesforce, o usar un archivo de configuración app.config que maneje credenciales para evitar codificación de información).
Para el método public String Query, el código anterior retorna una cadena de texto en formato XML que tiene la siguiente estructura: <ClaimandComplaintRequest> <Leads> <Lead><Name>Akin, Kristen</Name><Company>Aethna Home Products</Company><StateProvince>VA</StateProvince><Email>kakin@athenahome.com</Email><LeadStatus>Working - Contacted</LeadStatus><CreatedDate>2015-12-28T17:07:00Z</CreatedDate><LeadID>00Q1500000sGMpKEAW</LeadID></Lead> </Leads> </ClaimandComplaintRequest> La razón por la que retorna un XML es para habilitar un fácil manejo de la información directamente en Bizagi, a través del uso del API de reglas y del uso de scopes o tecnologías XPath en Bizagi. |
1.11 Construya la librería
Construya su proyecto de tal forma que produzca la librería necesaria en Bizagi.
Haga esto asegurándose de que se genera para su arquitectura de sistema (32-bit o 64-bit) y la versión del framework de .NET:
La imagen de arriba muestra la clase de librería MySalesforceLibrary.dll (como fue llamado por los pasos presentados anteriormente).
Recuerde dónde se genera esta clase, ya que la necesitará en pasos y configuraciones posteriores.
1.12 Pruebe su componente desde otro proyecto de Visual Studio
Aunque este es un paso adicional, se recomienda asegurarse del correcto funcionamiento de su componente cuando se invoca desde otro proyecto.
Este otro proyecto puede ser uno creado directamente en su solución de Visual Studio como un proyecto de consola.
Observe que Bizagi puede invocar la clase de librería como lo hace un proyecto de consola, desde un punto de vista lógico. Garantizando al mismo tiempo que no tiene errores de codificación antes de entrar en Bizagi, se consigue roundtrips más eficientes con respecto a los ajustes de código. |
Para esto, cree un nuevo proyecto de consola a esta misma solución:
Esto le ayudará a probar y verificar su componente (por ejemplo ver directamente en la consola los prospectos generados):
Asegúrese de incluir su clase de librería como referencia:
Después, copie y pegue exactamente el mismo contenido desde el archivo app.config del proyecto de clase de librería de Salesforce en el archivo app.config del proyecto de consola creado.
Esto significa que el app.config o el proyecto de Consola, deben tener la misma dirección del endpoint (endpoint address) y la configuración de los parámetros maxBufferSize, maxReceivedMessageSize y maxBufferPoolSize, se muestra a continuación:
,
Para la clase principal (llamada TestConsole en este ejemplo), usted puede utilizar el siguiente código y diligenciar userName, password y securityToken:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySalesforceLibrary;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
String userName = ""; //your account's username here
String password = ""; //your password here
String securityToken = ""; //your security token here
String objectType = "Lead";
Console.WriteLine("Press an option (1-4) to run a test:");
Console.WriteLine("\t" + "-> 1 to test the connection only");
Console.WriteLine("\t" + "-> 2 to test querying all leads");
Console.WriteLine("\t" + "-> 3 to test creating one lead");
Console.WriteLine("\t" + "-> 4 to test all of the above");
Class1 pr = new Class1();
String option = Console.ReadLine();
int optionInt;
if (Int32.TryParse(option, out optionInt))
{
switch (optionInt)
{
case 1:
pr.Connect(userName, password, securityToken, objectType);
break;
case 2:
Console.WriteLine(pr.Query(userName, password, securityToken));
break;
case 3:
Console.WriteLine(pr.Create(userName, password, securityToken,
"Jerome", "Jones", "AgilityCorp", "jj@agilitycorp.com"));
break;
case 4:
pr.Test(userName, password, securityToken, objectType,
"Jerome", "Jones", "AgilityCorp", "jj@agilitycorp.com");
break;
default:
Console.WriteLine("Not a valid option. Ending execution.");
break;
}
}
}
}
}
Ejecutando el proyecto de consola con el código anterior, le permitirán probar separadamente tanto la conexión como todos los métodos usados en este ejemplo (o puede extender estas posibilidades si implementa métodos adicionales):
2. Registre el componente en Bizagi Studio
Una vez haya construido la clase de librería y haya verificado que funciona correctamente, abra su proyecto de Bizagi Studio.
2.1 Abra la librería de componentes
Navegue a la pestaña de Herramientas en la cinta de opciones y dé clic en la opción Librería de componentes.
Dé clic en Agregar para registrar su componente de Salesforce:
2.2 Ingrese los detalles del componente
Ingrese los detalles de Nombre visual y Descripción.
Por último, localice y cargue la clase de librería, la cual en este ejemplo es MySalesforceLibrary.dll:
Dé clic en Finalizar y después en Ok.
2.3 Ingrese los detalles del componente
De la misma forma como se hizo con el Proyecto de Consola de Pruebas, necesita utilizar las mismas definiciones que le permitan a Bizagi como aplicación, ejecutar y trasmitir servicios de Salesforce.
Para esto, copie el contenido del archivo app.config del proyecto de la clase de librería de Salesforce, específicamente, aquellos dentro del elemento <system.serviceModel>, los cuales son <bindings> y <client>.
Desde el explorador de Windows, localice el archivo web.config de Bizagi y edítelo (por defecto en C:\Bizagi\Projects\[su_proyecto]\WebApplication).
Para editarlo, primero localice el elemento <system.serviceModel> y después, copie dicho contenido dentro del mismo:
Guarde el archivo cuando termine.
A partir de este punto, el componente ha sido empaqueta y puede ser usado libremente en cualquier regla de negocio de sus procesos.
De acuerdo con la configuración realizada anteriormente, la forma de utilizar los métodos 2 en una regla de negocio es: •MySalesforceLibrary.Class1.Query(...) •MySalesforceLibrary.Class1.Create(...) |
3. Configure una regla de negocio que invoque su componente
Antes de configurar cualquier regla de negocio para utilizar el componente registrado, necesitará asegurarse previamente de que tiene las definiciones apropiadas en el modelo de datos y las opciones de Interfaz gráfica para manejar la información de Salesforce (i.e., los campos para el nombre del prospecto, el correo electrónico y la compañía en Bizagi).
Para ilustrar esta parte y producir una aplicación completamente ejecutable, recuerde que haremos cambios necesarios en la plantilla del proceso Peticion, Quejas y Reclamos que se descargó desde el Process Xchange.
3.1 Cree una entidad llamada Prospecto (Lead)
Edite el modelo de datos para que desde ahora tenga una entidad llamada Prospecto (Lead).
Para esto, vaya al diagrama del Modelo de datos del proceso (asistente del proceso paso #2) y cree una nueva entidad maestra:
3.2 Cree los atributos para la entidad
La información de la entidad Prospecto debe coincidir con la información del prospecto en Salesforce que esté considerada por el componente.
Por lo tanto, cree los siguientes atributos que corresponden a aquellos usados por el código provisto en el ejemplo: Nombre (Name), Compañía (Company), Estado (StateProvince), Correo Electrónico (Email), Estado del prospecto (LeadStatus) y Fecha de creación (CreatedDate).
3.3 Cree una entidad de relación
Cree una nueva relación para conectar el modelo actual de datos (desde la entidad de proceso llamada Solicitud de Quejas y Reclamos (Claim and Complaint request), con la entidad Prospecto (Lead) recientemente creada.
Para esto, dé clic en la opción Relación:
Para esta relación, asegúrese de seleccionar Solicitud de Quejas y Reclamos (Claim and Complaint request) como la Entidad 1 y Prospecto (Lead) como la Entidad 2:
Después, Selección la opción Colección (Uno-Muchos).
Esto le permite a las interfaces de usuario, presentar una tabla con la lista de prospectos, estos serán traídos a Bizagi desde Salesforce.
Bizagi llamará esta relación Prospectos (Leads).
Ahora que los cambios en el modelo de datos han sido completados, el diagrama del modelo debe mostrar la nueva relación que conecta la entidad Solicitud de quejas y reclamos (Claim and Complaint request) con la entidad Prospecto (Lead):
3.4 Abra las formas
Procederemos ahora a editar las interfaces de usuario existentes.
Para esto, vaya al paso #3 del asistente de proceso llamado Definir formas, y abra la forma de la actividad Analizar sugerencia (Analyse suggestion):
Tenga en cuenta que puede usar la información del solicitante que ya está almacenada en este punto (este conjunto de información es el que será enviado como un nuevo prospecto en Salesforce).
Por lo tanto, ajuste las interfaces de usuario para presentar la posibilidad de crear un Prospecto en Salesforce, solo necesita un botón con su acción respectiva.
3.5 Agregue un nuevo botón
Localice el control de Botón para agregarlo al grupo de información del solicitante:
Asegúrese de configurar su Etiqueta y la Etiqueta del botón y después, dé clic en Acciones y validaciones para definir la acción cuando se hace clic:
3.6 Defina la acción del botón
Agregue una nueva acción, la cual lanzará la integración con Salesforce cuando se da clic al botón Crearlo como Prospecto (Create as lead).
Configure la acción para ejecutar una regla, tal como se muestra a continuación:
Para la configuración del argumento, cree una nueva regla de negocio:
El código de la regla debe tener:
var myComponent = new MySalesforceLibrary.Class1();
myComponent.Create("", "", "",
<ClaimandComplaintRequest.Customer.FirstName>,
<ClaimandComplaintRequest.Customer.LastName>,
"Agility Corp.",
<ClaimandComplaintRequest.Customer.CustomerSnapshot.Email>);
Tenga en cuenta que este código instancia el componente al invocar sus métodos con esta sintaxis: MySalesforceLibrary.Class1.Create(...). Recuerde que este código necesitará ingresar el nombre de Usuario, la contraseña y el token de seguridad de su propia cuenta de Salesforce. |
Guarde la regla asegurándose de que no hay errores mostrados en Bizagi.
La nueva acción debe verse de manera similar a esta:
Aunque a este punto usted ya ha verificado la conexión con Salesforce desde Bizagi y creó prospectos utilizando el botón, vamos a ilustrar cómo configurar la parte en que se traen todos los prospectos.
3.7 Incluya una tabla para todos los prospectos
En la misma forma de la actividad, cree una pestaña adicional
Tenga en cuenta que la puede nombrar como "Prospectos Salesforce" o con el nombre de su elección, aunque la parte más relevante es asegurarse que incluyó la relación Prospectos (Leads) de su modelo de datos (i.e una colección, para ser mostrada por Bizagi como una tabla en tiempo de ejecución).
3.8 Configure la tabla
Establezca las propiedades de la tabla como de solo lectura (i.e es decir, Opciones de borrado, Opciones de adición y Opciones de fila deshabilitadas) después, incluya la información relevante del prospecto (Nombre (Name), Compañía (Company), Estado (StateProvince), Correo electrónico (Email), Estado del prospecto (LeadStatus) y fecha de creación (CreatedDate)), como se muestra a continuación:
Cierre y guarde la forma cuando termine.
3.9 Configure la regla de negocio desde las acciones de la actividad.
Vaya al asistente del proceso en el paso 4 llamado Acciones de la actividad.
Agregue una nueva acción a la actividad en el tiempo Al Salir de la actividad Enviar Respuesta (Send Answer):
Cree una nueva regla de negocio que tenga este código:
var myComponent = new MySalesforceLibrary.Class1();
var result = myComponent.Query("", "", "");
CEntityXmlHelper.fromXmlToEntityWithScopes(Me, result,false);
Guarde la regla siempre que se asegure de que no hay errores mostrados por Bizagi. Y eso es todo.
Usted puede mejor el ejemplo presentado, el cual es solo con propósitos ilustrativos.
Por ejemplo y para una implementación en vivo, usted puede considerar estos aspectos más avanzados: •Para el componente, se espera y se sugiere usar un archivo .config file para permitir una rigurosa seguridad y mejor manejo de las credenciales de las cuentas de servicio y el token de seguridad, en vez de quemarlas en la regla de negocio. •En Bizagi, se le recomienda usar integración asíncrona con Salesforce, para utilizar una entidad adicional en el medio que conecte la entidad de proceso con prospecto (Lead) y no directamente, y así usar transformaciones XLST. •Dependiendo de sus requerimientos, usted podría querer extender este ejemplo y modificar ambos componentes en Bizagi. Por ejemplo, puede agregar más atributos como el ID retornado por el prospecto creado en Salesforce, permitir entradas dinámicas para el nombre del a compañía o enviar información adicional a Salesforce (como números de teléfono, localización, etc). |
Ejecución
Ejecute su proceso utilizando el botón Ejecutar en Bizagi Studio.
Una vez se abra el Portal de Trabajo de Bizagi en el navegador, cree un nuevo caso del proceso Peticiones, quejas y reclamos:
En la primera tarea llamada Recibir solicitud (Receive request), usted diligenciará los detalles del solicitante (documento, nombre, correo electrónico) y asegúrese de seleccionar que la solicitud es una Sugerencia.
Dé clic en Siguiente cuando termine.
Usted verá a Bizagi en espera por un momento mientras trae los registros desde Salesforce.
En la tarea Analizar Sugerencia (Analyze Suggestion), usted puede ver todos los prospectos desde la pestaña Prospectos de Salesforce o utilizar el botón Crear como Prospecto para crear uno nuevo:
Ver todos los prospectos:
Cuando cree un nuevo prospecto, usted puede verificar su creación en el portal de Salesforce:
Tips para solución de problemas
Como se dijo previamente, se recomienda que se pruebe el componente en Bizagi una vez haya validado completamente que los métodos del mismo funcionen correctamente cuando fueron invocados desde otro proyectos de Visual Studio.
Una vez haya verificado esto y para solucionar problemas mientras se esté usando en Bizagi, depure el componente usando la opción "Adjuntar al proceso..." como se entrega con Visual Studio.
Para ello, tenga en cuenta que debe adjuntar a un proceso de IIS que ejecuta w3wp.exe:
Para esto, usted necesitará asegurarse de que la salida del componente esté empaquetada en Bizagi en modo Debug (Esto solo para ser usado en ambientes de desarrollo para propósitos de solución de problemas).
Cuando haga los cambios al componente y reconstruya su salida, asegúrese de cargar de nuevo esta librería en Bizagi Studio.
Para forzar que se tomen todos los cambios, puede reiniciar los servicios de IIS y borrar los archivos temporales o las versiones anteriores de los archivos dll de sus componentes.
Si tiene el siguiente error "Could not find default endpoint element that references contract 'sforce2.Soap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element." tenga en cuenta que necesita llevar a cabo los cambios en el archivo de configuración del portal de trabajo de Bizagi (web.config) como se describió cuando se registró el componente. |