fixing models and build views for revokeDocument
This commit is contained in:
parent
77000882f5
commit
8a797f079b
|
@ -115,8 +115,20 @@ def upgrade():
|
||||||
op.create_index(op.f('ix_trade_document_created'), 'trade_document', ['created'], unique=False, schema=f'{get_inv()}')
|
op.create_index(op.f('ix_trade_document_created'), 'trade_document', ['created'], unique=False, schema=f'{get_inv()}')
|
||||||
op.create_index(op.f('ix_trade_document_updated'), 'trade_document', ['updated'], unique=False, schema=f'{get_inv()}')
|
op.create_index(op.f('ix_trade_document_updated'), 'trade_document', ['updated'], unique=False, schema=f'{get_inv()}')
|
||||||
|
|
||||||
|
op.create_table('confirm_document',
|
||||||
|
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
|
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
|
sa.Column('action_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
|
|
||||||
|
sa.ForeignKeyConstraint(['id'], [f'{get_inv()}.action.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['action_id'], [f'{get_inv()}.action.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['common.user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
schema=f'{get_inv()}'
|
||||||
|
)
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
op.drop_table('action_trade_document', schema=f'{get_inv()}')
|
op.drop_table('action_trade_document', schema=f'{get_inv()}')
|
||||||
|
op.drop_table('confirm_document', schema=f'{get_inv()}')
|
||||||
op.drop_table('trade_document', schema=f'{get_inv()}')
|
op.drop_table('trade_document', schema=f'{get_inv()}')
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,19 @@ class TradeDef(ActionDef):
|
||||||
SCHEMA = schemas.Trade
|
SCHEMA = schemas.Trade
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmDocumentDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.ConfirmDocument
|
||||||
|
|
||||||
|
|
||||||
|
class RevokeDocumentDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.RevokeDocument
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CancelTradeDef(ActionDef):
|
class CancelTradeDef(ActionDef):
|
||||||
VIEW = None
|
VIEW = None
|
||||||
SCHEMA = schemas.CancelTrade
|
SCHEMA = schemas.CancelTrade
|
||||||
|
|
|
@ -296,7 +296,7 @@ class ActionDevice(db.Model):
|
||||||
primary_key=True)
|
primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
class ActionWithMultipleTradeDocuments(Action):
|
class ActionWithMultipleTradeDocuments(ActionWithMultipleDevices):
|
||||||
documents = relationship(TradeDocument,
|
documents = relationship(TradeDocument,
|
||||||
backref=backref('actions_docs', lazy=True, **_sorted_actions),
|
backref=backref('actions_docs', lazy=True, **_sorted_actions),
|
||||||
secondary=lambda: ActionTradeDocument.__table__,
|
secondary=lambda: ActionTradeDocument.__table__,
|
||||||
|
@ -1466,14 +1466,18 @@ class ConfirmDocument(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
||||||
lazy=True,
|
lazy=True,
|
||||||
order_by=lambda: Action.end_time,
|
order_by=lambda: Action.end_time,
|
||||||
collection_class=list),
|
collection_class=list),
|
||||||
primaryjoin='Confirm.action_id == Action.id')
|
primaryjoin='ConfirmDocument.action_id == Action.id')
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
if self.action.t in ['Trade']:
|
if self.action.t in ['Trade']:
|
||||||
origin = 'To'
|
origin = 'To'
|
||||||
if self.user == self.action.user_from:
|
if self.user == self.action.user_from:
|
||||||
origin = 'From'
|
origin = 'From'
|
||||||
return '<{0.t} {0.id} accepted by {1}>'.format(self, origin)
|
return '<{0.t}app/views/inventory/ {0.id} accepted by {1}>'.format(self, origin)
|
||||||
|
|
||||||
|
|
||||||
|
class RevokeDocument(ConfirmDocument):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Confirm(JoinedTableMixin, ActionWithMultipleDevices):
|
class Confirm(JoinedTableMixin, ActionWithMultipleDevices):
|
||||||
|
@ -1516,7 +1520,7 @@ class ConfirmRevoke(Confirm):
|
||||||
return '<{0.t} {0.id} accepted by {0.user}>'.format(self)
|
return '<{0.t} {0.id} accepted by {0.user}>'.format(self)
|
||||||
|
|
||||||
|
|
||||||
class Trade(JoinedTableMixin, ActionWithMultipleDevices):
|
class Trade(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
||||||
"""Trade actions log the political exchange of devices between users.
|
"""Trade actions log the political exchange of devices between users.
|
||||||
Every time a trade action is performed, the old user looses its
|
Every time a trade action is performed, the old user looses its
|
||||||
political possession, for example ownership, in favor of another
|
political possession, for example ownership, in favor of another
|
||||||
|
|
|
@ -55,15 +55,19 @@ class Action(Thing):
|
||||||
|
|
||||||
|
|
||||||
class ActionWithOneDevice(Action):
|
class ActionWithOneDevice(Action):
|
||||||
__doc__ = m.ActionWithOneDevice.__doc__
|
|
||||||
doc = NestedOn(s_document.TradeDocument, only_query='id')
|
|
||||||
|
|
||||||
|
|
||||||
class ActionWithOneDocument(Action):
|
|
||||||
__doc__ = m.ActionWithOneDevice.__doc__
|
__doc__ = m.ActionWithOneDevice.__doc__
|
||||||
device = NestedOn(s_device.Device, only_query='id')
|
device = NestedOn(s_device.Device, only_query='id')
|
||||||
|
|
||||||
|
|
||||||
|
class ActionWithMultipleDocuments(Action):
|
||||||
|
__doc__ = m.ActionWithMultipleTradeDocuments.__doc__
|
||||||
|
documents = NestedOn(s_document.TradeDocument,
|
||||||
|
many=True,
|
||||||
|
required=True, # todo test ensuring len(devices) >= 1
|
||||||
|
only_query='id',
|
||||||
|
collection_class=OrderedSet)
|
||||||
|
|
||||||
|
|
||||||
class ActionWithMultipleDevices(Action):
|
class ActionWithMultipleDevices(Action):
|
||||||
__doc__ = m.ActionWithMultipleDevices.__doc__
|
__doc__ = m.ActionWithMultipleDevices.__doc__
|
||||||
devices = NestedOn(s_device.Device,
|
devices = NestedOn(s_device.Device,
|
||||||
|
@ -476,7 +480,7 @@ class Confirm(ActionWithMultipleDevices):
|
||||||
raise ValidationError(txt)
|
raise ValidationError(txt)
|
||||||
|
|
||||||
|
|
||||||
class ConfirmDocument(ActionWithOneDocument):
|
class ConfirmDocument(ActionWithMultipleDocuments):
|
||||||
__doc__ = m.Confirm.__doc__
|
__doc__ = m.Confirm.__doc__
|
||||||
action = NestedOn('Action', only_query='id')
|
action = NestedOn('Action', only_query='id')
|
||||||
|
|
||||||
|
@ -580,8 +584,8 @@ class Revoke(ActionWithMultipleDevices):
|
||||||
raise ValidationError(txt)
|
raise ValidationError(txt)
|
||||||
|
|
||||||
|
|
||||||
class RevokeDocument(ActionWithOneDocument):
|
class RevokeDocument(ActionWithMultipleDocuments):
|
||||||
__doc__ = m.Revoke.__doc__
|
__doc__ = m.RevokeDocument.__doc__
|
||||||
action = NestedOn('Action', only_query='id')
|
action = NestedOn('Action', only_query='id')
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
|
@ -598,7 +602,8 @@ class RevokeDocument(ActionWithOneDocument):
|
||||||
This is not checked in the view becouse the list of documents is inmutable
|
This is not checked in the view becouse the list of documents is inmutable
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not data['devices'] == OrderedSet():
|
import pdb; pdb.set_trace()
|
||||||
|
if not data['documents'] == OrderedSet():
|
||||||
return
|
return
|
||||||
|
|
||||||
documents = []
|
documents = []
|
||||||
|
@ -684,7 +689,7 @@ class ConfirmRevoke(ActionWithMultipleDevices):
|
||||||
raise ValidationError(txt)
|
raise ValidationError(txt)
|
||||||
|
|
||||||
|
|
||||||
class ConfirmRevokeDocument(ActionWithOneDocument):
|
class ConfirmRevokeDocument(ActionWithMultipleDocuments):
|
||||||
__doc__ = m.ConfirmRevoke.__doc__
|
__doc__ = m.ConfirmRevoke.__doc__
|
||||||
action = NestedOn('Action', only_query='id')
|
action = NestedOn('Action', only_query='id')
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ from sqlalchemy.util import OrderedSet
|
||||||
from teal.marshmallow import ValidationError
|
from teal.marshmallow import ValidationError
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.action.models import Trade, Confirm, ConfirmRevoke, Revoke
|
from ereuse_devicehub.resources.action.models import (Trade, Confirm, ConfirmRevoke,
|
||||||
|
Revoke, RevokeDocument, ConfirmDocument)
|
||||||
from ereuse_devicehub.resources.user.models import User
|
from ereuse_devicehub.resources.user.models import User
|
||||||
from ereuse_devicehub.resources.lot.views import delete_from_trade
|
from ereuse_devicehub.resources.lot.views import delete_from_trade
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@ class ConfirmMixin():
|
||||||
self.schema = schema
|
self.schema = schema
|
||||||
a = resource_def.schema.load(data)
|
a = resource_def.schema.load(data)
|
||||||
self.validate(a)
|
self.validate(a)
|
||||||
if not a['devices'] and not a['documents']:
|
if not a['devices']:
|
||||||
raise ValidationError('Devices not exist.')
|
raise ValidationError('Devices not exist.')
|
||||||
self.model = self.Model(**a)
|
self.model = self.Model(**a)
|
||||||
|
|
||||||
|
@ -267,3 +268,134 @@ class ConfirmRevokeView(ConfirmMixin):
|
||||||
dev.reset_owner()
|
dev.reset_owner()
|
||||||
|
|
||||||
trade.lot.devices.difference_update(devices)
|
trade.lot.devices.difference_update(devices)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmDocumentMixin():
|
||||||
|
"""
|
||||||
|
Very Important:
|
||||||
|
==============
|
||||||
|
All of this Views than inherit of this class is executed for users
|
||||||
|
than is not owner of the Trade action.
|
||||||
|
|
||||||
|
The owner of Trade action executed this actions of confirm and revoke from the
|
||||||
|
lot
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
Model = None
|
||||||
|
|
||||||
|
def __init__(self, data, resource_def, schema):
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
|
self.schema = schema
|
||||||
|
a = resource_def.schema.load(data)
|
||||||
|
self.validate(a)
|
||||||
|
if not a['documents']:
|
||||||
|
raise ValidationError('Documents not exist.')
|
||||||
|
self.model = self.Model(**a)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
db.session().final_flush()
|
||||||
|
ret = self.schema.jsonify(self.model)
|
||||||
|
ret.status_code = 201
|
||||||
|
db.session.commit()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmDocumentView(ConfirmDocumentMixin):
|
||||||
|
"""Handler for manager the Confirmation register from post
|
||||||
|
|
||||||
|
request_confirm = {
|
||||||
|
'type': 'Confirm',
|
||||||
|
'action': trade.id,
|
||||||
|
'devices': [device_id]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
Model = Confirm
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
"""If there are one device than have one confirmation,
|
||||||
|
then remove the list this device of the list of devices of this action
|
||||||
|
"""
|
||||||
|
real_devices = []
|
||||||
|
for dev in data['devices']:
|
||||||
|
ac = dev.last_action_trading
|
||||||
|
if ac.type == Confirm.t and not ac.user == g.user:
|
||||||
|
real_devices.append(dev)
|
||||||
|
|
||||||
|
data['devices'] = OrderedSet(real_devices)
|
||||||
|
|
||||||
|
# Change the owner for every devices
|
||||||
|
for dev in data['devices']:
|
||||||
|
user_to = data['action'].user_to
|
||||||
|
dev.change_owner(user_to)
|
||||||
|
|
||||||
|
|
||||||
|
class RevokeDocumentView(ConfirmDocumentMixin):
|
||||||
|
"""Handler for manager the Revoke register from post
|
||||||
|
|
||||||
|
request_revoke = {
|
||||||
|
'type': 'Revoke',
|
||||||
|
'action': trade.id,
|
||||||
|
'devices': [device_id],
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
Model = RevokeDocument
|
||||||
|
|
||||||
|
def __init__(self, data, resource_def, schema):
|
||||||
|
self.schema = schema
|
||||||
|
a = resource_def.schema.load(data)
|
||||||
|
self.validate(a)
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
"""All devices need to have the status of DoubleConfirmation."""
|
||||||
|
|
||||||
|
### check ###
|
||||||
|
if not data['documents']:
|
||||||
|
raise ValidationError('Documents not exist.')
|
||||||
|
|
||||||
|
for doc in data['documents']:
|
||||||
|
if not doc.trading == 'Confirmed':
|
||||||
|
txt = 'Some of documents do not have enough to confirm for to do a revoke'
|
||||||
|
ValidationError(txt)
|
||||||
|
### End check ###
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmRevokeDocumentView(ConfirmDocumentMixin):
|
||||||
|
"""Handler for manager the Confirmation register from post
|
||||||
|
|
||||||
|
request_confirm_revoke = {
|
||||||
|
'type': 'ConfirmRevoke',
|
||||||
|
'action': action_revoke.id,
|
||||||
|
'devices': [device_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
Model = ConfirmRevoke
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
"""All devices need to have the status of revoke."""
|
||||||
|
|
||||||
|
if not data['action'].type == 'Revoke':
|
||||||
|
txt = 'Error: this action is not a revoke action'
|
||||||
|
ValidationError(txt)
|
||||||
|
|
||||||
|
for dev in data['devices']:
|
||||||
|
if not dev.trading == 'Revoke':
|
||||||
|
txt = 'Some of devices do not have revoke to confirm'
|
||||||
|
ValidationError(txt)
|
||||||
|
|
||||||
|
devices = OrderedSet(data['devices'])
|
||||||
|
data['devices'] = devices
|
||||||
|
|
||||||
|
# Change the owner for every devices
|
||||||
|
# data['action'] == 'Revoke'
|
||||||
|
|
||||||
|
trade = data['action'].action
|
||||||
|
for dev in devices:
|
||||||
|
dev.reset_owner()
|
||||||
|
|
||||||
|
trade.lot.devices.difference_update(devices)
|
||||||
|
|
|
@ -625,11 +625,11 @@ 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.
|
||||||
"""
|
"""
|
||||||
amount = Column(Integer, check_range('amount', min=0, max=100), default=0)
|
amount = Column(Integer, check_range('amount', min=0, max=100), default=0)
|
||||||
owner_id = db.Column(UUID(as_uuid=True),
|
# owner_id = db.Column(UUID(as_uuid=True),
|
||||||
db.ForeignKey(User.id),
|
# db.ForeignKey(User.id),
|
||||||
nullable=False,
|
# nullable=False,
|
||||||
default=lambda: g.user.id)
|
# default=lambda: g.user.id)
|
||||||
author = db.relationship(User, primaryjoin=owner_id == User.id)
|
# 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_id = db.Column(UUID(as_uuid=True),
|
receiver_id = db.Column(UUID(as_uuid=True),
|
||||||
|
|
|
@ -94,7 +94,8 @@ class TradeDocument(Thing):
|
||||||
"""The trading state, or None if no Trade action has
|
"""The trading state, or None if no Trade action has
|
||||||
ever been performed to this device. This extract the posibilities for to do"""
|
ever been performed to this device. This extract the posibilities for to do"""
|
||||||
|
|
||||||
confirm = 'Confirm'
|
# import pdb; pdb.set_trace()
|
||||||
|
confirm = 'ConfirmDocument'
|
||||||
to_confirm = 'To Confirm'
|
to_confirm = 'To Confirm'
|
||||||
revoke = 'Revoke'
|
revoke = 'Revoke'
|
||||||
|
|
||||||
|
@ -105,16 +106,13 @@ class TradeDocument(Thing):
|
||||||
actions = list(reversed(actions))
|
actions = list(reversed(actions))
|
||||||
ac = actions[0]
|
ac = actions[0]
|
||||||
|
|
||||||
if ac.type == confirm:
|
|
||||||
return confirm
|
|
||||||
|
|
||||||
if ac.type == revoke:
|
if ac.type == revoke:
|
||||||
return revoke
|
return revoke
|
||||||
|
|
||||||
if ac.type == confirm:
|
if ac.type == confirm:
|
||||||
if ac.user == self.owner:
|
if ac.user == self.owner:
|
||||||
return confirm
|
|
||||||
return to_confirm
|
return to_confirm
|
||||||
|
return 'Confirmed'
|
||||||
|
|
||||||
def last_action_of(self, *types):
|
def last_action_of(self, *types):
|
||||||
"""Gets the last action of the given types.
|
"""Gets the last action of the given types.
|
||||||
|
|
|
@ -6,7 +6,7 @@ from teal.resource import View
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
|
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
|
||||||
from ereuse_devicehub.resources.action.models import Confirm, Revoke
|
from ereuse_devicehub.resources.action.models import ConfirmDocument
|
||||||
from ereuse_devicehub.resources.hash_reports import ReportHash
|
from ereuse_devicehub.resources.hash_reports import ReportHash
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class TradeDocumentView(View):
|
||||||
trade = doc.lot.trade
|
trade = doc.lot.trade
|
||||||
if trade:
|
if trade:
|
||||||
trade.documents.add(doc)
|
trade.documents.add(doc)
|
||||||
confirm = Confirm(action=trade,
|
confirm = ConfirmDocument(action=trade,
|
||||||
user=g.user,
|
user=g.user,
|
||||||
devices=set(),
|
devices=set(),
|
||||||
documents={doc})
|
documents={doc})
|
||||||
|
|
Reference in a new issue