API para descarga masiva de los datos

Servicio permite la preparación de datos bajo petición del usuario la descarga rápida completa o por partes. El servicio maneja los mismos tipos de datos como el resto de API y genera una lista de objetos en el formato JSON. Diferentes tipos de datos pueden tener filtros para especificar exactamente el dato.

Conjuntos de datos disponibles

Parámetro Tipo Descripción
articulos lista de Articulo
Devuelve la lista de artículos.
incluir_ficheros_adjuntos bool True si quiere incluir los ficheros adjuntos como la imagen de producto. Por defecto es False.
 
articulos_lotes lista de ArticuloLote
Devuelve la lista de artículos lotes.
incluir_ficheros_adjuntos bool True si quiere incluir las imágenes del lote. Por defecto es False.
 
centros_coste lista de CentroCoste
Devuelve la lista centros de coste.
 
cliente_tipos lista de TipoCliente
Devuelve la lista de tipos de clientes.
 
compras lista de Compra
Obtener el histórico de compras entre fechas indicadas (de 0:00 hasta 24:00).
fecha_desde datetime Indica la fecha desde la cual se van a obtener las compras.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener las compras.
 
descuentos lista de Descuento
Obtener la lista de descuentos de precios de los artículos para hoy y los próximos 7 días.
 
deudas lista de Deuda
Devuelve la lista de deudas activas de los clientes. Indica incluir_deudas o incluir_efectos para indicar que tipo de deuda hay que incluir. Si no indica nada se incluirán ambos.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener las deudas o efectos.
incluir_deudas bool True si quiere incluir deudas.
incluir_efectos bool True si quiere incluir efectos.
incluir_liquidado bool True si quiere incluir liquidados.
fecha_desde datetime Indica la fecha desde la cual se van a obtener las deudas o efectos, solo se debe indicar si 'incluir liquidado' es True. El periodo máximo es de 12 meses
 
diario lista de Asiento
Devuelve la lista de asientos. Tiene que indicar las fechas.
fecha_desde datetime Indica la fecha desde la cual se van a obtener los asientos.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener los asientos.
 
empleados lista de Empleado
Devuelve la lista de empleados.
 
facturas_contables lista de FacturasContables
Devuelve todas las facturas contables entre dos fechas indicadas.
fecha_desde datetime Indica la fecha de registro desde la cual se van a obtener las facturas contables.
fecha_hasta datetime Indica la fecha de registro hasta la cual se van a obtener las facturas contables.
 
formas_pago lista de FormaPago
Devuelve la lista de formas de pago.
 
interlocutores lista de InterlocutorComercial
Devuelve los interlocutores, todos o filtrados por tipo.
tipo string Indica el tipo de interlocutor para generar: cliente, proveedor o acreedor.
modificado_desde datetime Obtener solo interlocutores modificados desde la fecha indicada.
 
movimientos lista de MovimientoAlmacen
Devuelve todos los movimientos de almacén entre dos fechas indicadas.
fecha_desde datetime Indica la fecha desde la cual se van a obtener las compras.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener las compras.
 
stocks lista de FormatoStock
Devuelve todos los formatos con el stock calculado.
 
subcuentas lista de Subcuenta
Devuelve la lista de subcuentas contables.
 
tarifas lista de Tarifa
Obtener la lista de tarifas de precios de los artículos.
 
vehiculos lista de Vehiculo
Devuelve la lista de vehículos.
 
ventas lista de Venta
Obtener el histórico de ventas entre las fechas indicadas. El intervalo esta limitado a un año.
fecha_desde datetime Indica la fecha desde la cual se van a obtener las ventas.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener las ventas.
incluir_pedidos bool True si hay que incluir pedidos. Por defecto (False) solo devuelve albaranes y facturas directas.
todos_estados bool True si hay que incluir documentos en todos los estados. Por defecto (False) solo incluye estados que bloquean el documento (Bloqueado, Facturado, Rectificado)
modificado_desde datetime Obtener solo ventas modificadas desde la fecha indicada.
 
ventas_facturas lista de VentaFactura
Devuelve todas las facturas de ventas entre dos fechas indicadas.
fecha_desde datetime Indica la fecha desde la cual se van a obtener las compras.
fecha_hasta datetime Indica la fecha hasta la cual se van a obtener las compras.
 

