Artículos etiquetados con: SAPB1-Desarrollo

Hasta 170.000€ de subvención para implantar un #ERP en tu #PYME en #Canarias.

Convocatoria de subvenciones a empresas de alta tecnología e intensivas en conocimiento en áreas prioritarias de la RIS3 (EATIC)

Beneficiarios: PYMEs que estén válidamente constituidas en el momento de la presentación de la solicitud, tengan residencia fiscal o un establecimiento permanente en la Comunidad Autónoma de Canarias y cuenten con uno o más empleados a la fecha de solicitud. (Menos 250 empleados y volumen anual de negocios inferior a 50 millones euros)

Plazo máximo solicitud: 19 de abril de 2017 a 14:00h.

Importe mínimo proyecto: 86.000,00 Euros aproximadamente. 

Importe subvención: Hasta 70% (Mínimo: 60.000,00; Máximo: 174.990,00)

Gastos subvencionables: Inmovilizado material e inmaterial + Consultoría externa + gastos auditoría. 

Gestión de eventos en SAP Business One

Conoce mejor como interactúan los eventos con tus addons

Gestión de eventos en SAP Business One

En SAP Business One se producen gran cantidad de eventos cuando un usuario interactúa con la aplicación cliente.
Todos estos eventos son comunicados a las aplicaciones de terceros (addons) que se hayan conectado a la interfaz de usuario mediante la API de interfaz de usuario: UI API.
Entre otros, los eventos comunicados pueden ser pulsaciones de teclas, cambio de idioma, creación de una factura de ventas, abrir una ventana de datos maestros de interlocutor comercial, pulsar un botón, etc…
En este artículo nos centraremos en gestionar mejor la comunicación de tus addons con los eventos que más nos interese.

Modificando la interfaz de usuario de SAP Business One

¿Quieres saber trabajar con la UI API de SAP Business One?

Modificando la interfaz de usuario  de SAP Business One

Siempre es interesante poder modificar la UI (interfaz de usuario) para realizar tareas básicas de manera más sencilla.

En este post detallaremos en solo 3 acciones un ejemplo práctico y útil del tipo de cosas que podemos hacer.

Gestión de múltiples códigos EAN en SAP Business One

SAP B1 cuenta con la posibilidad de gestionar los códigos de barra asociados a los artículos de una sociedad.

Para ello, de forma estándar, el formulario “Datos maestros de artículo” cuenta con un campo que almacenará el código de barras asociado a cada artículo.

Por lo general, en las empresas es necesario poder asignar a un artículo varios códigos de barra, por lo que para cubrir esta funcionalidad deberemos recurrir a algunas de las herramientas de personalización del producto.

Lo que necesitaríamos principalmente es una tabla en la que podamos introducir en cada línea, un artículo, un código de barras asociado al artículo y opcionalmente, el tipo de código de barras de que se trata, así como si es el código de barras a usar de forma predeterminada o no.

Para contar con esta tabla en el sistema crearemos una “tabla definida por el usuario” o UDT (User Defined Table):

Varias líneas de esta tabla pueden estar referidas al mismo artículo con distintos códigos de barra, por lo que ya tendremos el soporte para poder gestionar múltiples códigos de barra. De esta forma tendremos una tabla similar a la que aparece reflejada en la siguiente captura de pantalla:

A partir de aquí podremos incluir funcionalidades a nuestro sistema mediante el uso de búsquedas formateadas y/o del SDK de SAP Business One.

A continuación se muestra una captura de un formulario de datos maestros de artículo, que cuenta con una pestaña de “Códigos de barra” desarrollada mediante el SDK de SAP B1:

UDF y búsquedas formateadas

