Introducción
El presente documento busca orientar a los desarrolladores que requieran consumir la API de Rindegastos con la finalidad de obtener información de comprobaciones de gastos y llevarla a su sistema contable. Este es un ejemplo estándar de cómo se puede abordar el problema de integración de datos y puede modificarse según las necesidades de cada cliente.
Para llevar a cabo la tarea anterior es recomendable que el desarrollador a cargo de consumir los servicios proporcionados por la API tenga al menos manejo de los siguientes puntos:
-
Manejo de algún lenguaje de programación.
-
Experiencia en el consumo de servicios de tipo Rest.
-
Manejo de estructuras JSON.
Conceptos Básicos de la API
Si estás leyendo esto es porque probablemente es la primera vez que utilizaras la API de Rindegastos, por lo tanto lo primero que vamos a repasar de manera breve son algunos conceptos básicos de la API Rindegastos.
Los conceptos básicos que debemos manejar en relación al consumo de la API son:
Autenticación: lo primero que debes considerar antes de consumir nuestra API es que para poder usarla se debe pedir a Rindegastos un TOKEN de acceso. Es importante recalcar que sin este TOKEN no podrás hacer absolutamente nada. El token se puede conseguir fácilmente desde la vista de administración en la cuenta de la empresa.
Más información aquí.
Solicitudes: una vez que tengas el TOKEN ya estás listo para consumir nuestra API. Existen variadas plataformas para probar el consumo sin necesidad de pasar directamente a programar (si gustas puedes hacer llamadas usando programas como SOAP UI o Insomnia entre otros) para que te familiarices con la estructura de datos básicos para cada llamada.
Más información aquí.
Definiciones: existen algunas definiciones que debemos considerar ya que nuestra API se compone de distintos objetos (Gasto, Informe de Gasto, Fondo, Usuario y Política de Gasto) dentro de los cuales tenemos distintos métodos que nos permitirán llegar a los datos específicos para cada objeto, Por ejemplo si necesitamos ir a buscar la lista de Usuarios registrados de la empresa, usaremos el método getUsers del objeto Usuario.
Integración Estándar en 3 pasos
Tal como indicamos al principio de este documento nuestro objetivo es explicar de manera breve cómo y cuáles métodos consumir dentro de la API de Rindegastos para obtener información de comprobaciones de gastos y llevar esta información a otro sistema.
Sin más preámbulo, a continuación se enumeran los pasos a seguir, método a método, para cumplir con el flujo de obtención de datos y el respectivo feedback a Rindegastos.
1. Obtención de informes de gastos cerrados y no integrados
Lo primero que haremos será ir a buscar todos los informes de gastos que han sido comprobados, revisados y cerrados (es decir que ya cumplieron con el flujo de aprobación completo) y que no han sido integrados previamente.
Para la tarea anterior utilizaremos el método getExpenseReports del objeto Informe de Gastos. El resultado del consumo de este método será una estructura de datos JSON que incluye un máximo de 100 registros por página, esto significa que si tienes 1000 informes cerrados sin integrar tendrás que llamar al método 10 veces paginando correctamente.
La llamada a este método y a cualquier otro debe incluir en la cabecera el parámetro authorization con el TOKEN asignado a la empresa y los siguientes parámetros de filtro:
- Status = 1 (que significa buscar los reportes cerrados)
- IntegrationStatus = 0 (que significa buscar los informes no integrados).
Por otra parte el método HTTP que utilizaremos para consumir será GET.
Un ejemplo de consumo de este servicio usando CURL sería el siguiente:
curl 'https://api.rindegastos.com/v1/getExpenseReports?Status=1&IntegrationStatus=0' -X GET
-H 'authorization: Bearer {token} ' -H 'Content-Type: application/json'
Lo anterior retornará una estructura de datos JSON con la siguiente información:
{
"Records": {
"TotalRecords": 1,
"Reports": 1,
"Page": 1,
"Pages": 1
},
"ExpenseReports": [
{
"Id": 1,
"Title": "New Expense Report",
"ReportNumber": "1",
"SendDate": "2017-06-27",
"CloseDate": "2017-06-29",
"EmployeeId": 2,
"EmployeeName": "John Lemon",
"EmployeeIdentification": "",
"ApproverId": 4,
"ApproverName": "Apple MacCartney",
"PolicyId": 6,
"PolicyName": "East Devon",
"Status": 1,
"CustomStatus": "",
"FundId": 0,
"FundName": "",
"ReportTotal": 36.99,
"ReportTotalApproved": 36.99,
"Currency": "GBP",
"Note": "Check",
"Integrated": "",
"IntegrationDate": "",
"IntegrationExternalCode": "",
"IntegrationInternalCode": "",
"NbrExpenses": 3,
"NbrApprovedExpenses": 3,
"NbrRejectedExpenses": 0,
"ExtraFields": [
{
"Name": "Costing Code",
"Value": "London",
"Code": "0101"
},
{
"Name": "Due Date",
"Value": "2017-06-20",
"Code": ""
}
],
"Files": [
]
}
]
}
Una vez que tengamos el resultado de la llamada, podemos tomar el resultado y llevarlo a un arreglo en el lenguaje de programación que estemos utilizando. Por ejemplo si estuviésemos usando PHP podríamos usar json_decode para posteriormente hacer un bucle sobre el atributo ExpenseReports para recorrer todos los informes de gastos encontrados.
2. Obtención de los gastos aprobados dentro de cada informe
Ahora que ya tenemos los informes de gastos que no han sido integrados gracias a la llamada getExpenseReports anteriormente detallada, lo que necesitamos hacer es ir a buscar los gastos que están aprobados dentro de cada uno de estos informes de gastos.
Para esto recorrer uno a uno los informes de gastos y para cada uno ejecutar la llamada a un segundo método de la API llamado getExpenses. Este método nos permitirá buscar la lista de gastos incluidos en un informe de gastos específico usando como parámetro de búsqueda el atributo Id, donde Id vendría siendo el identificador del informe de gastos.
Supongamos que este es nuestro código fuente, donde en la variable $json tenemos el resultado de la llamada expuesta en el paso 1:
<?php
//Variable con JSON decodificado
$data = json_decode($json);
//Bucle donde recorremos todas las cabeceras de rendición de gastos
foreach($data->ExpenseReports as $report){
//Id de cada reporte
$id_reporte = $report->Id;
//Llamada a método getExpenses
}
En la llamada al método getExpenses se utiliza la misma metodología de llamada utilizada en la llamada al método getExpenseReports sólo que en esta ocasión nuestro parámetro principal de filtro será ReportId donde pasaremos el valor de Id de cada informe de gastos.
Si tuviésemos que ejecutar dicha llamada usado CURL, sería de la siguiente forma:
curl 'https://api.rindegastos.com/v1/getExpenses?ReportId=1&Status=1' -X GET
-H 'authorization: Bearer (PONER AQUÍ EL TOKEN DE TU EMPRESA)' -H 'Content-Type: application/json'
Nota: ReportId corresponde al Id del informe de gastos y Status corresponde a al valor de estado del gasto (1 = aprobado o 2 = rechazado)
El resultado en formato JSON sería como el siguiente ejemplo:
{
"Records": {
"TotalRecords": 1,
"Expenses": 1,
"Page": 1,
"Pages": 1
},
"Expenses": [
{
"Id": 839910,
"Status": 1,
"Supplier": "PRUEBA ",
"IssueDate": "2017-08-25",
"OriginalAmount": 10000,
"OriginalCurrency": "CLP",
"ExchangeRate": 0,
"Net": 8403,
"Tax": 1597,
"TaxName": "IVA",
"OtherTaxes": 0,
"RetentionName": "",
"Retention": 0,
"Total": 10000,
"Currency": "CLP",
"Reimbursable": false,
"Category": "ALIMENTACION",
"CategoryCode": "610903",
"CategoryGroup": "",
"CategoryGroupCode": "",
"Note": 0,
"IntegrationDate": "",
"IntegrationExternalCode": "",
"ExtraFields": [
{
"Name": "OT",
"Value": "",
"Code": ""
},
{
"Name": "Tipo de Documento",
"Value": "DOCUMENTO FUERA DE PLAZO",
"Code": "87|EL|IVA_NR"
},
{
"Name": "N° Documento",
"Value": "5555",
"Code": ""
},
{
"Name": "Rut",
"Value": "77607420-9",
"Code": ""
},
{
"Name": "Sucursal",
"Value": "S60 - CASA MATRIZ",
"Code": "S60"
},
{
"Name": "Area",
"Value": "A63 - GAF Y ADMIN",
"Code": "A63"
},
{
"Name": "Centro de Costo",
"Value": "C0506001 - STGO SOL NEG TRAD",
"Code": "C0506001"
}
],
"Files": [
{
"FileName": "DATOS BANCARIOS.JPG",
"Extension": "jpg",
"Original": "https://ppstatic.s3.amazonaws.com/expenses/uploads/original/1-384-59d2906e02993-1506971758-538.jpg",
"Large": "https://ppstatic.s3.amazonaws.com/expenses/uploads/large/1-384-59d2906e02993-1506971758-538.jpg",
"Medium": "https://ppstatic.s3.amazonaws.com/expenses/uploads/medium/1-384-59d2906e02993-1506971758-538.jpg",
"Small": "https://ppstatic.s3.amazonaws.com/expenses/uploads/small/1-384-59d2906e02993-1506971758-538.jpg"
}
],
"NbrFiles": 1,
"ReportId": 129906,
"ExpensePolicyId": 10212,
"UserId": 5474
}
]
}
A partir del resultado anterior, la operación a seguir para leer el contenido del JSON es similar a la de cuando recorrimos los informes de gastos. Ejemplo:
<?php
//Variable con JSON decodificado
$dataGasto = json_decode($json);
//Bucle donde recorremos todas las cabeceras de rendición de gastos
foreach($dataGasto>Expenses as $expense){
//datos del gasto
$id = $expense>Id;
$proveedor = $expense->Supplier;
$total = $expense->Total;
$cuenta_gasto = $expense->CategoryCode;
//SUB PASO 1 validar /insertar datos
//SUB PASO 2 Registrar resultado integración gasto
}
En el código de ejemplo anterior hemos puestos dos subpasos que ya tienen relación con lo que deseas hacer con los datos obtenidos. Por ejemplo en el SUB PASO 1 puedes guardar la información de gastos obtenida en el libro diario de tu empresa, y si el resultado de la inserción es correcta puedes marcar en Rindegastos el gasto específico como Integrado. Esto se realiza usando el método setExpenseIntegration que permite marcar el gasto como integrado y asignar un número de comprobante a este mismo. De esta manera un gasto queda integrado en ambos sistemas.
3. Finalizar la tarea de comunicación de comprobaciones.
Para finalizar la tarea de comunicación de comprobaciones, se deben marcar como integrados los informes de gastos procesados en Rindegastos. Para esta tarea es necesario llamar a un último método llamado setExpenseReportIntegration. De esta forma al marcar como integrado un informe de gastos, la próxima vez que llamemos al método getExpenseReports filtrando solo por los informes no integrados (IntegrationStatus = 0), no tendremos información duplicada.
Resumen de lo visto
En resumen, la metodología recomendada a seguir, quedaría de la siguiente forma:
<?php
//>PASO 1 leer la lista de reportes no integrados usando método getExpenseReports
//>Variable con JSON decodificado
$data = json_decode($jsonReportes);
//>Bucle donde recorremos todas las cabeceras de rendición de gastos
foreach($data->ExpenseReports as $report){
//>Id de cada reporte
$id_reporte = $report->Id;
//>OBTENER LOS GASTOS DE UNA RENDICION USANDO EL ID DEL REPORTE $id_reporte
$dataGasto = json_decode($jsonGastos);
//>Bucle donde recorremos todas las cabeceras de rendición de gastos
foreach($dataGasto>Expenses as $expense){
//datos del gasto
$id = $expense>Id;
$proveedor = $expense->Supplier;
$total = $expense->Total;
$cuenta_gasto = $expense->CategoryCode;
[...]
//SUB PASO 1 validar /insertar datos
//SUB PASO 2 Registrar resultado integración gasto setExpenseIntegration (opcional)
}
//>SI LA INFORMACIÓN DE LOS GASTOS FUE INSERTADA CON ÉXITO EN EL SUB PASO 1, SE RECOMIENDA APLICAR UN SUB PASO 3
//>DONDE SE MARQUE EN RINDEGASTOS LA RENDICIÓN COMO INTEGRADA setExpenseReportIntegration (obligatorio para esta forma de integración)
}