Merge branch 'mvp_deliverynote' into devel

This commit is contained in:
Big Lebowski 2020-04-13 22:45:25 +02:00
commit 315f5b793a
10 changed files with 152 additions and 66 deletions

View File

@ -16,6 +16,7 @@ from ereuse_devicehub.db import db
from ereuse_devicehub.query import things_response from ereuse_devicehub.query import things_response
from ereuse_devicehub.resources.deliverynote.models import Deliverynote from ereuse_devicehub.resources.deliverynote.models import Deliverynote
from ereuse_devicehub.resources.lot.models import Lot from ereuse_devicehub.resources.lot.models import Lot
from ereuse_devicehub.resources.device.models import Computer
class DeliverynoteView(View): class DeliverynoteView(View):
@ -41,8 +42,18 @@ class DeliverynoteView(View):
'ethereum_address'), partial=True) 'ethereum_address'), partial=True)
d = request.get_json(schema=patch_schema) d = request.get_json(schema=patch_schema)
dlvnote = Deliverynote.query.filter_by(id=id).one() dlvnote = Deliverynote.query.filter_by(id=id).one()
# device_fields = ['transfer_state', 'deliverynote_address']
# computers = [x for x in dlvnote.transferred_devices if isinstance(x, Computer)]
for key, value in d.items(): for key, value in d.items():
setattr(dlvnote, key, value) setattr(dlvnote, key, value)
# Transalate ethereum_address attribute
# devKey = key
# if key == 'ethereum_address':
# devKey = 'deliverynote_address'
# if devKey in device_fields:
# for dev in computers:
# setattr(dev, devKey, value)
db.session.commit() db.session.commit()
return Response(status=204) return Response(status=204)

View File

@ -381,18 +381,19 @@ class Computer(Device):
It is a subset of the Linux definition of DMI / DMI decode. It is a subset of the Linux definition of DMI / DMI decode.
""" """
ethereum_address = Column(CIText(), unique=True, default=None)
deposit = Column(Integer, check_range('deposit',min=0,max=100), default=0) deposit = Column(Integer, check_range('deposit',min=0,max=100), default=0)
owner_address = db.Column(CIText(), owner_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.ethereum_address), db.ForeignKey(User.id),
nullable=False, nullable=False,
default=lambda: g.user.ethereum_address) default=lambda: g.user.id)
author = db.relationship(User, primaryjoin=owner_address == User.ethereum_address) author = db.relationship(User, primaryjoin=owner_id == User.id)
transfer_state = db.Column(IntEnum(TransferState), default=TransferState.Initial, nullable=False) transfer_state = db.Column(IntEnum(TransferState), default=TransferState.Initial, nullable=False)
transfer_state.comment = TransferState.__doc__ transfer_state.comment = TransferState.__doc__
receiver_address = db.Column(CIText(), receiver_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.ethereum_address), db.ForeignKey(User.id),
nullable=True) nullable=True)
receiver = db.relationship(User, primaryjoin=receiver_address == User.ethereum_address) receiver = db.relationship(User, primaryjoin=receiver_id == User.id)
deliverynote_address = db.Column(CIText(), nullable=True) deliverynote_address = db.Column(CIText(), nullable=True)
def __init__(self, chassis, **kwargs) -> None: def __init__(self, chassis, **kwargs) -> None:

View File

@ -122,12 +122,13 @@ class Computer(Device):
dump_only=True, dump_only=True,
collection_class=set, collection_class=set,
description=m.Computer.privacy.__doc__) description=m.Computer.privacy.__doc__)
ethereum_address = SanitizedStr(validate=f.validate.Length(max=42))
deposit = Integer(validate=f.validate.Range(min=0, max=100), deposit = Integer(validate=f.validate.Range(min=0, max=100),
description=m.Computer.deposit.__doc__) description=m.Computer.deposit.__doc__)
# author_id = NestedOn(s_user.User,only_query='author_id') # author_id = NestedOn(s_user.User,only_query='author_id')
owner_address = SanitizedStr(validate=f.validate.Length(max=42)) owner_id = UUID(data_key='ownerID')
transfer_state = EnumField(enums.TransferState, description=m.Computer.transfer_state.comment) transfer_state = EnumField(enums.TransferState, description=m.Computer.transfer_state.comment)
receiver_address = SanitizedStr(validate=f.validate.Length(max=42)) receiver_id = UUID(data_key='receiverID')
deliverynote_address = SanitizedStr(validate=f.validate.Length(max=42)) deliverynote_address = SanitizedStr(validate=f.validate.Length(max=42))

