Wiki source code of Libertya REST API - Manual de uso
Last modified by admin on 2026/07/18 17:44
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | = Libertya REST API {{id name="libertya-rest-api" /}}= | ||
| 2 | |||
| 3 | == Manual de uso {{id name="manual-de-uso" /}}== | ||
| 4 | |||
| 5 | {{toc/}} | ||
| 6 | |||
| 7 | = Introducción {{id name="introducción" /}}= | ||
| 8 | |||
| 9 | El presente documento detalla los pasos para realizar el deploy de Libertya REST API en una instancia Libertya. | ||
| 10 | |||
| 11 | = Convenciones {{id name="convenciones" /}}= | ||
| 12 | |||
| 13 | A modo de ejemplo, en todos los casos del presente documento se indica como dirección del servidor y puerto **localhost:8080**. | ||
| 14 | |||
| 15 | = Requerimientos {{id name="requerimientos" /}}= | ||
| 16 | |||
| 17 | Al momento de escribir este documento, se requiere **Java 8** y **Libertya 23.0** para poder ejecutar adecuadamente LY REST API (en versiones anteriores a Libertya 23.0 podría funcionar adecuadamente pero no ha sido validado). | ||
| 18 | |||
| 19 | = Distribución {{id name="distribución" /}}= | ||
| 20 | |||
| 21 | El proyecto se distribuye en un único archivo (por ejemplo **lyrestapi-1.0.0.jar**) conteniendo tanto la lógica necesaria, así como las librerías de Libertya sobre las que se apoya. | ||
| 22 | |||
| 23 | Notar que dentro de dicho archivo jar, en **/BOOT-INF/lib/** se encuentran las librerías **OXP.jar** y **OXPXLib.jar** utilizadas en el build del proyecto. Por consiguiente, en caso de actualizar la versión de Libertya CORE (o sus componentes), será necesario reemplazar estos archivos con las nuevas versiones y si la nueva versión contiene cambios estructurales, deberá adecuarse el schema de los end-points implementados en función de dichos cambios. | ||
| 24 | |||
| 25 | = Preferencias {{id name="preferencias" /}}= | ||
| 26 | |||
| 27 | Dentro del archivo jar, en **/BOOT-INF/classes/** se encuentra el archivo **application.properties**. En dicho archivo se configuran - entre otras - las siguientes propiedades: | ||
| 28 | |||
| 29 | *. Información de conexión a la base de datos y el ID de la compañía a utilizar (por defecto 1010016). | ||
| 30 | **. Utilizada para - por ejemplo - poder validar la existencia de usuarios ante las solicitudes de tokens a la base de datos\\ | ||
| 31 | **. Saber la compañía sobre la cual se estará ejecutando el servicio, y por consiguiente determinar datos relevantes para el contexto como la moneda.\\ | ||
| 32 | **. Las gestiones operativas serán registradas bajo el usuario contenido en la información del token obtenido.\\ | ||
| 33 | *. Secret key a utilizar para la generación de los JWT a utilizar, así como el tiempo de expiración de los tokens generados\\ | ||
| 34 | *. Completar directamente los documentos o dejarlos en borrador\\ | ||
| 35 | *. Generación de logs (ubicacion, formato, etc.)\\ | ||
| 36 | *. Recuperación de valores para propiedades que referencian a otras entidades\\ | ||
| 37 | *. Carga de valores por defecto en inserción | ||
| 38 | |||
| 39 | A lo largo de este documento se entrará en detalle sobre cada uno de estos ítems. | ||
| 40 | |||
| 41 | **IMPORTANTE** : las propiedades más relevantes (conexión a base de datos, compañía, puerto, etc.), pueden ser configuradas desde variables de entorno. La aplicación priorizará la configuración según las variables de entorno, y en caso contrario, utilizará las propiedades de **application.properties**. | ||
| 42 | |||
| 43 | = Ejecución {{id name="ejecución" /}}= | ||
| 44 | |||
| 45 | **java -jar lyrestapi-1.0.0.jar** | ||
| 46 | |||
| 47 | La salida debería ser similar a la siguiente: | ||
| 48 | |||
| 49 | . ____ _ __ _ _\\/\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ \\\( ( )\___ |’_ | ‘_| |’_ \/ _` | \ \ \ \\\\\/ ___)| |_)| | | | | || (_| | ) ) ) )\\’ |____| .__|_| |_|_| |_\__, | / / / /\\=========|_|==============|___/=/_/_/_/\\:: Spring Boot :: (v2.7.6) | ||
| 50 | |||
| 51 | - Starting LYRestAPI using Java 1.8.0_362 on pc-usuario with PID 12553 (/home/usuario/workspace/org.libertya.api/build/classes/java/main started by usuario in /home/usuario/workspace/org.libertya.api)\\- No active profile set, falling back to 1 default profile: “default”\\- Tomcat initialized with port(s): 8080 (http)\\2023-08-03 09:29:33.973 INFO - Starting service [Tomcat]\\…\\- Tomcat started on port(s): 8080 (http) with context path ’’\\- Started LYRestAPI in 8.839 seconds (JVM running for 10.532) | ||
| 52 | |||
| 53 | == Inicio automático en distribuciones recientes de Linux {{id name="inicio-automático-en-distribuciones-recientes-de-linux" /}}== | ||
| 54 | |||
| 55 | Es posible configurar el inicio/detención de la aplicación como servicio de Linux. Para esto se debe crear el archivo en **/etc/systemd/system/lyrestapi.service** (o el nombre de preferencia) con un contenido similar al siguiente (suponiendo que la aplicación se almacena en **/opt/lyrestapi**): | ||
| 56 | |||
| 57 | [Unit]\\Description=Libertya REST API\\After=network.target | ||
| 58 | |||
| 59 | [Service]\\Type=simple\\User=libertya\\WorkingDirectory=/opt/lyrestapi\\ExecStart=/usr/bin/java -jar /opt/lyrestapi/lyrestapi-1.0.0.jar\\Restart=always\\RestartSec=5 | ||
| 60 | |||
| 61 | [Install]\\WantedBy=multi-user.target | ||
| 62 | |||
| 63 | Luego deberá ejecutarse: | ||
| 64 | |||
| 65 | sudo systemctl daemon-reload\\sudo systemctl enable lyrestapi\\sudo systemctl start lyrestapi | ||
| 66 | |||
| 67 | == Ejecución mediante Docker {{id name="ejecución-mediante-docker" /}}== | ||
| 68 | |||
| 69 | De contar con una imagen Docker de **lyrestapi**, es posible disparar un container, indicando las variables de entorno relevantes, por ejemplo: | ||
| 70 | |||
| 71 | docker run -p 8080:8080 –name lyrestapi_app -e DB_HOST=192.168.1.35 -e DB_NAME=libertya_test lyrestapi | ||
| 72 | |||
| 73 | Lógicamente, se deberán cambiar los argumentos de entorno según corresponda. | ||
| 74 | |||
| 75 | = Token {{id name="token" /}}= | ||
| 76 | |||
| 77 | El primer paso es obtener un token a fin de poder interactuar con la API. | ||
| 78 | |||
| 79 | curl -X POST \\\http:~/~/localhost:8080/token \\\-H ‘username: AdminLibertya’ \\\-H ‘password: AdminLibertya’ \\\-H ‘clientid: 1010016’ \\\-H ‘orgid: 0’ | ||
| 80 | |||
| 81 | Lógicamente, bajo **username**, **password**, **clientid**, **orgid** deberán indicarse credenciales de acceso adecuadas según la información alojada en la tabla de usuarios (AD_User). Un usuario registrado en AD_User bajo AD_Org_ID = 0 puede generar un token tanto con **orgid = 0** como con cualquiera de las organizaciones pertenecientes a la compañía indicada bajo **clientid**. Un usuario registrado en AD_User bajo un AD_Org_ID distinto a 0 podrá generar un token únicamente para la organización en cuestión. | ||
| 82 | |||
| 83 | En caso de haber especificado correctamente la información de acceso, obtendremos un token que podremos utilizar hasta su fecha de expiración: | ||
| 84 | |||
| 85 | Bearer eyJhbGciOiJIUzUxMiJ9eyJqdGkiOiJKV1RCdWlsZGVyIiwi…CMscA2rV7PIa9TXu-vYiq6VCuA3Ghv5fI2xGOs9IfB2UMepKp3L6ulXQ | ||
| 86 | |||
| 87 | **El token obtenido contiene el usuario con el cual se obtuvo dicho token. Cualquier actividad que se realice sobre la API con este token serán registrados con dicho usuario**. Si en las operaciones no se especifica la propiedad **ad_org_id**, se utilizará el **orgid** indicado en la solicitud del token. Por consiguiente, si el token fue generado con la organización 0, entonces bajo ciertas operaciones que requieren un orgId distinto a cero (por ejemplo la creacion de un OP/RC), se deberá especificar la propiedad **ad_org_id** como parte del payload a enviar. | ||
| 88 | |||
| 89 | **NOTA**: Los días de validez de un token pueden ser configurados bajo la propiedad **security.token.exp.days** (ver apartado [[Preferencias>>#preferencias]]). | ||
| 90 | |||
| 91 | **NOTA**: Adicionalmente al requerimiento del token, el usuario con el cual se generó dicho token debe existir y encontrarse activo. De esta manera, el control y limitación de acceso y a la API abarca tanto la validación del token así como la verificación del usuario en cuestión. Puede desactivar esta validación adicional modificando la preferencia **security.access.validate.user**. | ||
| 92 | |||
| 93 | **MUY IMPORTANTE**: en ambientes de producción, debe modificarse la propiedad **security.token.secret** con un valor distinto al definido por defecto, ya sea modificando el application.properties o especificando mediante la variable de entorno **TOKEN_SECRET**. | ||
| 94 | |||
| 95 | = Uso {{id name="uso" /}}= | ||
| 96 | |||
| 97 | == Recuperación de entidades {{id name="recuperación-de-entidades" /}}== | ||
| 98 | |||
| 99 | Una vez obtenido el token, la operatoria es sencilla. Simplemente se debe indicar dicho token en el header del request. | ||
| 100 | |||
| 101 | Por ejemplo, recuperar una **entidad comercial**: | ||
| 102 | |||
| 103 | curl -X GET \\\http:~/~/localhost:8080/v1.0/bpartners/1012142 \\\-H ‘authorization: Bearer eyJhbGciOiJIUzUxMiJ9…HFfythd7EgIQ49QkR3KhmfQuAmB9jBRcQ89tiw’ \\\-H ‘content-type: application/json’ | ||
| 104 | |||
| 105 | Respuesta: | ||
| 106 | |||
| 107 | {\\“cbpartnerId”: 1012436,\\“cbpGroupId”: 1000026,\\“acqusitioncost”: 0,\\“actuallifetimevalue”: 0,\\…,\\“trxenabled”: true,\\“updated”: “2023-06-02 12:15:04.745344”,\\“updatedby”: 1010717,\\“value”: “U819383ua42”\\} | ||
| 108 | |||
| 109 | Recuperar una **factura**: | ||
| 110 | |||
| 111 | curl -X GET \\\http:~/~/localhost:8080/v1.0/invoices/1022033 \\\-H ‘authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJqd…0NFu0-8h-KOf1xyrZMZvmQ8-0J77GsA’ \\\-H ‘content-type: application/json’ \ | ||
| 112 | |||
| 113 | Respuesta, notar que la misma estará formada por un encabezado (header), así como sus lineas (lines) e impuestos (taxes): | ||
| 114 | |||
| 115 | {\\“**header**”: {\\“cinvoiceId”: 1022033,\\“cbpartnerId”: 1012145,\\“cbpartnerLocationId”: 1012158,\\“ccurrencyId”: 118,\\…\\“totallines”: 350,\\“updated”: “2023-06-09 08:53:10.749484”,\\“updatedby”: 1010717,\\},\\“**lines**”: [\\{\\“ad_client_id”: 1010016,\\“ad_org_id”: 1010053,\\“c_invoice_id”: 1022033,\\“c_invoiceline_id”: 1030150,\\“qtyinvoiced”: 2,\\…\\“updated”: “2023-06-09 08:53:09.707834”,\\“updatedby”: 1010717\\},\\{\\“ad_client_id”: 1010016,\\“ad_org_id”: 1010053,\\“c_invoice_id”: 1022033,\\“c_invoiceline_id”: 1030151,\\…\\“qtyinvoiced”: 5,\\“taxamt”: 0,\\“updated”: “2023-06-09 08:53:09.992148”,\\“updatedby”: 1010717\\}\\],\\“**taxes**”: [\\{\\“cinvoiceId”: 1022033,\\“ctaxId”: 1010087,\\“ad_client_id”: 1010016,\\“ad_org_id”: 1010053,\\“c_tax_id”: 1010087,\\…\\“taxbaseamt”: 350,\\“updated”: “2023-06-09 08:53:10.164017”,\\“updatedby”: 1010717\\}\\]\\} | ||
| 116 | |||
| 117 | === Detalle de campos referenciados {{id name="detalle-de-campos-referenciados" /}}=== | ||
| 118 | |||
| 119 | En caso de que la propiedad **restapi.libertya.app.referencedValues** sea **Y**, además de recuperar la entidad en cuestión se recuperará la información asociada a las propiedades que referencian otras entidades, considerando que la información relevante se obtiene del campo value o bien de los campos identificadores del registro en cuestión. La información correspondiente puede obtenerse como una map dinamica de valores bajo la propiedad **referencedvalues**, con los sufijos por defecto **__detail** y **__value**: | ||
| 120 | |||
| 121 | |||
| 122 | {{code}} | ||
| 123 | ... | ||
| 124 | "updated": "2023-05-29 09:57:44.081033", | ||
| 125 | "updatedby": 1010717, | ||
| 126 | "**referencedvalues**": \[ | ||
| 127 | { | ||
| 128 | "key": "ad\_client\_id\_\_detail", | ||
| 129 | "value": "Libertya" | ||
| 130 | }, | ||
| 131 | { | ||
| 132 | "key": "ad\_client\_id\_\_value", | ||
| 133 | "value": "Libertya" | ||
| 134 | }, | ||
| 135 | { | ||
| 136 | "key": "ad\_org\_id\_\_detail", | ||
| 137 | "value": "Default" | ||
| 138 | }, | ||
| 139 | { | ||
| 140 | "key": "ad\_org\_id\_\_value", | ||
| 141 | "value": "Default" | ||
| 142 | }, | ||
| 143 | { | ||
| 144 | "key": "c\_bpartner\_id\_\_detail", | ||
| 145 | "value": "AFIP\_ADMINISTRACION FEDERAL DE INGRESOS PUBLICOS" | ||
| 146 | }, | ||
| 147 | { | ||
| 148 | "key": "c\_bpartner\_id\_\_value", | ||
| 149 | "value": "AFIP" | ||
| 150 | }, | ||
| 151 | { | ||
| 152 | "key": "c\_bpartner\_location\_id\_\_detail", | ||
| 153 | "value": "CAPITAL FEDERAL YRIGOYEN HIPOLITO 370 Piso:04 Depto:148\_1012296" | ||
| 154 | }, | ||
| 155 | { | ||
| 156 | "key": "c\_currency\_id\_\_detail", | ||
| 157 | "value": "ARS" | ||
| 158 | }, | ||
| 159 | { | ||
| 160 | "key": "c\_doctype\_id\_\_detail", | ||
| 161 | "value": "Factura de Cliente" | ||
| 162 | }, | ||
| 163 | { | ||
| 164 | "key": "c\_doctypetarget\_id\_\_detail", | ||
| 165 | "value": "Factura de Cliente" | ||
| 166 | }, | ||
| 167 | {{/code}} | ||
| 168 | |||
| 169 | Los sufijos a utilizar pueden modificarse cambiando las propiedades: **restapi.libertya.app.referencedValuesValueSuffix** y **restapi.libertya.app.referencedValuesDetailSuffix**. | ||
| 170 | |||
| 171 | === Criterios de filtrado {{id name="criterios-de-filtrado" /}}=== | ||
| 172 | |||
| 173 | Es posible especificar un conjunto de parametros de URL a fin de acotar la recuperación de entidades: | ||
| 174 | |||
| 175 | *. **limit**: Limita el número de elementos a retornar. en caso de no especificar un valor retornará 100 elementos únicamente\\ | ||
| 176 | *. **page**: Numero de pagina a retornar, el cual en conjunto con limit se utiliza para paginado.\\ | ||
| 177 | *. **order**: Criterio de ordenamiento por algún campo en particular.\\ | ||
| 178 | *. **filter**: Filtrado avanzado de recuperación de elementos.\\ | ||
| 179 | *. **fields**: Retornar unicamente los campos especificados. | ||
| 180 | |||
| 181 | Ejemplo: | ||
| 182 | |||
| 183 | *. http:~/~/localhost:8080/v1.0/bpartners?limit=3&page=2&order=c_bpartner_id&filter=“c_bpartner_id>1012141 and c_bpartner_id<1012145”&fields=name,value | ||
| 184 | |||
| 185 | Se está solicitando obtener **3 elementos** de **Entidades Comerciales**, con **desplazamiento a la pagina 2**, ordenados por **c_bpartner_id**, filtrando únicamente las ECs cuyo **ID sea mayor a 1012429** y recuperar solo las propiedades **name** y **value**. | ||
| 186 | |||
| 187 | curl -X GET \\\‘http:~/~/localhost:8080/v1.0/bpartners?limit=3&page=2&order=c_bpartner_id&filter=%22c_bpartner_id%3E1012429%22&fields=name%2Cvalue’ \\\-H ‘authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJ…TGz6vhkHFfythd7EgIQ49QkR3KhmfQuAmB9jBRcQ89tiw’ \ | ||
| 188 | |||
| 189 | Salida: | ||
| 190 | |||
| 191 | [\\{\\“name”: “Ent. Comercial Ejemplo 3”,\\“value”: “BP3”\\},\\{\\“name”: “Ent. Comercial Ejemplo 4”,\\“value”: “BP4”\\},\\{\\“name”: “Ent. Comercial Ejemplo 5”,\\“value”: “BP5”\\}\\] | ||
| 192 | |||
| 193 | === Navegabilidad {{id name="navegabilidad" /}}=== | ||
| 194 | |||
| 195 | Ante un GET a una lista de entidades, El header de la respuesta contendrá además los links a **prev** y **next** para la correspondiente navegabilidad. Por ejemplo: | ||
| 196 | |||
| 197 | Para el siguiente GET query en donde se recuperan los elementos de la página 2: | ||
| 198 | |||
| 199 | *. http:~/~/localhost:8080/v1.0/allocations?fields=documentno,docstatus,created&sort=documentno&limit=10&page=2 | ||
| 200 | |||
| 201 | Obtendermos además las siguientes propiedades en el header: | ||
| 202 | |||
| 203 | *. **Prev**: http:~/~/localhost:8080/v1.0/allocations?fields=documentno,docstatus,created&sort=documentno&limit=10&page=1\\ | ||
| 204 | *. **Next**: http:~/~/localhost:8080/v1.0/allocations?fields=documentno,docstatus,created&sort=documentno&limit=10&page=3 | ||
| 205 | |||
| 206 | == Creación de entidades {{id name="creación-de-entidades" /}}== | ||
| 207 | |||
| 208 | La estructura a respetar en la creación de entidades dependerá del tipo de entidad a crear. Por ejemplo, la creación de un artículo simplemente implica el volcado de la información relacionada con el artículo a crear. Sin embargo, para la creación de una factura es necesario volcar tanto el contenido de la cabecera como el de sus líneas. Se detallan a continuación algunos ejemplos de la estructura básica a enviar. En todos los casos es necesario realizar un HTTP POST al end-point correspondiente, incluyendo el correspondiente token JWT generado previamente. | ||
| 209 | |||
| 210 | === Nuevo artículo {{id name="nuevo-artículo" /}}=== | ||
| 211 | |||
| 212 | curl –request POST \\\–url http:~/~/localhost:8080/v1.0/products \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJ…g0DLlRES7Q’ \\\–data ‘{\\“name”: “Articulo de ejemplo 2”,\\“value”: “EJE02”,\\“c_uom_id”: 100,\\“m_product_category_id”: 1010146,\\“c_taxcategory_id”: 1010048\\}’ | ||
| 213 | |||
| 214 | === Nueva factura de cliente {{id name="nueva-factura-de-cliente" /}}=== | ||
| 215 | |||
| 216 | curl –request POST \\\–url http:~/~/localhost:8080/v1.0/invoices \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxMi…cDrGVAHJmg’ \\\–data ‘{\\“**header**”:\\{\\“c_doctype_id”: 1010507,\\“c_doctypetarget_id”: 1010507,\\“issotrx”: true,\\“c_bpartner_id”: 1012145,\\“c_bpartner_location_id”: 1012158,\\“c_currency_id”: 118,\\“m_pricelist_id”: 1010595,\\“c_paymentterm_id”: 1010083,\\“paymentrule”: “S”,\\“ad_user_id”: 100\\},\\“**lines**”:\\[\\{\\“ad_org_id”: “1010053”,\\“qtyinvoiced”: “2”,\\“pricesactual”: “30”\\}\\]\\}’ | ||
| 217 | |||
| 218 | **NOTA**: Las propiedades **c_doctypetarget_id** / **c_doctype_id** / **issotrx** definen si la factura a crear es de cliente o de proveedor. | ||
| 219 | |||
| 220 | === Nuevo recibo de cliente {{id name="nuevo-recibo-de-cliente" /}}=== | ||
| 221 | |||
| 222 | curl –request POST \\\–url http:~/~/localhost:8080/v1.0/allocations \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxMi…pmcDrGVAHJmg’ \\\–data ‘{\\“c_bpartner_id”: 1012142,\\“c_doctype_id”: 1010568,\\“earlypayment”: false,\\“**invoices**”:\\[\\{\\“c_invoice_id”: “1022046”,\\“amount”: “1”\\}\\],\\“**payments**”:\\[\\{\\“c_pospaymentmedium_id”: “1010269”,\\“amount”: “1”,\\“c_payment_id”: “1012189”\\}\\]\\}’ | ||
| 223 | |||
| 224 | **NOTA**: En la creación de entidades no es necesario especificar la **compañía** (ad_client_id) o la **organización** (ad_org_id) dado que éstos valores (al igual que createdby, updatedby) son automáticamente cargados a partir de la información del token JWT. | ||
| 225 | |||
| 226 | **NOTA**: La propiedad **restapi.libertya.app.useDefaults** permite especificar si se desean cargar los valores por defecto (según la definición en metadatos) en la creación de nuevas entidades previo al volcado de la información recibida en el payload. | ||
| 227 | |||
| 228 | **NOTA**: La propiedad **org.libertya.api.service.doc.complete** por defecto se encuentra activa, la cual hace que se complete el documento (pedido, remito, factura, etc.) que se está creando inmediatamente. Puede cambiar el comportamiento desactivando esta propiedad. De esta manera los documentos creados quedarán en estado borrador. | ||
| 229 | |||
| 230 | === Creación de documentos en etapas {{id name="creación-de-documentos-en-etapas" /}}=== | ||
| 231 | |||
| 232 | La manera más sencilla de crear documentos (pedidos, remitos, facturas, etc.) es utilizando el end-point principal correspondiente, el cual recibe - por ejemplo - tanto la información de la cabecera como la de sus líneas. Sin embargo, en caso de ser necesario es posible crear un documento en sucesivas invocaciones (*), por ejemplo: | ||
| 233 | |||
| 234 | 1. Creación de cabecera de factura bajo POST a **/v1.0/invoices** (solo con la información de la cabecera)\\ | ||
| 235 | 1. Creación de linea/s de factura bajo POST/s a **/v1.0/invoicelines**\\ | ||
| 236 | 1. Completado de factura bajo PUT a **/v1.0/invoices/{id_invoice}/process?action=CO** | ||
| 237 | |||
| 238 | (*) En este caso es necesario desactivar la propiedad **org.libertya.api.service.doc.complete** a fin de que la API no intente completar el documento automáticamente luego de crear la cabecera de la factura. | ||
| 239 | |||
| 240 | == Actualización de entidades {{id name="actualización-de-entidades" /}}== | ||
| 241 | |||
| 242 | La actualización de entidades no presenta mayores considerandos, salvo la convención para forzar a null una propiedad en particular. En caso de necesitar forzar a null una propiedad se debe enviar al cadena **[NULL]** como body de la propiedad en cuestión en el end point de la operación HTTP PUT correspondiente, por ejemplo: | ||
| 243 | |||
| 244 | curl –request PUT \\\–url http:~/~/localhost:8080/v1.0/inventories/1010562 \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxM…A4Bnrwk5TAw’ \\\–data ‘{\\**“description”: “[NULL]”,**\\“isactive”: false\\}’ | ||
| 245 | |||
| 246 | **NOTA**: En caso de ser necesario, es posible definir una cadena especial distinta a **[NULL]** modificando la propiedad **restapi.libertya.app.nullValue** en el archivo **application.properties**. | ||
| 247 | |||
| 248 | === Actualización de entidades con estructuras complejas {{id name="actualización-de-entidades-con-estructuras-complejas" /}}=== | ||
| 249 | |||
| 250 | A diferencia de la creación de nuevas entidades con estructuras complejas como facturas, remitos, pedidos, las actualizaciones sobre la cabecera y sus correspondientes líneas se realizan de manera independiente, con endpoints específicos en cada caso. Por ejemplo: | ||
| 251 | |||
| 252 | **HTTP POST http:~/~/localhost:8080/v1.0/invoices** para crear una factura, enviando el JSON con la estructura completa de cabecera / lineas. | ||
| 253 | |||
| 254 | **HTTP PUT http:~/~/localhost:8080/v1.0/invoicelines/{id_linea_de_factura}** para actualizar una línea de factura, enviando el JSON con la estructura de las propiedades a modificar de la línea de factura únicamente. | ||
| 255 | |||
| 256 | == Eliminación de entidades {{id name="eliminación-de-entidades" /}}== | ||
| 257 | |||
| 258 | La eliminación de entidades simplemente implica realizar un HTTP DELETE al endpoint correspondiente. Por ejemplo: | ||
| 259 | |||
| 260 | curl –request DELETE \\\–url http:~/~/localhost:8080/v1.0/products/1012096 \\\–header ‘authorization: Bearer eyJhbGciOiJIUzU…aUjpmcDrGVAHJmg’ \ | ||
| 261 | |||
| 262 | == Procesamiento de entidades {{id name="procesamiento-de-entidades" /}}== | ||
| 263 | |||
| 264 | Las entidades de tipo documento (pedidos, remitos, facturas, etc.) pueden ser procesadas (cerradas, completadas, anuladas, revertidas, etc.) mediante un HTTP PUT al endpoint correspondiente, indicando además el tipo de acción a realizar: | ||
| 265 | |||
| 266 | *. CO: Completar\\ | ||
| 267 | *. CL: Cerrar\\ | ||
| 268 | *. VO: Anular\\ | ||
| 269 | *. RE: Revertir | ||
| 270 | |||
| 271 | Por ejemplo: | ||
| 272 | |||
| 273 | curl –request PUT \\\–url ‘http:~/~/localhost:8080/v1.0/inventories/1010584/process?action=VO’ \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiUzUxMiJ9.eyJq…f5GT3mvE6D2uvg’ \ | ||
| 274 | |||
| 275 | **NOTA**: Si la propiedad **org.libertya.api.service.doc.complete** se encuentra activa, los documentos se completarán automáticamente en la creación de los mismos. | ||
| 276 | |||
| 277 | == Gestion dinámica de propiedades de entidades {{id name="gestion-dinámica-de-propiedades-de-entidades" /}}== | ||
| 278 | |||
| 279 | La propiedad **additionalvalues** eventualmente contenida en cada JSON permite gestionar propiedades adicionales pertenecientes a la entidad de manera dinámica. Si por algún motivo existieran columnas adicionales (en los metadatos de Libertya y a nivel físico) a las originalmente soportadas en las operaciones definidias en la API al momento de su release, es posible gestionar la información de dichos campos mediante el uso de la propiedad **additionalvalues**, bajo un esquema **key**/**value**. Esta funcionalidad está soportada tanto en la creación como en la actualización de entidades, así como en la recuperación de las mismas. | ||
| 280 | |||
| 281 | Para los ejemplos que se muestran a continuación, se supone que la instalación de un plugin ad-hoc creó dos nuevas columnas sobre la tabla usuario, llamadas **Facebook_ID** y **Instagram_ID**, las cuales no son parte de la estructura original de la API. | ||
| 282 | |||
| 283 | **NOTA**: También es posible actualizar la estructura de las entidades de Libertya REST API a fin de que considere esta ampliación estructural, pero en este caso será necesario regenerar y recompilar los fuentes del proyecto el proyecto LYRESTAPI en función de la estructura de la base de datos donde se utilizar la API. | ||
| 284 | |||
| 285 | === Carga de entidades con eventuales campos adicionales {{id name="carga-de-entidades-con-eventuales-campos-adicionales" /}}=== | ||
| 286 | |||
| 287 | Se puede realizar la carga sobre las propiedades **Facebook_ID** y **Instagram_ID** mediante el uso de la property **additionalvalues** de la siguiente manera: | ||
| 288 | |||
| 289 | curl –request POST \\\–url http:~/~/localhost:8080/v1.0/users \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxM…5GT3mvE6D2uvg’ \\\–data ‘{\\“name” : “un usuario de ejemplo”,\\“**additionalvalues**”: [\\{\\“key”: “facebook_id”,\\“value”: “myfacebookid”\\},\\{\\“key”: “instagram_id”,\\“value”: “myinstagramid”\\}\\]\\}’ | ||
| 290 | |||
| 291 | === Actualizacion de entidades con eventuales campos adicionales {{id name="actualizacion-de-entidades-con-eventuales-campos-adicionales" /}}=== | ||
| 292 | |||
| 293 | De manera similar a la creación de nuevas entidades, se puede realizar la actualizacion de las propiedades **Facebook_ID** y **Instagram_ID** de una entidad existente mediante el uso **additionalvalues** de la siguiente manera: | ||
| 294 | |||
| 295 | curl –request PUT \\\–url http:~/~/localhost:8080/v1.0/users/1010716 \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxMiJ…5GT3mvE6D2uvg’ \\\–data ‘{ “description” : “una descripcion”,\\“**additionalvalues**”: [\\{\\“key”: “facebook_id”,\\“value”: “myotherfacebookid”\\},\\{\\“key”: “instagram_id”,\\“value”: “myotherinstagramid”\\}\\]\\}’ | ||
| 296 | |||
| 297 | === Visualización de entidades con eventuales campos adicionales {{id name="visualización-de-entidades-con-eventuales-campos-adicionales" /}}=== | ||
| 298 | |||
| 299 | Al ejecutar la recuperación del usuario obtendremos la estructura predefinida y bajo la propiedad **additionalvalues** la información adicional (**Facebook_ID** y **Instagram_ID**): | ||
| 300 | |||
| 301 | curl –request GET \\\–url http:~/~/localhost:8080/v1.0/users/1097718 \\\–header ‘Content-Type: application/json’ \\\–header ‘authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJqd…GeW5twOCOf5GT3mvE6D2uvg’ \ | ||
| 302 | |||
| 303 | {\\“ad_client_id”: 1010016,\\“ad_user_id”: 1097718,\\…\\“**additionalvalues**”: [\\{\\“key”: “facebook_id”,\\“value”: “foobarfacebookid”\\},\\{\\“key”: “instagram_id”,\\“value”: “foobarinstagramid”\\}\\],\\…\\} | ||
| 304 | |||
| 305 | == Gestion de usuarios {{id name="gestion-de-usuarios" /}}== | ||
| 306 | |||
| 307 | La API soporta la gestión de usuarios (creación, modificación, eliminación, recuperación). Sin embargo, considerando que a partir de la información de usuarios se podría realizar operaciones sensibles o que afecten la seguridad del sistema, existe la posibilidad de deshabilitar estas operaciones mediante la siguiente propiedad de **application.properties**: | ||
| 308 | |||
| 309 | # Operaciones de gestion de usuarios habilitados: (C)reate, (R)etrieve, (U)pdate, (D)elete\\org.libertya.api.service.user.operations=CRUD | ||
| 310 | |||
| 311 | Si se desea quitar alguna de las operaciones relacionadas con la gestión de usuarios, simplemente deben quitarse los permisos correspondientes C, R, U o D según sea necesario. | ||
| 312 | |||
| 313 | **NOTA**: En la recuperación de entidades de tipo usuarios, el campo password es omitido del conjunto de información a retornar. | ||
| 314 | |||
| 315 | = Log de eventos {{id name="log-de-eventos" /}}= | ||
| 316 | |||
| 317 | Ante cada evento se volcará al log la información relacioanda con el evento en cuestión, por ejemplo: | ||
| 318 | |||
| 319 | 2023-06-15 08:54:08.263 INFO - BPartnerController.addBPartner Arg1: class BPartner {, acqusitioncost: 0.0000, …, value: U8119383ua42, },\\2023-06-15 08:54:08.377 INFO - BPartnerController.addBPartner: <409 CONFLICT Conflict,No se pudieron guardar los cambios: : Existe un registro de Entidad Comercial que ya contiene el valor U8119383ua42 para el campo Clave. El valor de este campo no puede ser duplicado.,[]> | ||
| 320 | |||
| 321 | 2023-06-15 09:03:26.630 INFO - InvoiceController.retrieveInvoice Arg1: 1022033,\\2023-06-15 09:03:27.239 INFO - InvoiceController.retrieveInvoice: <200 OK OK,class InvoiceDocument {, header: class Invoice {, adClientId: 1010016, adOrgId: 1010053, … authmatch: true, | ||
| 322 | |||
| 323 | La ubicación del archivo de log, así como el formato y límites pueden ser especificados en el archivo **application.properties**. | ||
| 324 | |||
| 325 | # Log de eventos - Ubicacion - Formato - Historial\\logging.file.name=~${LOG_FILENAME:/tmp/lyrestapi.log}\\logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %level - %msg%n\\logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} %level - %msg%n\\logging.file.max-size=20MB\\logging.file.max-history=7\\# Limitar el tamaño del contenido a almacenar para cada request y response (-1 = sin limite)\\logging.request.max.length=-1\\logging.response.max.length=300 | ||
| 326 | |||
| 327 | En donde: | ||
| 328 | |||
| 329 | *. **logging.file.name** permite indicar la ubicación y nombre del archivo a generar\\ | ||
| 330 | *. **logging.pattern.*** permite especificar el formato de log\\ | ||
| 331 | *. **logging.file.max-*** permite limitar el tamaño de archivos e historial\\ | ||
| 332 | *. **logging.request.max.length** permite indicar la longitud a almacenar del request (o -1 si queremos almacenarla por completo)\\ | ||
| 333 | *. **logging.response.max.length** idem anterior pero para responses | ||
| 334 | |||
| 335 | = API Docs y API UI {{id name="api-docs-y-api-ui" /}}= | ||
| 336 | |||
| 337 | Accediendo a **localhost:8080/api-docs** y **localhost:8080/api-docs.yaml** se puede recuperar la definición completa de los end-points de todas las operaciones que soporta Libertya REST API, en formato JSON como YAML respectivamente. | ||
| 338 | |||
| 339 | Accediendo a **localhost:8080/swagger-ui** es posible acceder a la visualización de las operaciones mediante la herramienta **Swagger UI**: | ||
| 340 | |||
| 341 | [[image:image1.png]] | ||
| 342 | |||
| 343 | **NOTA**: A fin de poder realizar las pruebas pertinentes bajo Swagger UI, es necesario previamente introducir un token (JWT) válido obtenido previamente (mediante la operación **POST** **localhost:8080/token** detallada al principio de este documento), sin incluir el prefijo Bearer. | ||
| 344 | |||
| 345 | [[image:image2.png]] | ||
| 346 | |||
| 347 | La funcionalidad de API Docs y API UI funcionalidad puede ser desactivada modificando a **false** las siguientes propiedades de **application.properties**: | ||
| 348 | |||
| 349 | *. springdoc.api-docs.enabled=true\\ | ||
| 350 | *. springdoc.swagger-ui.enabled=true | ||
| 351 | |||
| 352 | = Información operacional de la aplicación {{id name="información-operacional-de-la-aplicación" /}}= | ||
| 353 | |||
| 354 | Accediendo a **http:~/~/localhost:8080/monitor** es posible acceder a información sobre la aplicación, salud de la misma, métricas, etc., mostrando la nómina de links habilitados: | ||
| 355 | |||
| 356 | {\\“_links”: {\\“self”: {\\“href”: “http:~/~/localhost:8080/monitor”,\\“templated”: false\\},\\“health”: {\\“href”: “http:~/~/localhost:8080/monitor/health”,\\“templated”: false\\},\\“info”: {\\“href”: “http:~/~/localhost:8080/monitor/info”,\\“templated”: false\\},\\…\\} | ||
| 357 | |||
| 358 | Por ejemplo accediendo a **http:~/~/localhost:8080/monitor/health** obtenemos: | ||
| 359 | |||
| 360 | {\\“status”: “UP”,\\“components”: {\\“diskSpace”: {\\“status”: “UP”,\\“details”: {\\“total”: 943412031488,\\“free”: 233513222144,\\“threshold”: 10485760,\\“exists”: true\\}\\},\\“ping”: {\\“status”: “UP”\\}\\}\\} | ||
| 361 | |||
| 362 | **NOTA**: Habilitar las métricas sin restricción puede representar un riesgo de seguridad, ya que dichas métricas pueden proporcionar información detallada sobre el estado interno y el comportamiento de la aplicación en ejecución. Esto puede abarcar datos sensibles o confidenciales que podrían ser aprovechados por potenciales atacantes para comprender mejor la arquitectura de la aplicación e identificar vulnerabilidades. Es por este motivo que por defecto la aplicación solo habilita las métricas básicas de información y salud de la aplicación. | ||
| 363 | |||
| 364 | En caso de querer ampliar las métricas deberá cambiar la siguiente línea de **application.properties**: | ||
| 365 | |||
| 366 | management.endpoints.web.exposure.include=info,uptime,health | ||
| 367 | |||
| 368 | incluyendo otras métricas adicionales, por ejemplo: | ||
| 369 | |||
| 370 | management.endpoints.web.exposure.include=info,uptime,health**,logfile,caches,dbinfo** | ||
| 371 | |||
| 372 | o si por ejemplo se desean habilitar todas las métricas: | ||
| 373 | |||
| 374 | management.endpoints.web.exposure.include=***** |