Add inventories
This commit is contained in:
parent
f0f1376b7d
commit
9272674760
|
@ -64,10 +64,15 @@ class DevicehubConfig(Config):
|
||||||
TAG_TOKEN = None
|
TAG_TOKEN = None
|
||||||
"""Access to the tag provider."""
|
"""Access to the tag provider."""
|
||||||
|
|
||||||
def __init__(self, db: str = None) -> None:
|
def __init__(self, schema: str = None, token=None) -> None:
|
||||||
if not self.ORGANIZATION_NAME or not self.ORGANIZATION_TAX_ID:
|
if not self.ORGANIZATION_NAME or not self.ORGANIZATION_TAX_ID:
|
||||||
raise ValueError('You need to set the main organization parameters.')
|
raise ValueError('You need to set the main organization parameters.')
|
||||||
if not self.TAG_BASE_URL or not self.TAG_TOKEN:
|
if not self.TAG_BASE_URL:
|
||||||
raise ValueError('You need a tag service.')
|
raise ValueError('You need a tag service.')
|
||||||
|
self.TAG_TOKEN = token or self.TAG_TOKEN
|
||||||
|
if not self.TAG_TOKEN:
|
||||||
|
raise ValueError('You need a tag token')
|
||||||
self.TAG_BASE_URL = boltons.urlutils.URL(self.TAG_BASE_URL)
|
self.TAG_BASE_URL = boltons.urlutils.URL(self.TAG_BASE_URL)
|
||||||
super().__init__(db)
|
if schema:
|
||||||
|
self.SCHEMA = schema
|
||||||
|
super().__init__()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import citext
|
||||||
from sqlalchemy import event
|
from sqlalchemy import event
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
from sqlalchemy.sql import expression
|
from sqlalchemy.sql import expression
|
||||||
|
@ -11,7 +12,10 @@ class SQLAlchemy(SchemaSQLAlchemy):
|
||||||
schema of the database, as it is in the `search_path`
|
schema of the database, as it is in the `search_path`
|
||||||
defined in teal.
|
defined in teal.
|
||||||
"""
|
"""
|
||||||
|
# todo add here all types of columns used so we don't have to
|
||||||
|
# manually import them all the time
|
||||||
UUID = postgresql.UUID
|
UUID = postgresql.UUID
|
||||||
|
CIText = citext.CIText
|
||||||
|
|
||||||
def drop_all(self, bind='__all__', app=None):
|
def drop_all(self, bind='__all__', app=None):
|
||||||
"""A faster nuke-like option to drop everything."""
|
"""A faster nuke-like option to drop everything."""
|
||||||
|
@ -37,6 +41,6 @@ def create_view(name, selectable):
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
db = SQLAlchemy(session_options={"autoflush": False})
|
db = SQLAlchemy(session_options={'autoflush': False})
|
||||||
f = db.func
|
f = db.func
|
||||||
exp = expression
|
exp = expression
|
||||||
|
|
|
@ -44,9 +44,11 @@ class Devicehub(Teal):
|
||||||
# todo can I make it with a global Session only?
|
# todo can I make it with a global Session only?
|
||||||
event.listen(db.session, 'before_commit', DeviceSearch.update_modified_devices)
|
event.listen(db.session, 'before_commit', DeviceSearch.update_modified_devices)
|
||||||
|
|
||||||
def _init_db(self):
|
def _init_db(self, exclude_schema=None, check=False):
|
||||||
super()._init_db()
|
created = super()._init_db(exclude_schema, check)
|
||||||
|
if created:
|
||||||
DeviceSearch.set_all_devices_tokens_if_empty(self.db.session)
|
DeviceSearch.set_all_devices_tokens_if_empty(self.db.session)
|
||||||
|
return created
|
||||||
|
|
||||||
def regenerate_search(self):
|
def regenerate_search(self):
|
||||||
"""Re-creates from 0 all the search tables."""
|
"""Re-creates from 0 all the search tables."""
|
||||||
|
|
|
@ -46,7 +46,7 @@ class OrganizationDef(AgentDef):
|
||||||
print(json.dumps(o, indent=2))
|
print(json.dumps(o, indent=2))
|
||||||
return o
|
return o
|
||||||
|
|
||||||
def init_db(self, db: SQLAlchemy):
|
def init_db(self, db: SQLAlchemy, exclude_schema=None):
|
||||||
"""Creates the default organization."""
|
"""Creates the default organization."""
|
||||||
org = models.Organization(**app.config.get_namespace('ORGANIZATION_'))
|
org = models.Organization(**app.config.get_namespace('ORGANIZATION_'))
|
||||||
db.session.add(org)
|
db.session.add(org)
|
||||||
|
|
|
@ -297,6 +297,7 @@ class ManufacturerDef(Resource):
|
||||||
SCHEMA = schemas.Manufacturer
|
SCHEMA = schemas.Manufacturer
|
||||||
AUTH = True
|
AUTH = True
|
||||||
|
|
||||||
def init_db(self, db: 'db.SQLAlchemy'):
|
def init_db(self, db: 'db.SQLAlchemy', exclude_schema=None):
|
||||||
"""Loads the manufacturers to the database."""
|
"""Loads the manufacturers to the database."""
|
||||||
|
if exclude_schema != 'common':
|
||||||
Manufacturer.add_all_to_session(db.session)
|
Manufacturer.add_all_to_session(db.session)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
from ereuse_devicehub.db import db
|
||||||
|
from ereuse_devicehub.resources.models import Thing
|
||||||
|
|
||||||
|
|
||||||
|
class Inventory(Thing):
|
||||||
|
__table_args__ = {'schema': 'common'}
|
||||||
|
id = db.Column(db.Unicode(), primary_key=True)
|
||||||
|
id.comment = """The name of the inventory as in the URL and schema."""
|
||||||
|
name = db.Column(db.CIText(), nullable=False, unique=True)
|
||||||
|
name.comment = """The human name of the inventory."""
|
||||||
|
tag_token = db.Column(db.UUID(as_uuid=True), unique=True)
|
||||||
|
tag_token.comment = """The token to access a Tag service."""
|
|
@ -34,7 +34,7 @@ class LotDef(Resource):
|
||||||
view_func=lot_device,
|
view_func=lot_device,
|
||||||
methods={'POST', 'DELETE'})
|
methods={'POST', 'DELETE'})
|
||||||
|
|
||||||
def init_db(self, db: 'db.SQLAlchemy'):
|
def init_db(self, db: 'db.SQLAlchemy', exclude_schema=None):
|
||||||
# Create functions
|
# Create functions
|
||||||
with pathlib.Path(__file__).parent.joinpath('dag.sql').open() as f:
|
with pathlib.Path(__file__).parent.joinpath('dag.sql').open() as f:
|
||||||
sql = f.read()
|
sql = f.read()
|
||||||
|
|
|
@ -5,6 +5,8 @@ from sqlalchemy import Column
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
from sqlalchemy_utils import EmailType, PasswordType
|
from sqlalchemy_utils import EmailType, PasswordType
|
||||||
|
|
||||||
|
from ereuse_devicehub.db import db
|
||||||
|
from ereuse_devicehub.resources.inventory.model import Inventory
|
||||||
from ereuse_devicehub.resources.models import STR_SIZE, Thing
|
from ereuse_devicehub.resources.models import STR_SIZE, Thing
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +25,10 @@ class User(Thing):
|
||||||
data_types.html#module-sqlalchemy_utils.types.password>`_
|
data_types.html#module-sqlalchemy_utils.types.password>`_
|
||||||
"""
|
"""
|
||||||
token = Column(UUID(as_uuid=True), default=uuid4, unique=True)
|
token = Column(UUID(as_uuid=True), default=uuid4, unique=True)
|
||||||
|
inventories = db.relationship(Inventory,
|
||||||
|
backref=db.backref('users', lazy=True, collection_class=set),
|
||||||
|
secondary=lambda: UserInventory.__table__,
|
||||||
|
collection_class=set)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return '<User {0.email}>'.format(self)
|
return '<User {0.email}>'.format(self)
|
||||||
|
@ -31,3 +37,10 @@ class User(Thing):
|
||||||
def individual(self):
|
def individual(self):
|
||||||
"""The individual associated for this database, or None."""
|
"""The individual associated for this database, or None."""
|
||||||
return next(iter(self.individuals), None)
|
return next(iter(self.individuals), None)
|
||||||
|
|
||||||
|
|
||||||
|
class UserInventory(db.Model):
|
||||||
|
"""Relationship between users and their inventories."""
|
||||||
|
__table_args__ = {'schema': 'common'}
|
||||||
|
user_id = db.Column(db.UUID(as_uuid=True), db.ForeignKey(User.id), primary_key=True)
|
||||||
|
inventory_id = db.Column(db.Unicode(), db.ForeignKey(Inventory.id), primary_key=True)
|
||||||
|
|
|
@ -25,7 +25,7 @@ requests==2.19.1
|
||||||
requests-mock==1.5.2
|
requests-mock==1.5.2
|
||||||
SQLAlchemy==1.2.14
|
SQLAlchemy==1.2.14
|
||||||
SQLAlchemy-Utils==0.33.6
|
SQLAlchemy-Utils==0.33.6
|
||||||
teal==0.2.0a32
|
teal==0.2.0a33
|
||||||
webargs==4.0.0
|
webargs==4.0.0
|
||||||
Werkzeug==0.14.1
|
Werkzeug==0.14.1
|
||||||
sqlalchemy-citext==1.3.post0
|
sqlalchemy-citext==1.3.post0
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -29,7 +29,7 @@ setup(
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'teal>=0.2.0a32', # teal always first
|
'teal>=0.2.0a33', # teal always first
|
||||||
'click',
|
'click',
|
||||||
'click-spinner',
|
'click-spinner',
|
||||||
'ereuse-utils[Naming]>=0.4b14',
|
'ereuse-utils[Naming]>=0.4b14',
|
||||||
|
|
Reference in New Issue