View File

@ -1,10 +1,10 @@
import datetime import datetime
import marshmallow import marshmallow
from flask import current_app as app, render_template, request from flask import current_app as app, render_template, request, Response
from flask.json import jsonify from flask.json import jsonify
from flask_sqlalchemy import Pagination from flask_sqlalchemy import Pagination
from marshmallow import fields, fields as f, validate as v from marshmallow import fields, fields as f, validate as v, ValidationError
from teal import query from teal import query
from teal.cache import cache from teal.cache import cache
from teal.resource import View from teal.resource import View
@ -15,7 +15,7 @@ from ereuse_devicehub.query import SearchQueryParser, things_response
from ereuse_devicehub.resources import search from ereuse_devicehub.resources import search
from ereuse_devicehub.resources.action import models as actions from ereuse_devicehub.resources.action import models as actions
from ereuse_devicehub.resources.device import states from ereuse_devicehub.resources.device import states
from ereuse_devicehub.resources.device.models import Device, Manufacturer from ereuse_devicehub.resources.device.models import Device, Manufacturer, Computer
from ereuse_devicehub.resources.device.search import DeviceSearch from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.tag.model import Tag
@ -93,6 +93,23 @@ class DeviceView(View):
""" """
return super().get(id) return super().get(id)
def patch(self, id):
dev = Device.query.filter_by(id=id).one()
if isinstance(dev, Computer):
resource_def = app.resources['Computer']
# TODO check how to handle the 'actions_one'
patch_schema = resource_def.SCHEMA(only=['ethereum_address', 'transfer_state', 'deliverynote_address', 'actions_one'], partial=True)
json = request.get_json(schema=patch_schema)
# TODO check how to handle the 'actions_one'
json.pop('actions_one')
if not dev:
raise ValueError('Device non existent')
for key, value in json.items():
setattr(dev,key,value)
db.session.commit()
return Response(status=204)
raise ValueError('Cannot patch a non computer')
def one(self, id: int): def one(self, id: int):
"""Gets one device.""" """Gets one device."""
if not request.authorization: if not request.authorization:
@ -110,7 +127,7 @@ class DeviceView(View):
return self.schema.jsonify(device) return self.schema.jsonify(device)
@auth.Auth.requires_auth @auth.Auth.requires_auth
@cache(datetime.timedelta(minutes=1)) # @cache(datetime.timedelta(minutes=1))
def find(self, args: dict): def find(self, args: dict):
"""Gets many devices.""" """Gets many devices."""
# Compute query # Compute query

View File