SAP Business one puede ser adaptado a las necesidades específicas de un cliente en particular de múltiples maneras. Estas posibilidades se podrían agrupar en:

  1. Uso de las múltiples opciones de parametrización estándar disponibles en el producto. Tomando determinadas decisiones durante la implantación, podemos configurar SAP Business One para que, por ejemplo, use como método de valoración de nuestro inventario, el criterio del peso medio variable o del último precio de compra.
  2. Se pueden agregar elementos a la base de datos estándar siguiendo las reglas definidas por SAP. Podemos crear nuevos campos (llamados campos UDF: user defined fields) que nos pueden ayudar a almacenar la información cómo y dónde el cliente necesita verla. También se pueden crear nuevas tablas (llamadas tablas UDT: user defined tables) e incluso crear nuevos objetos con determinadas funciones predefinidas que nos pueden facilitar la labor de desarrollar nuevos datos maestros o documentos (UDO: user defined objects). En este apartado podemos incluir la creación de búsquedas formateadas (formatted searches) que permiten asociar el resultado de una consulta SQL a un campo de la base de datos, de este modo podemos, por ejemplo, asociar una lista de valores a un campo, ya sea estándar o UDF, sin necesidad de desarrollo.
  3. Uso del kit de desarrollo (SDK) disponible para SAP Business One, pudiendo interactuar tanto con la base de datos a través de su interfaz de datos: DI API, o con la interfaz de usuario a través de la UI API

En este post me he planteado explicar un pequeño ejemplo que ilustre varias formas de conseguir que una empresa pueda conocer el saldo de un cliente, en el momento en el que se va a introducir en el sistema un pedido de ventas de dicho cliente. De forma estándar, una de las opciones podría consistir en seleccionar el cliente desde la pantalla de pedido, navegamos a sus datos maestros haciendo uso de la “flecha naranja” correspondiente y visualizamos el saldo en la parte superior derecha de sus datos maestros.                           Otra opción estándar es “parametrizar” nuestra lista de selección de clientes del pedido (conocida como ChooseFromList) para que ya incluya el saldo de todos los clientes disponibles en nuestra base de datos:                                         Otra opción podría ser añadir un campo nuevo al documento de pedido (campo UDF) y asignar una búsqueda formateada a dicho campo para que se actualice con la selección del cliente y muestre el saldo de forma automática. Para lograr esto seguiremos los siguientes pasos: 1. Creación de un nuevo campo UDF para los documentos de pedido: Introducimos la siguiente información para nuestro nuevo campo:                       Podemos comprobar que nuestro campo ha sido creado, si abrimos un nuevo pedido y nos aseguramos de tener activada la opción de visualizar campos definidos por el usuario               2. Crear la consulta SQL que nos permita extraer el saldo de un cliente determinado:           3. Una vez hemos creado nuestra consulta SQL, la grabaremos en el Query Manager, pero antes de ello sustituiremos el valor del criterio de filtrado “CARDCODE=C30000” por el valor de código de cliente que procederá del documento de pedido. Esto lo podemos lograr haciendo uso de la etiqueta $ que nos permitirá acceder a valores del documento que se está usando y aún no han sido almacenado en la base de datos. En este caso necesitamos el campo CardCode, de la tabla ORDR. Por lo tanto sustituiremos nuestra consulta por: 4. Asignaremos nuestra búsqueda formateada al campo UDF creado y haremos que se actualice automáticamente al seleccionar un nuevo cliente desde pedido: Pulsamos “Shift + F2” desde “Saldo cliente” y seleccionamos las siguientes opciones:               Con esto habremos conseguido que tras seleccionar un cliente en nuestros documentos de pedido, se cargue automáticamente su saldo en nuestro nuevo campo “Saldo IC”: Esto ha sido un pequeño ejemplo de uso de las posibilidades de personalización de SAP Business One. Por último, me gustaría aprovechar este post para desearles feliz navidad y un próspero 2013.

Desactivación y activación temporal de filtros

Es posible limitar el número de eventos que SAP Business One envía a nuestro addon para su gestión.

Limitar el número de eventos que recibe nuestro addon permite que aquellos eventos que no necesiten ser gestionados, no empeoren el rendimiento de la aplicación y por lo tanto mejore la experiencia del usuario.

Es posible que sea interesante en algún momento desactivar el envío de eventos de SAP B1 a nuestra aplicación, realizar alguna labor y volver a activar el envío de eventos. Este tipo de estrategias suele resultar adecuado cuando gestionamos con nuestro addon diferentes eventos que están relacionados y que pueden causar efectos colaterales no deseados.

Para poder desactivar y activar temporalmente los filtros haremos uso de XML y de los métodos presentes en la clase de la UI API Application 1. En el constructor de nuestra clase: Constructor de clase con filtros

La variable "filtros" ha sido declarada globalmente a la clase: private EventFilters filtros; En el lugar donde desactivemos y activemos los filtros escribiremos:

Activar desactivar filtros

El método setFiltros() contiene el siguiente código: Reestablecer filtrado

