Scripts en SAP Business One Service Layer II — El script

Como dije en la anterior entrada, mi primer script iba a ser de una operación sencilla: crear dos documentos, un recibo de producción y su emisión de componentes correspondiente, en una transacción.

Como siempre, nuestro punto de partida es el manual de Service Layer que tenemos en nuestro servidor (https://<miservidor>:50000/Working_with_SAP_Business_One_Service_Layer.pdf) y que también podemos consultar aquí. Todo el apartado 3.20 está dedicado a esto. El código de ejemplo que trae lo tenemos también en la carpeta de instalación de Service Layer y es un buen punto de partida.

Sigue leyendo

Scripts en SAP Business One Service Layer I — Preparando el entorno

Una vez montado el cliente OData de Service Layer, realizar las operaciones individuales que hasta ahora hacía por B1WS, como, no sé, hacer traslados, crear y modificar ofertas y pedidos, crear y modificar UDOs varios, ha sido sencillo. Otra cosa muy distinta son las operaciones complejas que encapsulo en una transacción por Di Server, algo que no permite B1WS, ni tampoco el flamante Service Layer.

O, por lo menos, no tal cual. Pero tiene su propio SDK que nos permite hacer una suerte de addons en JavaScript que, sin ser tan potentes como lo que podemos hacer por Di Api, es, en algunos aspectos, más potente que lo que nos ofrece Di Server.

Me he lanzado a probar este extraño mundo con una operación sencilla en mente, pero que en la empresa se hace con mucha frecuencia: un recibo de producción con su emisión de componentes correspondiente.

Sigue leyendo

Eliminar líneas de un objeto con Sap Business One Service Layer

En las primeras pruebas con SAP Service Layer y su cliente OData para .Net me he encontrado con un problema que, por otra parte, me esperaba. Quiero decir que la actualización en OData se basa en enviar el conjunto de los cambios y no toda la entidad, para tener un flujo de datos lo más reducido posible. En Service Layer esto implica que si, por ejemplo, quiero actualizar un pedido de ventas, enviaré los campos de la cabecera que cambian, así como las líneas que se cambian o se añaden.

Pero, ¿y si lo que quiero es eliminar una línea? En Di Server/B1WS debíamos enviar todas las líneas, por lo que, si faltaba alguna, SAP entendía que la queríamos eliminar.

¿Es posible hacer eso en Service Layer?

Atendiendo al manual del usuario que tenemos en https://<miservidor>:50000/Working_with_SAP_Business_One_Service_Layer.pdf, no.

Sigue leyendo

Sap Business One Service Layer

Después de meses de retrasos y problemas (que si falla la controladora RAID del nuevo servidor, que si hay que esperar a un parche de SAP que se retrasa, que si pruebas por aquí y por allá), en noviembre por fin actualizamos a SAP 10. De lo más interesante de esta versión es que por fin tenemos Service Layer en la versión para SQL Server (hasta entonces, estaba sólo para Hana).

Service Layer es una nueva api de datos para que nuestras aplicaciones puedan trabajar con SAP Business One. Es una api web moderna, Restful, con protocolo OData. Por supuesto, con algunas cosillas particulares, que para algo hablamos de SAP.

Yo esperaba con muchas ganas el poder meterle mano a Service Layer. El venerable Di Server se nos ha quedado pequeño y nos da mil y un extraños problemas. No cuento con que Service Layer sea la panacea, pero se supone que debe funcionar mejor que algo marcado como obsoleto años antes de que yo empezara a usarlo. El problema, como siempre, es la formación y la documentación. O la falta de. Como es habitual, me toca buscarme las habichuelas.

Sigue leyendo

SAP Business One B1WS: editar oferta de ventas II

Hace poco tuve que modificar unos documentos de márketing (ofertas y pedidos de ventas) vía B1WS/Di Server. Hasta el momento, sólo había creado documentos de SAP y supuse que la edición seguiría el mismo proceso que con los UDO, con los que tengo bastante más manejo. Básicamente, el proceso con un UDO es:

  • Obtengo el objeto sin modificar vía B1WS.
  • Modifico los campos de la cabecera con los datos nuevos.
  • Con el array de líneas, agrego las nuevas, elimino las que hay que borrar y modifico los campos de las que hay que modificar.
  • Le vuelvo a enviar todo a SAP.

Con las líneas, que es lo que me importa aquí, el proceso es como éste, siendo Origen el objeto con los cambios que envía la capa de lógica de negocio y Destino, el objeto sin modificar recuperado de SAP. Como pueden observar, hay una propiedad en las filas origen que me indica qué debo hacer con ellas:

Sigue leyendo

SAP Business One B1WS: editar oferta de ventas

Una breve entrada sobre SAP Business One:

Intento editar una oferta de ventas vía B1WS. Al obtener la misma mediante el consabido método de GetByParams, me da error al procesar el xml. Un error de conversión de algún campo de fecha/hora. Empezamos bien.

Ataco directamente el DiServer para conseguir la oferta en bruto, en texto plano, y busco los campos fecha/hora a ver cuál es el causante. Verán, SAP B1 guarda el tiempo como entero corto, en forma HHMM: 935, 1250, 1800… que son devueltos por correctamente formateados como 9:35:00, etc. Pero hay un campo de la oferta de ventas (y del resto de documentos de márketing), UpdateTS, que guarda HHMMSS: 125015. Y me encuentro con que el DiServer lo devuelve formateado, bajo el nombre de UpdateTime de la forma 1250:15:00. Ferpecto:

El maldito


Imagino que al que hizo la función que formatea los campos de hora para los servicios del DiServer le dirían que todos iban en forma HHMM o que los campos UpdateTS de los documentos de márketing son posteriores a dicha función y nadie se acordó de cambiarla/comprobarla.

Como el campo es irrelevante en la actualización (no necesito su valor y es algo que rellena el propio SAP), la solución es simple: editar manualmente el wsdl generado, buscar el campo de marras y cambiar el tipo de time a string.

Imagino que para la 9.3 lo habrán corregido, pero en la 9.2 parche 10, así están las cosas.

2020-04-14: pues no, no lo han actualizado. Entre el parche 10 de la 9.2 y el parche 13 de la 9.3 me he encontrado con un montón de cambios en la estructura de los documentos de márketing expuestos por Di Api/Di Server, pero el maldito UpdateTime sigue dando guerra.

Adiós, mi viejo ordenador

En primavera de 2007 me compré un ordenador. Un sobremesa Packard Bell bastante descompensado, con un Pentium D Presler cuando pegaba fuerte el Core Duo, con dos gigas de RAM (cosa harto rara entonces) y una GeForce de gama baja. La parte interesante estaba en el monitor, un 22» realmente bueno. Combinado, el precio estaba bien, incluyendo el precio de la GeForce 8600 que le metí al poco (cuando salieron al mercado). Un espécimen de gran superficie que no casaba bien junto ni de casualidad: el ordenador no podía ni reproducir un dvd a pantalla completa, cosas de la gráfica de serie y los primeros drivers Nvida para Vista.

Pero era un pedazo de pantalla y, por aquel entonces, salía más a cuenta comprar un ordenador en el hipermercado que en las tiendas de la zona. Además, mi pliego de condiciones para comprar el ordenador se reducía a «ver anime». El sobremesa viejo, un P IV Willamette de segunda hornada (socket 478), ya no podía con los mp4 que sacaban los fansubs. Lo compré, dejé Vista aparcado, instalé XP y a disfrutar. Bueno, XP, Debian, 2003 Server… En aquel entonces, usaba yo más Debian que otra cosa. Luego, con la salida del Service Pack 1 para Vista, me obligué a usarlo un par de semanas y ya me enamoré de él y caí en las garras de la pérfida Spectra para siempre. Pasó de Vista a 7 y de 7 a 8 y ahora a 10.

Con el tiempo, la pantalla murió (ahora tengo una de 23» de peor calidad, cosas del seguro). Y la gráfica. Y luego repescó otra y… Y en el trabajo estrené un i5 y empecé a ver que el de casa se me había quedado viejo. Esta primavera lo he sustituido por un AMD A10-7870k, por cuestión de precio. Comprado a piezas y montado en una torre recauchutada.

Y ahora al venerable anciano le espera una segunda actividad. Monta desde hace unos años una GT530 y le he puesto un SSD de 120GB como unidad primaria. Arranca como nunca y creo que tiene por delante dos o tres años más de servicio. Lo que no está mal para una torre que compré ya obsoleta.

Eficiencia alemana (II): actualizar listas de precios en SAP B1

Problema pintoresco este que menciono. Las veces anteriores, mi compañero había actualizado los precios importando a partir de una hoja Excel desde dentro de SAP, pero, ya sea por mi poca pericia, ya por la actualización a 9.0, he sido incapaz de preparar el maldito Excel. La otra opción, que en su día se dejó por imposible, es importar a través de esa bestia del averno llamada Data Transfer. Así, preparo mi plantilla para los precios, tabla ITM1, con las columnas ItemCode, LineNum, PriceList, Price y Currency. De ellas, ItemCode es el código del artículo, PriceList es el id de la lista de precios. Añadimos el importe y la moneda (EUR) y listo… Uhm, salvo LineNum, que ponemos a 0, que es lo habitual (LineNum, como regla general, es el número de línea por código de la tabla maestra, es decir, que será 0 si sólo vamos a actualizar un precio por artículo, como era el caso).

Bien, pues eso no funciona.

Después de buscar por los foros oficiales, encuentro una respuesta ante este problema que es absurda. O, por lo menos, yo no le encuentro la lógica. Decía así: quite la columna PriceList y en LineNum ponga el id de la lista de precios menos 1.

Y funciona.

Eficiencia alemana

Con la actualización a SAP Business One 9.0 se decidió cambiar la nomenclatura de los almacenes. En la práctica, esto supuso crear almacenes nuevos y mover masimavente la mercancía en el sistema (necesario, de todas formas, para aprovechar el nuevo sistema de ubicaciones). Para evitar que los usuarios metieran accidentalmente mercancía en los almacenes viejos, se marcaron como Inactivos (un bonito check en el formulario de almacenes, que se corresponde con el campo Inactive de la tabla correspondiente). Hasta ahí, sin problemas.

Como baja colateral, el enlace entre el gestor de proyectos (desarrollo propio) y SAP dejó de funcionar. El enlace permite tanto crear artículos en SAP desde el gestor como actualizarlos después y supuso un gran ahorro de trabajo en el departamento, que hasta entonces debía copiar los datos logísticos de un nuevo producto a mano desde el gestor a SAP.

El error que da al actualizar el artículo es que hay almacenes inactivos. Guay. La cosa se pone interesante porque el código del error no aparece en la documentación (he descubierto estos meses que lo raro es que aparezca). Es más, buscando en la documentación de la DI Api (la interfaz de datos que se usa para comunicarse con SAP) el dichoso campo Inactive no aparece en el objeto Almacén.

Vale, puede ser que yo sea un cegato y venga con otro nombre (no es raro), así que me voy a la documentación de la base de datos para ver si la descripción del campo me da alguna pista sobre qué nombre buscar en la DI Api.

Y no lo encuentro. En la documentación de la base de datos de la versión 9.0 no viene, para la tabla maestra de almacenes, el campo Inactive. Por más que exista y por más que tenga un bonito check en el formulario de gestión de almacenes. Con un par.

A eso se le llama «eficiencia alemana».

Hasta Yoda hace anuncios

Sí, señor. Hasta el maestro de jedis se ha vendido y hace anuncios. Me recuerda a una escena de Spaceballs. ¿Que qué anuncia? Seguro que lo habéis visto en páginas web y en prensa escrita: las bondades de Internet Explorer 8. O sea, que además de prestarse a hacer anuncios, ¡los hace para el Imperio! En la segunda parte de la campaña, lo estoy viendo, tendremos a Darth Vader diciendo «Si hubiéramos tenido IE8, los rebeldes no nos habrían robado los planos de la Estrella de la Muerte». Bromas aparte, la campaña es curiosa y bien hecha y es un intento de relanzar IE8 en un momento delicado para la familia de navegadores de Microsoft, que sigue perdiendo cuota frente a otras opciones y, sobre todo, un intento de quitarse de encima el sanbenito de navegador inseguro. Porque, vale, IE6 era como era, pero IE8 es uno de los navegadores más seguros que podemos encontrar y ya iba siendo hora de que desde Microsoft pusieran más empeño en alabar sus virtudes para contrarrestar el manido «Internet Explorer es una mierda por donde te van a entrar todos los virus del mundo mundial» que todavía oigo con mucha frecuencia.

Por mi parte, me acostumbré a IE8 en el trabajo (la aplicación de las tiendas sólo funcionaba bajo IE, cosas de los dichosos controles ActiveX y tal; por lo menos, conseguí hacerla funcionar con IE8 y dejar, así, IE6, que hay muchos que no lo han conseguido con sus respectivas aplicaciones) y lo uso en casa cuando la seguridad es prioritaria. En el portátil uso bastante IE8 64bits, aunque eso me suponga quedarme sin flash, porque es bastante más ágil. Y es que la razón por la que no uso IE8 en mi día a día es porque me tarda Dios y ayuda en abrir una nueva pestaña. Y yo soy de los que pulsan Ctrl+T y se ponen a escribir la dirección (o parte, o el nombre) del sitio web, así que IE8 no me da lo que necesito.

Chrome tampoco. Tiene la velocidad a la hora de abrir pestañas, sí, pero la mezcla de barra de direcciones y buscador no me da los resultados deseados, tiene las pestañas arriba. Con otros detalles más a los que tampoco me hago, fue a la pila de descartes. Junto con Ópera, cuya interfaz me desespera y a la que no logro acostumbrarme. Con Safari, tres cuartos de lo mismo. Los he probado alrededor de una semana cada uno y no he conseguido acostumbrarme a ninguno.

Así que sigo usando mi viejo amigo Firefox, pese a ser el menos seguro ahora mismo (con la futura versión 4, ya veremos). No por sus extensiones, que no utilizo, ni porque sea software libre, que me la suda, ni por su ligereza o rapidez. Tampoco por su estabilidad (aunque me apostaría a que los problemas que me da a ese respecto son culpa última de algún control flash). Desde luego, no por su seguridad. Lo utilizo porque me sigue dando lo que necesito. Que, al fin y al cabo, es de lo que se trata.