Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)