@ -64,11 +64,11 @@ class Lot(Thing):
descendants. descendants.
""" """
deposit = db.Column(db.Integer, check_range('deposit', min=0, max=100), default=0) deposit = db.Column(db.Integer, check_range('deposit', min=0, max=100), default=0)
owner_address = db.Column(CIText(), owner_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.ethereum_address), db.ForeignKey(User.id),
nullable=False, nullable=False,
default=lambda: g.user.ethereum_address) default=lambda: g.user.id)
owner = db.relationship(User, primaryjoin=owner_address == User.ethereum_address) owner = db.relationship(User, primaryjoin=owner_id == User.id)
transfer_state = db.Column(IntEnum(TransferState), default=TransferState.Initial, nullable=False) transfer_state = db.Column(IntEnum(TransferState), default=TransferState.Initial, nullable=False)
transfer_state.comment = TransferState.__doc__ transfer_state.comment = TransferState.__doc__
receiver_address = db.Column(CIText(), receiver_address = db.Column(CIText(),

View File

@ -22,7 +22,7 @@ class Lot(Thing):
deposit = f.Integer(validate=f.validate.Range(min=0, max=100), deposit = f.Integer(validate=f.validate.Range(min=0, max=100),
description=m.Lot.deposit.__doc__) description=m.Lot.deposit.__doc__)
# author_id = NestedOn(s_user.User,only_query='author_id') # author_id = NestedOn(s_user.User,only_query='author_id')
owner_address = SanitizedStr(validate=f.validate.Length(max=42)) owner_id = f.UUID(data_key='ownerID')
transfer_state = EnumField(TransferState, description=m.Lot.transfer_state.comment) transfer_state = EnumField(TransferState, description=m.Lot.transfer_state.comment)
receiver_address = SanitizedStr(validate=f.validate.Length(max=42)) receiver_address = SanitizedStr(validate=f.validate.Length(max=42))
deliverynote = NestedOn(s_deliverynote.Deliverynote, dump_only=True) deliverynote = NestedOn(s_deliverynote.Deliverynote, dump_only=True)

View File

@ -59,7 +59,7 @@ class LotView(View):
lot = Lot.query.filter_by(id=id).one() # type: Lot lot = Lot.query.filter_by(id=id).one() # type: Lot
return self.schema.jsonify(lot, nested=2) return self.schema.jsonify(lot, nested=2)
@teal.cache.cache(datetime.timedelta(minutes=5)) # @teal.cache.cache(datetime.timedelta(minutes=5))
def find(self, args: dict): def find(self, args: dict):
"""Gets lots. """Gets lots.

View File

@ -26,7 +26,9 @@ from teal.resource import url_for_resource
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
from ereuse_devicehub.resources.action.models import Action, DisposeProduct, \ from ereuse_devicehub.resources.action.models import Action, DisposeProduct, \
EraseBasic, Rate, Trade EraseBasic, Rate, Trade
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.models import Thing from ereuse_devicehub.resources.models import Thing
from ereuse_devicehub.resources.user import User
class JoinedTableMixin: class JoinedTableMixin:
@ -42,7 +44,14 @@ class Proof(Thing):
""" """
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
type = Column(Unicode, nullable=False) type = Column(Unicode, nullable=False)
ethereum_hashes = Column(CIText(), default='', nullable=False) ethereum_hash = Column(CIText(), default='', nullable=False)
device_id = db.Column(BigInteger,
db.ForeignKey(Device.id),
nullable=False)
device = db.relationship(Device,
backref=db.backref('proofs_device', uselist=True, lazy=True),
lazy=True,
primaryjoin=Device.id == device_id)
@property @property
def url(self) -> urlutils.URL: def url(self) -> urlutils.URL:
@ -74,46 +83,76 @@ class Proof(Thing):
return '<{0.t} {0.id} >'.format(self) return '<{0.t} {0.id} >'.format(self)
class ProofTransfer(JoinedTableMixin, Proof): class ProofTransfer(JoinedTableMixin, Proof):
transfer_id = Column(UUID, ForeignKey(Trade.id), nullable=False) supplier_id = db.Column(UUID(as_uuid=True),
transfer = relationship(DisposeProduct, db.ForeignKey(User.id),
backref=backref("proof_transfer", nullable=False,
lazy=True, default=lambda: g.user.id)
cascade=CASCADE_OWN), supplier = db.relationship(User, primaryjoin=lambda: ProofTransfer.supplier_id == User.id)
uselist=False, receiver_id = db.Column(UUID(as_uuid=True),
primaryjoin=DisposeProduct.id == transfer_id) db.ForeignKey(User.id),
nullable=False)
receiver = db.relationship(User, primaryjoin=lambda: ProofTransfer.receiver_id == User.id)
deposit = Column(db.Integer, default=0)
class ProofDataWipe(JoinedTableMixin, Proof): class ProofDataWipe(JoinedTableMixin, Proof):
erasure_type = Column(CIText(), default='', nullable=False) # erasure_type = Column(CIText(), default='', nullable=False)
date = Column(db.DateTime, nullable=False, default=datetime.utcnow) date = Column(db.DateTime, nullable=False, default=datetime.utcnow)
result = Column(db.Boolean, default=False, nullable=False) result = Column(db.Boolean, default=False, nullable=False)
result.comment = """Identifies proof datawipe as a result.""" result.comment = """Identifies proof datawipe as a result."""
proof_author_id = Column(UUID(as_uuid=True),
db.ForeignKey(User.id),
nullable=False,
default=lambda: g.user.id)
proof_author = relationship(User, primaryjoin=lambda: ProofDataWipe.proof_author_id == User.id)
erasure_id = Column(UUID(as_uuid=True), ForeignKey(EraseBasic.id), nullable=False) erasure_id = Column(UUID(as_uuid=True), ForeignKey(EraseBasic.id), nullable=False)
erasure = relationship(EraseBasic, erasure = relationship(EraseBasic,
backref=backref('proof_datawipe', backref=backref('proof_datawipe',
lazy=True, lazy=True,
uselist=False,
cascade=CASCADE_OWN), cascade=CASCADE_OWN),
primaryjoin=EraseBasic.id == erasure_id) primaryjoin=EraseBasic.id == erasure_id)
class ProofFunction(JoinedTableMixin, Proof): class ProofFunction(JoinedTableMixin, Proof):
disk_usage = Column(db.Integer, default=0) disk_usage = Column(db.Integer, default=0)
rate_id = Column(UUID, ForeignKey(Rate.id), nullable=False) proof_author_id = Column(UUID(as_uuid=True),
db.ForeignKey(User.id),
nullable=False,
default=lambda: g.user.id)
proof_author = db.relationship(User, primaryjoin=lambda: ProofFunction.proof_author_id == User.id)
rate_id = Column(UUID(as_uuid=True), ForeignKey(Rate.id), nullable=False)
rate = relationship(Rate, rate = relationship(Rate,
backref=backref('proof_function', backref=backref('proof_function',
lazy=True, lazy=True,
uselist=False,
cascade=CASCADE_OWN), cascade=CASCADE_OWN),
primaryjoin=Rate.id == rate_id) primaryjoin=Rate.id == rate_id)
class ProofReuse(JoinedTableMixin, Proof): class ProofReuse(JoinedTableMixin, Proof):
receiver_segment = Column(CIText(), default='', nullable=False)
id_receipt = Column(CIText(), default='', nullable=False)
supplier_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.id),
# nullable=False,
# default=lambda: g.user.id)
nullable=True)
supplier = db.relationship(User, primaryjoin=lambda: ProofReuse.supplier_id == User.id)
receiver_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.id),
# nullable=False)
nullable=True)
receiver = db.relationship(User, primaryjoin=lambda: ProofReuse.receiver_id == User.id)
price = Column(db.Integer) price = Column(db.Integer)
class ProofRecycling(JoinedTableMixin, Proof): class ProofRecycling(JoinedTableMixin, Proof):
collection_point = Column(CIText(), default='', nullable=False) collection_point = Column(CIText(), default='', nullable=False)
date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) date = Column(db.DateTime, nullable=False, default=datetime.utcnow)
contact = Column(CIText(), default='', nullable=False) contact = Column(CIText(), default='', nullable=False)
ticket = Column(CIText(), default='', nullable=False) ticket = Column(CIText(), default='', nullable=False)
gps_location = Column(CIText(), default='', nullable=False) gps_location = Column(CIText(), default='', nullable=False)
recycler_code = Column(CIText(), default='', nullable=False)