Usando esta estrategia podemos centrarnos en gestionar los eventos que nos interesan sin preocuparnos por la recepción accidental de otros en nuestro addon.

Búsqueda eficiente en Control "matrix"

Entre mis pruebas usando el SDK de SAP Business One, he estado intentando averiguar la forma más eficiente para buscar y seleccionar dentro de un control “matrix” (cargado usando dbdatasources) una fila que cumple un criterio específico.

La idea era replicar el formulario de Listas de precios del estándar añadiendo dos columnas para vincular a los artículos, además de los precios, dos descuentos que se usarán a nivel de línea en los documentos.

Es decir, tenemos una matriz con información de precios de artículos (replicando el formulario del estándar para las listas de precios), tenemos un edittext para hacer búsquedas en la matriz (al igual que el estándar), introducimos un código de artículo en el edittext y pulsamos en un botón de buscar para realizar una búsqueda del código de artículo en la matriz de forma eficiente.

En mi caso estaba tratando con cerca de 2400 registros que se cargan velozmente usando el método del control Matrix: ”loadfromdatasource”. A continuación expongo mis experiencias:

  • El óptimo sería usar el dbdatasource de la columna por la que queremos buscar para hacer un query(conditions) con el valor que tenemos y seleccionar en la matriz la fila que se corresponde con el valor seleccionado en el dbdatasource. Pude comprobar que el query(conditions) tarda un tiempo despreciable para encontrar cuál es la línea del dbdatasource adecuada. El problema es que una vez encontrada la línea del dbdatasource que se está buscando no hay forma de saber con qué línea del control Matrix se corresponde. Por lo tanto, para poder saber la línea de la matrix que debía marcar, me dispuse a cargar en el dbdatasource la información de índice de cada fila. Esto lo hice de dos maneras:

 

    • Con un datatable de los de ado .net: Tardaba 44 segundos en cargar el formulario después de haber ejecutado el loadfromdatasource
    • Usar arraylist cargado en el momento del form también retrasa la carga demasiado (en comparación con loadfromdatasource):

Código usado:

Form f = kernel.cargarForm("XML\\ITOP_PRECIOS.xml", "ITOP_PRECIOS" + FormUID);
   inicializarFormItopDtos(f, lista);
   DateTime antes = DateTime.Now;
   ArrayList listaAux = new ArrayList();
   for (int i = 0; i < f.DataSources.DBDataSources.Item("ITM1").Size; i++) {
      listaAux.Add(i);
   }
   TimeSpan tarda = DateTime.Now - antes;
   kernel.Application.MessageBox("Tarda: " + tarda.TotalSeconds.ToString(), 0, "", "", "");

Resultado carga form rellenando arraylist:

    • Rellenando un userdatasoure y usando mtx.addRow() en lugar de loadfromdatasource: Tardaba 74 segundos en cargar el formulario.
  • Después de los resultados anteriores (Carga de formulario demasiado lenta) me planteé desechar la búsqueda con Query(conditions), por lo que llegué a estas dos alternativas:
    • Búsqueda por ui api en la matrix…. Opción demasiado lenta.
    • Búsqueda en los datasources: Lo mejor que he encontrado. Haciendo una búsqueda secuencial en la columna que corresponda del dabdatasource adecuado se obtienen unos resultados muy buenos con los 2400 registros:
      • Último registro (empieza por f):

      • Registro no existente:

      • Registro intermedio:

El código usado es el siguiente:

private void seleccionarFila(Matrix mtx, DBDataSource dbds, string columna, string codigoABuscar, string celdaFocoDestino) {
   int i = 0;
   DateTime antes = DateTime.Now;
   while ((i < dbds.Size) && (!dbds.GetValue(columna, i).Trim().StartsWith(codigoABuscar)))
   i++;
   if (i < dbds.Size) {
      mtx.SelectRow(i + 1, true, false);
      mtx.Columns.Item(celdaFocoDestino).Cells.Item(i + 1).Click(BoCellClickType.ct_Regular, 0);
   }
   else
   kernel.Application.MessageBox("Código: " + codigoABuscar + " no encontrado", 1, "", "", "");
   TimeSpan tarda = DateTime.Now - antes;
   kernel.Application.MessageBox("Tarda: " + tarda.TotalSeconds.ToString(), 0, "", "", "");
}