This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
devicehub-teal/ereuse_devicehub/resources/inventory.py
Xavier Bustamante Talavera c0073e9212 Add DeviceSearch
2018-09-29 12:24:22 +02:00

126 lines
4.1 KiB
Python

from flask import current_app as app, jsonify
from flask_sqlalchemy import Pagination
from marshmallow import Schema as MarshmallowSchema
from marshmallow.fields import Float, Integer, Nested, Str
from marshmallow.validate import Range
from sqlalchemy import Column
from teal.query import Between, ILike, Join, Or, Query, Sort, SortField
from teal.resource import Resource, View
from ereuse_devicehub.resources import search
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.event.models import Rate
from ereuse_devicehub.resources.lot.models import Lot
from ereuse_devicehub.resources.schemas import Thing
from ereuse_devicehub.resources.tag import Tag
class Inventory(Thing):
pass
class RateQ(Query):
rating = Between(Rate.rating, Float())
appearance = Between(Rate.appearance, Float())
functionality = Between(Rate.functionality, Float())
class TagQ(Query):
id = Or(ILike(Tag.id), required=True)
org = ILike(Tag.org)
class OfType(Str):
def __init__(self, column: Column, *args, **kwargs):
super().__init__(*args, **kwargs)
self.column = column
def _deserialize(self, value, attr, data):
v = super()._deserialize(value, attr, data)
return self.column.in_(app.resources[v].subresources_types)
class Filters(Query):
type = Or(OfType(Device.type))
model = ILike(Device.model)
manufacturer = ILike(Device.manufacturer)
serialNumber = ILike(Device.serial_number)
rating = Join(Device.id == Rate.device_id, RateQ)
tag = Join(Device.id == Tag.id, TagQ)
class Sorting(Sort):
created = SortField(Device.created)
class InventoryView(View):
class FindArgs(MarshmallowSchema):
search = Str()
filter = Nested(Filters, missing=[])
sort = Nested(Sorting, missing=[Device.created.desc()])
page = Integer(validate=Range(min=1), missing=1)
def get(self, id):
"""Inventory view
---
description: Supports the inventory view of ``devicehub-client``; returns
all the devices, groups and widgets of this Devicehub instance.
responses:
200:
description: The inventory.
schema:
type: object
properties:
devices:
type: array
items:
$ref: '#/definitions/Device'
pagination:
type: object
properties:
page:
type: integer
minimum: 0
perPage:
type: integer
minimum: 0
total:
type: integer
minimum: 0
"""
# todo .format(yaml.load(schema2parameters(self.FindArgs, default_in='path', name='path')))
return super().get(id)
def find(self, args: dict):
"""See :meth:`.get` above."""
search_p = args.get('search', None)
query = Device.query
if search_p:
properties = DeviceSearch.properties
tags = DeviceSearch.tags
query = query.join(DeviceSearch).filter(
search.Search.match(properties, search_p) | search.Search.match(tags, search_p)
).order_by(
search.Search.rank(properties, search_p) + search.Search.rank(tags, search_p)
)
query = query.filter(*args['filter']).order_by(*args['sort'])
devices = query.paginate(page=args['page'], per_page=30) # type: Pagination
inventory = {
'devices': app.resources[Device.t].schema.dump(devices.items, many=True, nested=1),
'lots': app.resources[Lot.t].schema.dump(Lot.roots(), many=True, nested=1),
'widgets': {},
'pagination': {
'page': devices.page,
'perPage': devices.per_page,
'total': devices.total,
}
}
return jsonify(inventory)
class InventoryDef(Resource):
SCHEMA = Inventory
VIEW = InventoryView
AUTH = True