Esta pequeña serie sobre scripts en Service Layer consta de tres partes:
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.
Dicho esto, y tras ver los scripts, creo que la mejor opción es mandar un json con dos propiedades, Recibo y Emision, cada una con el documento correspondiente. Con esto, el script, sin complicarnos mucho con la gestión de errores, sería algo como:
var http = require('HttpModule.js'); var ServiceLayerContext = require('ServiceLayerContext.js'); function POST() { var slContext = new ServiceLayerContext(); var obj = http.request.getJsonObj(); var recibo = obj.Recibo; var emision = obj.Emision; if (!obj.Recibo || !obj.Emision) { throw http.ScriptException(http.HttpStatus.HTTP_BAD_REQUEST, "Indique recibo y emision. "); } slContext.startTransaction(); var res1 = slContext.InventoryGenEntries.add(recibo); if (!res1.isOK()) { slContext.rollbackTransaction(); throw http.ScriptException(http.HttpStatus.HTTP_BAD_REQUEST, "Recibo: " + res1.getErrMsg()); } var res2 = slContext.InventoryGenExits.add(emision); if (!res2.isOK()) { slContext.rollbackTransaction(); throw http.ScriptException(http.HttpStatus.HTTP_BAD_REQUEST, "Emision: " + res2.getErrMsg()); } slContext.commitTransaction(); /* SET HTTP RESPONSE */ var ret = { "Recibo": res1.body, "Emision": res2.body } http.response.setContentType(http.ContentType.APPLICATION_JSON); http.response.setStatus(http.HttpStatus.HTTP_OK); http.response.setContent(ret); http.response.send(); }
Para pruebas (básicamente, para saber si le estaba mandando la información bien), en el ScriptException me devolví lo que había enviado:
if (!obj.Recibo || !obj.Emision) { throw http.ScriptException(http.HttpStatus.HTTP_BAD_REQUEST, "Indique recibo y emision. " + http.request.getContent()); }
El siguiente paso era crear el archivo ard con los datos de nuestro pequeño addon. El código viene en el manual y sólo necesitamos cambiar un par de cosas: el nombre de la empresa, el del addon y el número de versión:
<?xml version="1.0" encoding="utf-8"?> <AddOnRegData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SlientInstallation="" SlientUpgrade="" Partnernmsp="cda-ie" SchemaVersion="3.0" Type="ServiceLayerScript" OnDemand="" OnPremise="" ExtName="" ExtVersion="1.12" Contdata="" Partner="cda-ie" DBType="MSSQL" ClientType="S"> <ServiceLayerScripts> <Script Name="recibo" FileName="Recibo.js"></Script> </ServiceLayerScripts> <XApps> <XApp Name="" Path="" FileName="" /> </XApps> </AddOnRegData>
Metemos el script y el ard en un zip con el mismo nombre y vamos a cargarlo en SAP, mediante el Extension Manager. Una vez subido, lo asignamos a la empresa y ya lo tenemos operativo.
La ventaja de trabajar con scripts es que, al igual que con la Di Api, puedo obtener datos de los pasos intermedios. Es decir, podría pasar el DocEntry/DocNum del recibo a campos personalizados de la emisión, para enlazarlos, hacer alguna consulta previa de validación y darle al script su propia lógica, etc. En general, podemos hacer casi cualquier cosa y hay bastantes ejemplos de código. Sin embargo, hay algo bastante importante que no podemos hacer: cerrar o cancelar documentos.