View File

@ -1,5 +1,5 @@
from flask import current_app as app from flask import current_app as app
from marshmallow import Schema as MarshmallowSchema, ValidationError, validates_schema from marshmallow import Schema as MarshmallowSchema, ValidationError, fields as f, validates_schema
from marshmallow.fields import Boolean, DateTime, Integer, Nested, String, UUID from marshmallow.fields import Boolean, DateTime, Integer, Nested, String, UUID
from marshmallow.validate import Length from marshmallow.validate import Length
from sqlalchemy.util import OrderedSet from sqlalchemy.util import OrderedSet
@ -11,46 +11,62 @@ from ereuse_devicehub.resources.proof import models as m
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing from ereuse_devicehub.resources.schemas import Thing
from ereuse_devicehub.resources.action import schemas as s_action from ereuse_devicehub.resources.action import schemas as s_action
from ereuse_devicehub.resources.device import schemas as s_device
from ereuse_devicehub.resources.user import schemas as s_user
class Proof(Thing): class Proof(Thing):
__doc__ = m.Proof.__doc__ __doc__ = m.Proof.__doc__
id = UUID(dump_only=True) id = UUID(dump_only=True)
ethereum_hashes = SanitizedStr(default='', validate=Length(max=STR_BIG_SIZE), ethereum_hash = SanitizedStr(default='', validate=Length(max=STR_BIG_SIZE),
data_key="ethereumHashes") data_key="ethereumHash", required=True)
url = URL(dump_only=True, description=m.Proof.url.__doc__) url = URL(dump_only=True, description=m.Proof.url.__doc__)
device_id = Integer(load_only=True, data_key='deviceID')
device = NestedOn(s_device.Device, dump_only=True)
class ProofTransfer(Proof): class ProofTransfer(Proof):
__doc__ = m.ProofTransfer.__doc__ __doc__ = m.ProofTransfer.__doc__
transfer = NestedOn(s_action.DisposeProduct, deposit = Integer(validate=f.validate.Range(min=0, max=100))
required=True, supplier_id = UUID(load_only=True, required=True, data_key='supplierID')
only_query='id') receiver_id = UUID(load_only=True, required=True, data_key='receiverID')
class ProofDataWipe(Proof): class ProofDataWipe(Proof):
__doc__ = m.ProofDataWipe.__doc__ __doc__ = m.ProofDataWipe.__doc__
erasure_type = SanitizedStr(default='') # erasure_type = String(default='', data_key='erasureType')
date = DateTime('iso', required=True) date = DateTime('iso', required=True)
result = Boolean(missing=False) result = Boolean(required=True)
erasure = NestedOn(s_action.EraseBasic, only_query='id') proof_author_id = SanitizedStr(validate=f.validate.Length(max=STR_SIZE),
load_only=True, required=True, data_key='proofAuthorID')
proof_author = NestedOn(s_user.User, dump_only=True)
erasure = NestedOn(s_action.EraseBasic, only_query='id', data_key='erasureID')
class ProofFunction(Proof): class ProofFunction(Proof):
__doc__ = m.ProofFunction.__doc__ __doc__ = m.ProofFunction.__doc__
disk_usage = Integer() disk_usage = Integer(validate=f.validate.Range(min=0, max=100), data_key='diskUsage')
rate = NestedOn(s_action.Rate, required=True, only_query='id') proof_author_id = SanitizedStr(validate=f.validate.Length(max=STR_SIZE),
load_only=True, required=True, data_key='proofAuthorID')
proof_author = NestedOn(s_user.User, dump_only=True)
rate = NestedOn(s_action.Rate, required=True,
only_query='id', data_key='rateID')
class ProofReuse(Proof): class ProofReuse(Proof):
__doc__ = m.ProofReuse.__doc__ __doc__ = m.ProofReuse.__doc__
price = Integer() receiver_segment = String(default='', data_key='receiverSegment', required=True)
id_receipt = String(default='', data_key='idReceipt', required=True)
supplier_id = UUID(load_only=True, required=False, data_key='supplierID')
receiver_id = UUID(load_only=True, required=False, data_key='receiverID')
price = Integer(required=True)
class ProofRecycling(Proof): class ProofRecycling(Proof):
__doc__ = m.ProofRecycling.__doc__ __doc__ = m.ProofRecycling.__doc__
collection_point = SanitizedStr(default='') collection_point = SanitizedStr(default='', data_key='collectionPoint', required=True)
date = DateTime() date = DateTime('iso', required=True)
contact = SanitizedStr(default='') contact = SanitizedStr(default='', required=True)
ticket = SanitizedStr(default='') ticket = SanitizedStr(default='', required=True)
gps_location = SanitizedStr(default='') gps_location = SanitizedStr(default='', data_key='gpsLocation', required=True)
recycler_code = SanitizedStr(default='', data_key='recyclerCode', required=True)

View File

@ -33,7 +33,8 @@ class ProofView(View):
Model = db.Model._decl_class_registry.data[prf['type']]() Model = db.Model._decl_class_registry.data[prf['type']]()
proof = Model(**p) proof = Model(**p)
db.session.add(proof) db.session.add(proof)
proofs.append(self.schema.dump(proof)) proofs.append(resource_def.schema.dump(proof))
db.session().final_flush()
db.session.commit() db.session.commit()
response = jsonify({ response = jsonify({
'items': proofs, 'items': proofs,