Ejecuta el servicio en 3 pasos

  1. POST /api_v1/generar_xxl
    Envía la lista de PeticionGenerarXXL. Puede indicar varios conjuntos de datos, pero cada dataset solo puede aparecer una vez.
    [
        {
            "dataset": "interlocutores",
        }
    ]

    Puede indicar una url de webhook de su servidor donde se recibirá el estado de la generación de los datos masivos(EstadoGenerarXXL).
    [
        {
            "dataset": "interlocutores",
            "webhook": "https://www.ejemplo.com/"
        }
    ]

    Puede indicar parámetros:
    [
        {
            "dataset": "interlocutores",
            "tipo": "proveedor"
        }
    ]

    La llamada pone la preparación de los datos a la cola y devuelve inmediatamente la confirmación EstadoGenerarXXL.
    {
        "peticion_id": "575c9ac3-4ea7-40f3-8407-fc8b56b7463b",
        "fecha_peticion": "2023-05-06T13:27:46",
        "error_message": "",
        "estado": "PENDING",
        "datasets": [
            {
                "dataset": "interlocutores",
                "estado": "PENDING",
                "fecha_generacion_inicio": None,
                "fecha_generacion_fin": None,
                "numero_registros": 0,
                "error_message": ""
            }
        ]
    }


    peticion_id es el identificador de esta petición y sirve para controlar su estado y para obtener los datos.
  2. GET /api_v1/estado_xxl
    GET /api_v1/estado_xxl/<peticion_id>
    La llamado devuelve EstadoGenerarXXL actualizado para la petición indicada. Si no indica peticion_id devuelve lista de estados de todas las petición del usuario. Las peticiones se eliminan automáticamente después de 12 horas.
    Tiene que revisar el estado de la petición, si es OK puede descargar los datos.
    El proceso de generación es lento, si el estado es PENDING debería esperar varios minutos antes de volver a comprobarlo. Si el estado es ERROR puede revisar error_message del mensaje.
    {
        "peticion_id": "575c9ac3-4ea7-40f3-8407-fc8b56b7463b",
        "fecha_peticion": "2023-05-06T13:27:46",
        "error_message": "",
        "estado": "OK",
        "datasets": [
            {
                "dataset": "interlocutores",
                "estado": "OK",
                "fecha_generacion_inicio": "2023-05-06T13:28:00",
                "fecha_generacion_fin": "2023-05-06T13:28:30",
                "numero_registros": 6534,
                "error_message": ""
            }
        ]
    }

  3. GET /datos_xxl/<peticion_id>/<dataset>
    GET /datos_xxl/<peticion_id>/<dataset>/<offset>/<limit>
    La llamada devuelve la lista de objetos generados. El tipo depende del tipo de conjunto de datos (dataset).
    Si no indica offset y limit la llamada devuelve todos los datos preparados. Utiliza numero_registros del EstadoDatasetXXL para controlar el numero de páginas.

Ejemplo de código

Ejemplo en python de generación y de la descarga de los datos masivos.


import requests
import os
import time

AUTH_SERVER_URL = "http://127.0.0.1:5000/"
AUTH_USER = "pruebas.admin"
AUTH_PASS = ""
API_NOMBRE = "xxl"
DOMAIN = "pruebas"
DOMAIN_SERVER_URL = "http://127.0.0.1:5000/"
DOMAIN_USER = "pruebas.admin"
DOMAIN_PASS = ""


def get_token():
    """
    implementa obtencion del token
    """
    apireq = {
        "domain": DOMAIN,
        "api": API_NOMBRE
    }

    r = requests.post(AUTH_SERVER_URL + "api_token/", auth=(AUTH_USER, AUTH_PASS), json=apireq, verify=False)
    if r.status_code == 555:
        raise ValueError("Error: {}".format(r.json()["error"]))
    else:
        r.raise_for_status()

    return r.json()["WINFRA-API-TOKEN"]


def api(token, path, data=None, raw=False):
    """
    implementa acceso a API y controla los errores
    """
    url = DOMAIN_SERVER_URL + "api_v1/" + path
    if data is None:
        method = "GET"
        r = requests.get(
            url,
            auth=(DOMAIN_USER, DOMAIN_PASS),
            headers={"WINFRA-API-TOKEN": token},
            verify=False
        )
    else:
        method = "POST"
        r = requests.post(
            url,
            auth=(DOMAIN_USER, DOMAIN_PASS),
            headers={"WINFRA-API-TOKEN": token},
            verify=False,
            json=data
        )

    print(f"{r.status_code} {method} {url}")

    if r.status_code in (555, 401, 422):
        raise ValueError("{}: {}".format(r.status_code, r.json()["error"]))
    else:
        r.raise_for_status()

    if raw:
        return r.content
    else:
        return r.json()


def xxl():
    """
    crear la peticion para generar los datos masivos y descargarlos
    """
    # obtener token
    t = get_token()

    # enviar peticion para generar los interlocutores de tipo proveedor y los articulos
    r = api(t, "generar_xxl", data=[
        {"dataset": "interlocutores", "tipo": "proveedor"},
        {"dataset": "articulos", },
    ])
    # id de la peticion
    pid = r["peticion_id"]
    print(f"Peticion {pid} creada...")

    # esperar hasta que se generen los datos
    while True:
        # obtener estado
        r = api(t, f"estado_xxl/{pid}")
        estado = r['estado']
        print(f"   {estado}")
        # si el estado es OK o ERROR ya esta acabado
        if estado == "OK" or estado == "ERROR":
            break

        # espero 10 minutos antes de volver a comprobar el estado
        time.sleep(10 * 60)

    # controlo el error
    if estado == "ERROR":
        print("Ocurrio un error en la generación de los datos:")
        for ds in r["datasets"]:
            if ds["estado"] == "ERROR":
                print(f"   {ds['dataset']} {ds['error_message']}")
    else:
        # generación ha funcionado, voy a descargar los datos
        print("Descargando datos...")
        pid = r["peticion_id"]
        # voy a descargar por bloques de 100 registros
        # esto no es necesario, si no hay muchos datos puede descargar todo de golpe
        limit = 100
        for ds in r["datasets"]:
            # nombre de conjunto generado
            dataset = ds['dataset']
            # numero de registros generados
            numero_registros = ds['numero_registros']
            print(f"   {dataset}: {numero_registros} registros.")

            # repetir la descarga desde 0 hasta numero de registros por bloque de 100
            for offset in range(0, numero_registros, limit):
                # obtener los datos
                r = api(t, f"datos_xxl/{pid}/{dataset}/{offset}/{limit}", raw=True)

                # escribir los datos a fichero como ejemplo
                with open(f"xxl.{dataset}.{offset}.json", "wb") as f:
                    f.write(r)

    print("Finalizado")


xxl()