def on_get(self, req, resp): """Obtiene informacion de todos los proveedores. Permite filtrar y paginar los resultados. El paginamiento es de 10 elementos por pagina y es opcional. **Nota**: Para usar un mismo filtro con diferentes valores, se debe usar el parametro tantas veces como sea necesario. e.g.: `?proveedor=6&proveedor=8`. El filtro se aplicara usando la disyuncion de los valores. i.e: ... `proveedor = 6 OR proveedor = 8`. El filtro ``q`` no puede ser usado de esta forma. **Nota**: El campo `monto_adjudicado` de la respuesta solo tiene un valor si se ha usado el filtro ``monto_adjudicado`` en el request, si no, es ``null``. Los parametros aceptados son: Filtros ============================== ================== ============================================================ Parámetro Ejemplo Descripción ============================== ================== ============================================================ ``q`` clavos y martillos Busqueda de texto ``proveedor`` 1 Por ID de proveedor ``fecha_adjudicacion`` 20140101|20141231 Por fecha de adjudicacion de licitaciones ``organismo_adjudicador`` 1 Por ID de organismos que han les concedido licitaciones ``n_licitaciones_adjudicadas`` 10|20 Por cantidad de licitaciones adjudicadas ``monto_adjudicado`` 10000|1000000 Por monto adjudicado en licitaciones ============================== ================== ============================================================ Modificadores ============================== ================ ============================================================ Parámetro Ejemplo Descripción ============================== ================ ============================================================ ``orden`` monto_adjudicado Ordenar los resultados ``pagina`` 1 Paginar y entregar la pagina solicitada ============================== ================ ============================================================ """ # Preparar los filtros y operaciones variables selects = [ models_api.ProveedorOrganismoCruce.empresa, models_api.ProveedorOrganismoCruce.nombre_empresa, models_api.ProveedorOrganismoCruce.rut_sucursal ] wheres = [] joins = [] order_bys = [] # Busqueda de texto q_q = req.params.get('q', None) if q_q: # TODO Hacer esta consulta sobre un solo indice combinado en lugar de usar dos filtros separados por OR wheres.append(ts_match(models_api.ProveedorOrganismoCruce.nombre_empresa, q_q) | ts_match(models_api.ProveedorOrganismoCruce.rut_sucursal, q_q)) # Filtrar por proveedor q_proveedor = req.params.get('proveedor', None) if q_proveedor: if isinstance(q_proveedor, basestring): q_proveedor = [q_proveedor] try: q_proveedor = map(lambda x: int(x), q_proveedor) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "proveedor debe ser un entero") wheres.append(models_api.ProveedorOrganismoCruce.empresa << q_proveedor) # Filtrar por fecha de adjudicacion q_fecha_adjudicacion = req.params.get('fecha_adjudicacion', None) if q_fecha_adjudicacion: if isinstance(q_fecha_adjudicacion, basestring): q_fecha_adjudicacion = [q_fecha_adjudicacion] filter_fecha_adjudicacion = [] for fechas in q_fecha_adjudicacion: fechas = fechas.split('|') try: fecha_adjudicacion_min = dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None fecha_adjudicacion_max = dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en fecha_adjudicacion deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "El formato de la fecha en fecha_adjudicacion no es correcto") if fecha_adjudicacion_min and fecha_adjudicacion_max: filter_fecha_adjudicacion.append((models_api.ProveedorOrganismoCruce.fecha_adjudicacion >= fecha_adjudicacion_min) & (models_api.ProveedorOrganismoCruce.fecha_adjudicacion <= fecha_adjudicacion_max)) elif fecha_adjudicacion_min: filter_fecha_adjudicacion.append(models_api.ProveedorOrganismoCruce.fecha_adjudicacion >= fecha_adjudicacion_min) elif fecha_adjudicacion_max: filter_fecha_adjudicacion.append(models_api.ProveedorOrganismoCruce.fecha_adjudicacion <= fecha_adjudicacion_max) if filter_fecha_adjudicacion: wheres.append(reduce(operator.or_, filter_fecha_adjudicacion)) # Filtrar por organismo_adjudicador q_organismo_adjudicador = req.params.get('organismo_adjudicador', None) if q_organismo_adjudicador: if isinstance(q_organismo_adjudicador, basestring): q_organismo_adjudicador = [q_organismo_adjudicador] try: q_organismo_adjudicador = map(lambda x: int(x), q_organismo_adjudicador) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "organismo_adjudicador debe ser un entero") wheres.append(models_api.ProveedorOrganismoCruce.organismo << q_organismo_adjudicador) # Filtrar por n_licitaciones_adjudicadas q_n_licitaciones_adjudicadas = req.params.get('n_licitaciones_adjudicadas') if q_n_licitaciones_adjudicadas: if isinstance(q_n_licitaciones_adjudicadas, basestring): q_n_licitaciones_adjudicadas = [q_n_licitaciones_adjudicadas] filter_n_licitaciones_adjudicadas = [] for n_licitaciones in q_n_licitaciones_adjudicadas: n_licitaciones = n_licitaciones.split('|') try: n_licitaciones_adjudicadas_min = int(n_licitaciones[0]) if n_licitaciones[0] else None n_licitaciones_adjudicadas_max = int(n_licitaciones[1]) if n_licitaciones[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en n_licitaciones_adjudicadas deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "n_licitaciones_adjudicadas debe ser un entero") if n_licitaciones_adjudicadas_min is not None and n_licitaciones_adjudicadas_max is not None: filter_n_licitaciones_adjudicadas.append( (peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) >= n_licitaciones_adjudicadas_min) & (peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) <= n_licitaciones_adjudicadas_max) ) elif n_licitaciones_adjudicadas_min is not None: filter_n_licitaciones_adjudicadas.append( peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) >= n_licitaciones_adjudicadas_min ) elif n_licitaciones_adjudicadas_max is not None: filter_n_licitaciones_adjudicadas.append( peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) <= n_licitaciones_adjudicadas_max ) if filter_n_licitaciones_adjudicadas: filter_n_licitaciones_adjudicadas = reduce(operator.or_, filter_n_licitaciones_adjudicadas) proveedores_n_licitaciones = models_api.ProveedorOrganismoCruce.select( models_api.ProveedorOrganismoCruce.empresa, peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) ) if wheres: proveedores_n_licitaciones = proveedores_n_licitaciones.where(*wheres) proveedores_n_licitaciones = proveedores_n_licitaciones.group_by( models_api.ProveedorOrganismoCruce.empresa ).having( filter_n_licitaciones_adjudicadas ) proveedores_ids = [proveedor_n_licitaciones['empresa'] for proveedor_n_licitaciones in proveedores_n_licitaciones.dicts().iterator()] wheres.append(models_api.ProveedorOrganismoCruce.empresa << proveedores_ids if proveedores_ids else False) # Filtrar por monto_adjudicado q_monto_adjudicado = req.params.get('monto_adjudicado') if q_monto_adjudicado: if isinstance(q_monto_adjudicado, basestring): q_monto_adjudicado = [q_monto_adjudicado] filter_monto_adjudicado = [] for monto_adjudicado in q_monto_adjudicado: monto_adjudicado = monto_adjudicado.split('|') try: monto_adjudicado_min = int(monto_adjudicado[0]) if monto_adjudicado[0] else None monto_adjudicado_max = int(monto_adjudicado[1]) if monto_adjudicado[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en monto_adjudicado deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "monto_adjudicado debe ser un entero") if monto_adjudicado_min is not None and monto_adjudicado_max: filter_monto_adjudicado.append( (peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) >= monto_adjudicado_min) & (peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) <= monto_adjudicado_max) ) elif monto_adjudicado_min is not None: filter_monto_adjudicado.append( peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) >= monto_adjudicado_min ) elif monto_adjudicado_max is not None: filter_monto_adjudicado.append( peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) <= monto_adjudicado_max ) if filter_monto_adjudicado: filter_monto_adjudicado = reduce(operator.or_, filter_monto_adjudicado) proveedores_montos = models_api.ProveedorOrganismoCruce.select( models_api.ProveedorOrganismoCruce.empresa, peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total).alias('monto_adjudicado') ) if wheres: proveedores_montos = proveedores_montos.where(*wheres) proveedores_montos = proveedores_montos.group_by( models_api.ProveedorOrganismoCruce.empresa ).having( filter_monto_adjudicado ).alias('proveedores_montos') selects.append(proveedores_montos.c.monto_adjudicado) joins.append([ proveedores_montos, peewee.JOIN_INNER, (models_api.ProveedorOrganismoCruce.empresa == proveedores_montos.c.empresa_id) ]) q_orden = req.params.get('orden', None) if q_orden == 'monto_adjudicado': order_bys.append(proveedores_montos.c.monto_adjudicado.asc()) elif q_orden == '-monto_adjudicado': order_bys.append(proveedores_montos.c.monto_adjudicado.desc()) # Construir query proveedores = models_api.ProveedorOrganismoCruce.select(*selects) # Aplicar filtros if wheres: proveedores = proveedores.where(*wheres) if joins: for join in joins: proveedores = proveedores.join(*join) if order_bys: proveedores = proveedores.order_by(*order_bys) proveedores = proveedores.distinct() n_proveedores = proveedores.count() # Aplicar paginamiento q_page = req.params.get('pagina', None) if q_page: q_page = max(int(q_page) if q_page.isdigit() else 1, 1) proveedores = proveedores.paginate(q_page, 10) # Construir la respuesta response = { 'n_proveedores': n_proveedores, 'proveedores': [ { 'id': proveedor['empresa'], 'nombre': proveedor['nombre_empresa'], 'rut': proveedor['rut_sucursal'], 'monto_adjudicado': int(proveedor['monto_adjudicado']) if 'monto_adjudicado' in proveedor else None } for proveedor in proveedores.dicts()] } # Codificar la respuesta en JSON resp.body = json.dumps(response, cls=JSONEncoderPlus, sort_keys=True)
def on_get(self, req, resp): """Obtiene informacion de todas las licitaciones. Permite filtrar y paginar los resultados. El paginamiento es de 10 elementos por pagina y es obligatorio. **Nota**: Para usar un mismo filtro con diferentes valores, se debe usar el parametro tantas veces como sea necesario. e.g.: `?organismo=6&organismo=8`. El filtro se aplicara usando la disyuncion de los valores. i.e.: `... organismo = 6 OR organismo = 8`. El filtro ``q`` no puede ser usado de esta forma. **Nota**: El paginamiento es obligatorio para evitar que una consulta retorne tantos reultados que puedan perjudicar el rendimiento del sistema. Los parametros aceptados son: Filtros ====================== ================== =========================== Parámetro Ejemplo Descripción ====================== ================== =========================== ``q`` clavos y martillos Busqueda de texto ``categoria_producto`` 1 Por categorias de sus items ``producto`` 1 Por productos en sus items ``estado`` 1 Por su estado ``monto`` 1000|2000 Por el monto adjudicado ``fecha_publicacion`` 20140101|20141231 Por fecha de publicacion ``fecha_cierre`` 20140101|20141231 Por fecha de cierre ``fecha_adjudicacion`` 20140101|20141231 Por fecha de adjudicacion ``organismo`` 1 Por organismo emisor ``proveedor`` 1 Por proveedor adjudicado ====================== ================== =========================== Modificadores ========== ================= ======================================= Parámetro Ejemplo Descripción ========== ================= ======================================= ``orden`` fecha_publicacion Ordenar los resultados ``pagina`` 1 Paginar y entregar la pagina solicitada ========== ================= ======================================= :param req: Falcon request object :param resp: Falcon response object :return: """ # Obtener todas las licitacion licitaciones = models_api.Licitacion.select() # Preparar las listas de filtros que se van a aplicar wheres = [] order_bys = [] # Busqueda de texto q_q = req.params.get("q", None) if q_q: # TODO Hacer esta consulta sobre un solo indice combinado en lugar de usar dos filtros separados por OR wheres.append( ts_match(models_api.Licitacion.nombre_licitacion, q_q) | ts_match(models_api.Licitacion.descripcion_licitacion, q_q) ) # Filtrar por id q_id = req.params.get("id", None) if q_id: if isinstance(q_id, basestring): q_id = [q_id] try: q_id = map(lambda x: int(x), q_id) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "id debe ser un entero") wheres.append(models_api.Licitacion.id_licitacion << q_id) # Filtrar por categoria de producto q_categoria_producto = req.params.get("categoria_producto", None) if q_categoria_producto: if isinstance(q_categoria_producto, basestring): q_categoria_producto = [q_categoria_producto] try: q_categoria_producto = map(lambda x: int(x), q_categoria_producto) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "categoria_producto debe ser un entero") wheres.append(models_api.Licitacion.id_categoria_nivel1.contains_any(q_categoria_producto)) # Filtrar por producto q_producto = req.params.get("producto", None) if q_producto: if isinstance(q_producto, basestring): q_producto = [q_producto] try: q_producto = map(lambda x: int(x), q_producto) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "producto debe ser un entero") wheres.append(models_api.Licitacion.id_categoria_nivel3.contains_any(q_producto)) # Filtrar por estado q_estado = req.params.get("estado", None) if q_estado: if isinstance(q_estado, basestring): q_estado = [q_estado] try: q_estado = map(lambda x: int(x), q_estado) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "estado debe ser un entero") wheres.append(models_api.Licitacion.estado << q_estado) # Filtrar por organismo q_organismo = req.params.get("organismo", None) if q_organismo: if isinstance(q_organismo, basestring): q_organismo = [q_organismo] try: q_organismo = map(lambda x: int(x), q_organismo) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "organismo debe ser un entero") wheres.append(models_api.Licitacion.id_organismo << q_organismo) # Filtrar por proveedor q_proveedor = req.params.get("proveedor", None) if q_proveedor: if isinstance(q_proveedor, basestring): q_proveedor = [q_proveedor] try: q_proveedor = map(lambda x: int(x), q_proveedor) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "proveedor debe ser un entero") wheres.append(models_api.Licitacion.empresas_ganadoras.contains_any(q_proveedor)) # Filtrar por monto q_monto = req.params.get("monto", None) if q_monto: if isinstance(q_monto, basestring): q_monto = [q_monto] filter_monto = [] for montos in q_monto: montos = montos.split("|") try: monto_min = int(montos[0]) if montos[0] else None monto_max = int(montos[1]) if montos[1] else None except IndexError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "Los valores en monto deben estar separados por un pipe [|]" ) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en monto deben ser enteros") if monto_min and monto_max: filter_monto.append( (models_api.Licitacion.monto_total >= monto_min) & (models_api.Licitacion.monto_total <= monto_max) ) elif monto_min: filter_monto.append(models_api.Licitacion.monto_total >= monto_min) elif monto_max: filter_monto.append(models_api.Licitacion.monto_total <= monto_max) if filter_monto: wheres.append(reduce(operator.or_, filter_monto)) # Filtrar por fecha de publicacion q_fecha_publicacion = req.params.get("fecha_publicacion", None) if q_fecha_publicacion: if isinstance(q_fecha_publicacion, basestring): q_fecha_publicacion = [q_fecha_publicacion] filter_fecha_publicacion = [] for fechas in q_fecha_publicacion: fechas = fechas.split("|") try: fecha_publicacion_min = ( dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None ) fecha_publicacion_max = ( dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None ) except IndexError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "Los valores en fecha_publicacion deben estar separados por un pipe [|]" ) except ValueError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "El formato de la fecha en fecha_publicacion no es correcto" ) if fecha_publicacion_min and fecha_publicacion_max: filter_fecha_publicacion.append( (models_api.Licitacion.fecha_publicacion >= fecha_publicacion_min) & (models_api.Licitacion.fecha_publicacion <= fecha_publicacion_max) ) elif fecha_publicacion_min: filter_fecha_publicacion.append(models_api.Licitacion.fecha_publicacion >= fecha_publicacion_min) elif fecha_publicacion_max: filter_fecha_publicacion.append(models_api.Licitacion.fecha_publicacion <= fecha_publicacion_max) if filter_fecha_publicacion: wheres.append(reduce(operator.or_, filter_fecha_publicacion)) # Filtrar por fecha de cierre q_fecha_cierre = req.params.get("fecha_cierre", None) if q_fecha_cierre: if isinstance(q_fecha_cierre, basestring): q_fecha_cierre = [q_fecha_cierre] filter_fecha_cierre = [] for fechas in q_fecha_cierre: fechas = fechas.split("|") try: fecha_cierre_min = ( dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None ) fecha_cierre_max = ( dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None ) except IndexError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "Los valores en fecha_cierre deben estar separados por un pipe [|]" ) except ValueError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "El formato de la fecha en fecha_cierre no es correcto" ) if fecha_cierre_min and fecha_cierre_max: filter_fecha_cierre.append( (models_api.Licitacion.fecha_cierre >= fecha_cierre_min) & (models_api.Licitacion.fecha_cierre <= fecha_cierre_max) ) elif fecha_cierre_min: filter_fecha_cierre.append(models_api.Licitacion.fecha_cierre >= fecha_cierre_min) elif fecha_cierre_max: filter_fecha_cierre.append(models_api.Licitacion.fecha_cierre <= fecha_cierre_max) if filter_fecha_cierre: wheres.append(reduce(operator.or_, filter_fecha_cierre)) # Filtrar por fecha de adjudicacion q_fecha_adjudicacion = req.params.get("fecha_adjudicacion", None) if q_fecha_adjudicacion: if isinstance(q_fecha_adjudicacion, basestring): q_fecha_adjudicacion = [q_fecha_adjudicacion] filter_fecha_adjudicacion = [] for fechas in q_fecha_adjudicacion: fechas = fechas.split("|") try: fecha_adjudicacion_min = ( dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None ) fecha_adjudicacion_max = ( dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None ) except IndexError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "Los valores en fecha_adjudicacion deben estar separados por un pipe [|]", ) except ValueError: raise falcon.HTTPBadRequest( "Parametro incorrecto", "El formato de la fecha en fecha_adjudicacion no es correcto" ) if fecha_adjudicacion_min and fecha_adjudicacion_max: filter_fecha_adjudicacion.append( (models_api.Licitacion.fecha_adjudicacion >= fecha_adjudicacion_min) & (models_api.Licitacion.fecha_adjudicacion <= fecha_adjudicacion_max) ) elif fecha_adjudicacion_min: filter_fecha_adjudicacion.append(models_api.Licitacion.fecha_adjudicacion >= fecha_adjudicacion_min) elif fecha_adjudicacion_max: filter_fecha_adjudicacion.append(models_api.Licitacion.fecha_adjudicacion <= fecha_adjudicacion_max) if filter_fecha_adjudicacion: wheres.append(reduce(operator.or_, filter_fecha_adjudicacion)) # Aplicar ordenamiento q_orden = req.params.get("orden", None) if q_orden: if q_orden == "monto": wheres.append(models_api.Licitacion.monto_total.is_null(False)) order_bys.append(models_api.Licitacion.monto_total.asc()) elif q_orden == "-monto": wheres.append(models_api.Licitacion.monto_total.is_null(False)) order_bys.append(models_api.Licitacion.monto_total.desc()) elif q_orden == "fecha_publicacion": wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_publicacion.asc()) elif q_orden == "-fecha_publicacion": wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_publicacion.desc()) elif q_orden == "fecha_cierre": wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_cierre.asc()) elif q_orden == "-fecha_cierre": wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_cierre.desc()) # Aplicar filtros if wheres: licitaciones = licitaciones.where(*wheres) if order_bys: licitaciones = licitaciones.order_by(*order_bys) # Aplicar paginamiento q_pagina = req.params.get("pagina", "1") q_pagina = max(int(q_pagina) if q_pagina.isdigit() else 1, 1) response = { "n_licitaciones": licitaciones.count(), "licitaciones": [ { # Identificadores "id": licitacion["id_licitacion"], "codigo": licitacion["codigo_licitacion"], # Descriptores "nombre": licitacion["nombre_licitacion"], "descripcion": licitacion["descripcion_licitacion"], # Organismo emisor "organismo": { "id": licitacion["id_organismo"], "categoria": licitacion["nombre_ministerio"], "nombre": licitacion["nombre_organismo"], }, # Fechas "fecha_publicacion": licitacion["fecha_publicacion"], "fecha_cierre": licitacion["fecha_cierre"], "fecha_adjudicacion": licitacion["fecha_adjudicacion"], # Estado "estado": licitacion["estado"], "fecha_cambio_estado": licitacion["fecha_cambio_estado"], # Items "n_items": licitacion["items_totales"], # Adjudicacion "adjudicacion": { "n_items": licitacion["items_adjudicados"], "monto": int(licitacion["monto_total"]) if licitacion["monto_total"] else None, "acta": licitacion["url_acta"], } if licitacion["monto_total"] else None, # Only if there is monto_total } for licitacion in licitaciones.paginate(q_pagina, Licitacion.MAX_RESULTS).dicts() ], } resp.body = json.dumps(response, cls=JSONEncoderPlus, sort_keys=True)
def on_get(self, req, resp): # Obtener todas las licitacion licitaciones = models_api.Licitacion.select() wheres = [] order_bys = [] # Busqueda de texto q_q = req.params.get('q', None) if q_q: # TODO Try to make just one query over one index instead of two or more ORed queries wheres.append(ts_match(models_api.Licitacion.nombre_licitacion, q_q) | ts_match(models_api.Licitacion.descripcion_licitacion, q_q)) # Busqueda por categoria de producto q_categoria_producto = req.params.get('categoria_producto', None) if q_categoria_producto: if isinstance(q_categoria_producto, basestring): q_categoria_producto = [q_categoria_producto] try: q_categoria_producto = map(lambda x: int(x), q_categoria_producto) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "categoria_producto debe ser un entero") wheres.append(models_api.Licitacion.id_categoria_nivel1.contains_any(q_categoria_producto)) # Busqueda por producto q_producto = req.params.get('producto', None) if q_producto: if isinstance(q_producto, basestring): q_producto = [q_producto] try: q_producto = map(lambda x: int(x), q_producto) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "producto debe ser un entero") wheres.append(models_api.Licitacion.id_categoria_nivel3.contains_any(q_producto)) # Busqueda por estado q_estado = req.params.get('estado', None) if q_estado: if isinstance(q_estado, basestring): q_estado = [q_estado] try: q_estado = map(lambda x: int(x), q_estado) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "estado debe ser un entero") wheres.append(models_api.Licitacion.estado << q_estado) # Busqueda por organismo q_organismo = req.params.get('organismo', None) if q_organismo: if isinstance(q_organismo, basestring): q_organismo = [q_organismo] try: q_organismo = map(lambda x: int(x), q_organismo) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "organismo debe ser un entero") wheres.append(models_api.Licitacion.id_organismo << q_organismo) # Busqueda por proveedor q_proveedor = req.params.get('proveedor', None) if q_proveedor: if isinstance(q_proveedor, basestring): q_proveedor = [q_proveedor] try: q_proveedor = map(lambda x: int(x), q_proveedor) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "proveedor debe ser un entero") wheres.append(models_api.Licitacion.empresas_ganadoras.contains_any(q_proveedor)) # Busqueda por monto q_monto = req.params.get('monto', None) if q_monto: if isinstance(q_monto, basestring): q_monto = [q_monto] filter_monto = [] for montos in q_monto: montos = montos.split('|') try: monto_min = int(montos[0]) if montos[0] else None monto_max = int(montos[1]) if montos[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en monto deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en monto deben ser enteros") if monto_min and monto_max: filter_monto.append((models_api.Licitacion.monto_total >= monto_min) & (models_api.Licitacion.monto_total <= monto_max)) elif monto_min: filter_monto.append(models_api.Licitacion.monto_total >= monto_min) elif monto_max: filter_monto.append(models_api.Licitacion.monto_total <= monto_max) if filter_monto: wheres.append(reduce(operator.or_, filter_monto)) # Busqueda por fecha de publicacion q_fecha_publicacion = req.params.get('fecha_publicacion', None) if q_fecha_publicacion: if isinstance(q_fecha_publicacion, basestring): q_fecha_publicacion = [q_fecha_publicacion] filter_fecha_publicacion = [] for fechas in q_fecha_publicacion: fechas = fechas.split('|') try: fecha_publicacion_min = dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None fecha_publicacion_max = dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en fecha_publicacion deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "El formato de la fecha en fecha_publicacion no es correcto") if fecha_publicacion_min and fecha_publicacion_max: filter_fecha_publicacion.append((models_api.Licitacion.fecha_publicacion >= fecha_publicacion_min) & (models_api.Licitacion.fecha_publicacion <= fecha_publicacion_max)) elif fecha_publicacion_min: filter_fecha_publicacion.append(models_api.Licitacion.fecha_publicacion >= fecha_publicacion_min) elif fecha_publicacion_max: filter_fecha_publicacion.append(models_api.Licitacion.fecha_publicacion <= fecha_publicacion_max) if filter_fecha_publicacion: wheres.append(reduce(operator.or_, filter_fecha_publicacion)) # Busqueda por fecha de cierre q_fecha_cierre = req.params.get('fecha_cierre', None) if q_fecha_cierre: if isinstance(q_fecha_cierre, basestring): q_fecha_cierre = [q_fecha_cierre] filter_fecha_cierre = [] for fechas in q_fecha_cierre: fechas = fechas.split('|') try: fecha_cierre_min = dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None fecha_cierre_max = dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en fecha_cierre deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "El formato de la fecha en fecha_cierre no es correcto") if fecha_cierre_min and fecha_cierre_max: filter_fecha_cierre.append((models_api.Licitacion.fecha_cierre >= fecha_cierre_min) & (models_api.Licitacion.fecha_cierre <= fecha_cierre_max)) elif fecha_cierre_min: filter_fecha_cierre.append(models_api.Licitacion.fecha_cierre >= fecha_cierre_min) elif fecha_cierre_max: filter_fecha_cierre.append(models_api.Licitacion.fecha_cierre <= fecha_cierre_max) if filter_fecha_cierre: wheres.append(reduce(operator.or_, filter_fecha_cierre)) # Busqueda por fecha de adjudicacion q_fecha_adjudicacion = req.params.get('fecha_adjudicacion', None) if q_fecha_adjudicacion: if isinstance(q_fecha_adjudicacion, basestring): q_fecha_adjudicacion = [q_fecha_adjudicacion] filter_fecha_adjudicacion = [] for fechas in q_fecha_adjudicacion: fechas = fechas.split('|') try: fecha_adjudicacion_min = dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None fecha_adjudicacion_max = dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en fecha_adjudicacion deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "El formato de la fecha en fecha_adjudicacion no es correcto") if fecha_adjudicacion_min and fecha_adjudicacion_max: filter_fecha_adjudicacion.append((models_api.Licitacion.fecha_adjudicacion >= fecha_adjudicacion_min) & (models_api.Licitacion.fecha_adjudicacion <= fecha_adjudicacion_max)) elif fecha_adjudicacion_min: filter_fecha_adjudicacion.append(models_api.Licitacion.fecha_adjudicacion >= fecha_adjudicacion_min) elif fecha_adjudicacion_max: filter_fecha_adjudicacion.append(models_api.Licitacion.fecha_adjudicacion <= fecha_adjudicacion_max) if filter_fecha_adjudicacion: wheres.append(reduce(operator.or_, filter_fecha_adjudicacion)) q_orden = req.params.get('orden', None) if q_orden: if q_orden == 'monto': wheres.append(models_api.Licitacion.monto_total.is_null(False)) order_bys.append(models_api.Licitacion.monto_total.asc()) elif q_orden == '-monto': wheres.append(models_api.Licitacion.monto_total.is_null(False)) order_bys.append(models_api.Licitacion.monto_total.desc()) elif q_orden == 'fecha_publicacion': wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_publicacion.asc()) elif q_orden == '-fecha_publicacion': wheres.append(models_api.Licitacion.fecha_publicacion.is_null(False)) order_bys.append(models_api.Licitacion.fecha_publicacion.desc()) if wheres: licitaciones = licitaciones.where(*wheres) if order_bys: licitaciones = licitaciones.order_by(*order_bys) # Get page q_pagina = req.params.get('pagina', '1') q_pagina = max(int(q_pagina) if q_pagina.isdigit() else 1, 1) response = { 'n_licitaciones': licitaciones.count(), 'licitaciones': [ { 'id': licitacion['id_licitacion'], 'codigo': licitacion['codigo_licitacion'], 'nombre': licitacion['nombre_licitacion'], 'descripcion': licitacion['descripcion_licitacion'], 'organismo': { 'id': licitacion['id_organismo'], 'categoria': licitacion['nombre_ministerio'], 'nombre': licitacion['nombre_organismo'], }, 'fecha_publicacion': licitacion['fecha_publicacion'], 'fecha_cierre': licitacion['fecha_cierre'], 'fecha_adjudicacion': licitacion['fecha_adjudicacion'], 'estado': licitacion['estado'], 'fecha_cambio_estado': licitacion['fecha_cambio_estado'], 'n_items': licitacion['items_totales'], 'adjudicacion': { 'n_items': licitacion['items_adjudicados'], 'monto': int(licitacion['monto_total']) if licitacion['monto_total'] else None, 'acta': licitacion['url_acta'], } if licitacion['monto_total'] else None, # Only if there is monto_total } for licitacion in licitaciones.paginate(q_pagina, Licitacion.MAX_RESULTS).dicts() ] } resp.body = json.dumps(response, cls=JSONEncoderPlus, sort_keys=True)
def on_get(self, req, resp): selects = [ models_api.ProveedorOrganismoCruce.organismo, models_api.ProveedorOrganismoCruce.nombre_ministerio, models_api.ProveedorOrganismoCruce.nombre_organismo ] wheres = [] joins = [] order_bys = [] # Busqueda de texto q_q = req.params.get('q', None) if q_q: # TODO Try to make just one query over one index instead of two or more ORed queries wheres.append(ts_match(models_api.ProveedorOrganismoCruce.nombre_ministerio, q_q) | ts_match(models_api.ProveedorOrganismoCruce.nombre_organismo, q_q)) q_organismo = req.params.get('organismo', None) if q_organismo: if isinstance(q_organismo, basestring): q_organismo = [q_organismo] try: q_organismo = map(lambda x: int(x), q_organismo) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "organismo debe ser un entero") wheres.append(models_api.ProveedorOrganismoCruce.organismo << q_organismo) # Busqueda por fecha de adjudicacion q_fecha_adjudicacion = req.params.get('fecha_adjudicacion', None) if q_fecha_adjudicacion: if isinstance(q_fecha_adjudicacion, basestring): q_fecha_adjudicacion = [q_fecha_adjudicacion] filter_fecha_adjudicacion = [] for fechas in q_fecha_adjudicacion: fechas = fechas.split('|') try: fecha_adjudicacion_min = dateutil.parser.parse(fechas[0], dayfirst=True, yearfirst=True).date() if fechas[0] else None fecha_adjudicacion_max = dateutil.parser.parse(fechas[1], dayfirst=True, yearfirst=True).date() if fechas[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en fecha_adjudicacion deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "El formato de la fecha en fecha_adjudicacion no es correcto") if fecha_adjudicacion_min and fecha_adjudicacion_max: filter_fecha_adjudicacion.append((models_api.ProveedorOrganismoCruce.fecha_adjudicacion >= fecha_adjudicacion_min) & (models_api.ProveedorOrganismoCruce.fecha_adjudicacion <= fecha_adjudicacion_max)) elif fecha_adjudicacion_min: filter_fecha_adjudicacion.append(models_api.ProveedorOrganismoCruce.fecha_adjudicacion >= fecha_adjudicacion_min) elif fecha_adjudicacion_max: filter_fecha_adjudicacion.append(models_api.ProveedorOrganismoCruce.fecha_adjudicacion <= fecha_adjudicacion_max) if filter_fecha_adjudicacion: wheres.append(reduce(operator.or_, filter_fecha_adjudicacion)) # Search by proveedor_adjudicado q_proveedor_adjudicado = req.params.get('proveedor_adjudicado', None) if q_proveedor_adjudicado: if isinstance(q_proveedor_adjudicado, basestring): q_proveedor_adjudicado = [q_proveedor_adjudicado] try: q_proveedor_adjudicado = map(lambda x: int(x), q_proveedor_adjudicado) except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "proveedor_adjudicado debe ser un entero") wheres.append(models_api.ProveedorOrganismoCruce.empresa << q_proveedor_adjudicado) # Search by n_licitaciones_adjudicadas q_n_licitaciones_adjudicadas = req.params.get('n_licitaciones_adjudicadas') if q_n_licitaciones_adjudicadas: if isinstance(q_n_licitaciones_adjudicadas, basestring): q_n_licitaciones_adjudicadas = [q_n_licitaciones_adjudicadas] filter_n_licitaciones_adjudicadas = [] for n_licitaciones in q_n_licitaciones_adjudicadas: n_licitaciones = n_licitaciones.split('|') try: n_licitaciones_adjudicadas_min = int(n_licitaciones[0]) if n_licitaciones[0] else None n_licitaciones_adjudicadas_max = int(n_licitaciones[1]) if n_licitaciones[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en n_licitaciones_adjudicadas deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "n_licitaciones_adjudicadas debe ser un entero") if n_licitaciones_adjudicadas_min is not None and n_licitaciones_adjudicadas_max is not None: filter_n_licitaciones_adjudicadas.append( (peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) >= n_licitaciones_adjudicadas_min) & (peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) <= n_licitaciones_adjudicadas_max) ) elif n_licitaciones_adjudicadas_min is not None: filter_n_licitaciones_adjudicadas.append( peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) >= n_licitaciones_adjudicadas_min ) elif n_licitaciones_adjudicadas_max is not None: filter_n_licitaciones_adjudicadas.append( peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) <= n_licitaciones_adjudicadas_max ) if filter_n_licitaciones_adjudicadas: filter_n_licitaciones_adjudicadas = reduce(operator.or_, filter_n_licitaciones_adjudicadas) organismos_n_licitaciones = models_api.ProveedorOrganismoCruce.select( models_api.ProveedorOrganismoCruce.organismo, peewee.fn.count(peewee.SQL('DISTINCT licitacion_id')) ) if wheres: organismos_n_licitaciones = organismos_n_licitaciones.where(*wheres) organismos_n_licitaciones = organismos_n_licitaciones.group_by( models_api.ProveedorOrganismoCruce.organismo ).having( filter_n_licitaciones_adjudicadas ) organismos_ids = [organismo_n_licitaciones['organismo'] for organismo_n_licitaciones in organismos_n_licitaciones.dicts().iterator()] wheres.append(models_api.ProveedorOrganismoCruce.organismo << organismos_ids if organismos_ids else False) # Search by monto_adjudicado q_monto_adjudicado = req.params.get('monto_adjudicado') if q_monto_adjudicado: if isinstance(q_monto_adjudicado, basestring): q_monto_adjudicado = [q_monto_adjudicado] filter_monto_adjudicado = [] for monto_adjudicado in q_monto_adjudicado: monto_adjudicado = monto_adjudicado.split('|') try: monto_adjudicado_min = int(monto_adjudicado[0]) if monto_adjudicado[0] else None monto_adjudicado_max = int(monto_adjudicado[1]) if monto_adjudicado[1] else None except IndexError: raise falcon.HTTPBadRequest("Parametro incorrecto", "Los valores en monto_adjudicado deben estar separados por un pipe [|]") except ValueError: raise falcon.HTTPBadRequest("Parametro incorrecto", "monto_adjudicado debe ser un entero") if monto_adjudicado_min is not None and monto_adjudicado_max is not None: filter_monto_adjudicado.append( (peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) >= monto_adjudicado_min) & (peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) <= monto_adjudicado_max) ) elif monto_adjudicado_min is not None: filter_monto_adjudicado.append( peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) >= monto_adjudicado_min ) elif monto_adjudicado_max is not None: filter_monto_adjudicado.append( peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total) <= monto_adjudicado_max ) if filter_monto_adjudicado: filter_monto_adjudicado = reduce(operator.or_, filter_monto_adjudicado) organismos_montos = models_api.ProveedorOrganismoCruce.select( models_api.ProveedorOrganismoCruce.organismo, peewee.fn.sum(models_api.ProveedorOrganismoCruce.monto_total).alias('monto_adjudicado') ) if wheres: organismos_montos = organismos_montos.where(*wheres) organismos_montos = organismos_montos.group_by( models_api.ProveedorOrganismoCruce.organismo ).having( filter_monto_adjudicado ).alias('organismos_montos') selects.append(organismos_montos.c.monto_adjudicado) joins.append([ organismos_montos, peewee.JOIN_INNER, (models_api.ProveedorOrganismoCruce.organismo == organismos_montos.c.organismo_id) ]) q_orden = req.params.get('orden', None) if q_orden == 'monto_adjudicado': order_bys.append(organismos_montos.c.monto_adjudicado.asc()) elif q_orden == '-monto_adjudicado': order_bys.append(organismos_montos.c.monto_adjudicado.desc()) # Build query organismos = models_api.ProveedorOrganismoCruce.select(*selects) if wheres: organismos = organismos.where(*wheres) if joins: for join in joins: organismos = organismos.join(*join) if order_bys: organismos = organismos.order_by(*order_bys) organismos = organismos.distinct() n_organismos = organismos.count() # Get page q_page = req.params.get('pagina', None) if q_page: q_page = max(int(q_page) if q_page.isdigit() else 1, 1) organismos = organismos.paginate(q_page, 10) response = { 'n_organismos': n_organismos, 'organismos': [ { 'id': organismo['organismo'], 'categoria': organismo['nombre_ministerio'], 'nombre': organismo['nombre_organismo'], 'monto_adjudicado': int(organismo['monto_adjudicado']) if 'monto_adjudicado' in organismo else None } for organismo in organismos.dicts().iterator()] } resp.body = json.dumps(response, cls=JSONEncoderPlus, sort_keys=True)