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/action/views/trade.py

306 lines
10 KiB
Python
Raw Normal View History

2021-05-10 09:47:56 +00:00
import copy
from flask import g
from sqlalchemy.util import OrderedSet
from teal.marshmallow import ValidationError
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.action.models import Trade, Confirm, ConfirmRevoke, Revoke
from ereuse_devicehub.resources.user.models import User
class TradeView():
"""Handler for manager the trade action register from post
2021-05-19 11:59:59 +00:00
2021-05-10 09:47:56 +00:00
request_post = {
'type': 'Trade',
'devices': [device_id],
2021-05-19 11:59:59 +00:00
'documents': [document_id],
2021-05-10 09:47:56 +00:00
'userFrom': user2.email,
'userTo': user.email,
'price': 10,
'date': "2020-12-01T02:00:00+00:00",
'lot': lot['id'],
'confirm': True,
}
"""
def __init__(self, data, resource_def, schema):
2021-05-19 11:59:59 +00:00
# import pdb; pdb.set_trace()
2021-05-10 09:47:56 +00:00
self.schema = schema
a = resource_def.schema.load(data)
self.trade = Trade(**a)
self.create_phantom_account()
db.session.add(self.trade)
self.create_automatic_trade()
self.create_confirmations()
def post(self):
db.session().final_flush()
ret = self.schema.jsonify(self.trade)
ret.status_code = 201
db.session.commit()
return ret
def create_confirmations(self) -> None:
"""Do the first confirmation for the user than do the action"""
# if the confirmation is mandatory, do automatic confirmation only for
# owner of the lot
if self.trade.confirm:
2021-05-19 11:59:59 +00:00
confirm_devs = Confirm(user=g.user,
action=self.trade,
devices=self.trade.devices)
confirm_docs = Confirm(user=g.user,
action=self.trade,
documents=self.trade.documents)
db.session.add(confirm_devs, confirm_docs)
2021-05-10 09:47:56 +00:00
return
# check than the user than want to do the action is one of the users
# involved in the action
assert g.user.id in [self.trade.user_from_id, self.trade.user_to_id]
2021-05-19 11:59:59 +00:00
confirm_from = Confirm(user=self.trade.user_from,
action=self.trade,
2021-05-10 09:47:56 +00:00
devices=self.trade.devices)
2021-05-19 11:59:59 +00:00
confirm_to = Confirm(user=self.trade.user_to,
action=self.trade,
2021-05-10 09:47:56 +00:00
devices=self.trade.devices)
db.session.add(confirm_from)
db.session.add(confirm_to)
def create_phantom_account(self) -> None:
"""
If exist both users not to do nothing
If exist from but not to:
search if exist in the DB
if exist use it
else create new one
The same if exist to but not from
"""
if self.trade.user_from_id and self.trade.user_to_id:
return
if self.trade.user_from_id and not self.trade.user_to_id:
assert g.user.id == self.trade.user_from_id
email = "{}_{}@dhub.com".format(str(self.trade.user_from_id), self.trade.code)
users = User.query.filter_by(email=email)
if users.first():
user = users.first()
self.trade.user_to = user
return
user = User(email=email, password='', active=False, phantom=True)
db.session.add(user)
self.trade.user_to = user
if not self.trade.user_from_id and self.trade.user_to_id:
email = "{}_{}@dhub.com".format(str(self.trade.user_to_id), self.trade.code)
users = User.query.filter_by(email=email)
if users.first():
user = users.first()
self.trade.user_from = user
return
user = User(email=email, password='', active=False, phantom=True)
db.session.add(user)
self.trade.user_from = user
def create_automatic_trade(self) -> None:
# not do nothing if it's neccesary confirmation explicity
if self.trade.confirm:
return
# Change the owner for every devices
for dev in self.trade.devices:
dev.owner = self.trade.user_to
if hasattr(dev, 'components'):
for c in dev.components:
c.owner = self.trade.user_to
class ConfirmMixin():
"""
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):
self.schema = schema
a = resource_def.schema.load(data)
self.validate(a)
if not a['devices']:
raise ValidationError('Devices 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 ConfirmView(ConfirmMixin):
"""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
"""
# import pdb; pdb.set_trace()
real_devices = []
for dev in data['devices']:
actions = copy.copy(dev.actions)
actions.reverse()
for ac in actions:
if ac == data['action']:
# If device have the last action the action Trade
real_devices.append(dev)
break
if ac.t == Confirm.t and not ac.user == g.user:
# If device is confirmed we don't need confirmed again
real_devices.append(dev)
break
if ac.t == 'Revoke' and not ac.user == g.user:
# If device is revoke before from other user
# it's not possible confirm now
break
if ac.t == 'ConfirmRevoke' and ac.user == g.user:
# if the last action is a ConfirmRevoke this mean than not there are
# other confirmation from the real owner of the trade
break
if ac.t == Confirm.t and ac.user == g.user:
# If device is confirmed we don't need confirmed again
break
data['devices'] = OrderedSet(real_devices)
# Change the owner for every devices
for dev in data['devices']:
dev.owner = data['action'].user_to
if hasattr(dev, 'components'):
for c in dev.components:
c.owner = data['action'].user_to
class RevokeView(ConfirmMixin):
"""Handler for manager the Revoke register from post
request_revoke = {
'type': 'Revoke',
'action': trade.id,
'devices': [device_id],
}
"""
Model = Revoke
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']:
actions = copy.copy(dev.actions)
actions.reverse()
for ac in actions:
if ac == data['action']:
# data['action'] is a Trade action, if this is the first action
# to find mean that this devices dont have a confirmation
break
if ac.t == 'Revoke' and ac.user == g.user:
break
if ac.t == Confirm.t and ac.user == g.user:
real_devices.append(dev)
break
data['devices'] = OrderedSet(real_devices)
class ConfirmRevokeView(ConfirmMixin):
"""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):
"""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']:
actions = copy.copy(dev.actions)
actions.reverse()
for ac in actions:
if ac == data['action']:
# If device have the last action the action for confirm
real_devices.append(dev)
break
if ac.t == 'Revoke' and not ac.user == g.user:
# If device is revoke before you can Confirm now
# and revoke is an action of one other user
real_devices.append(dev)
break
if ac.t == ConfirmRevoke.t and ac.user == g.user:
# If device is confirmed we don't need confirmed again
break
if ac.t == Confirm.t:
# if onwer of trade confirm again before than this user Confirm the
# revoke, then is not possible confirm the revoke
#
# If g.user confirm the trade before do a ConfirmRevoke
# then g.user can not to do the ConfirmRevoke more
break
data['devices'] = OrderedSet(real_devices)
# Change the owner for every devices
trade = data['action']
for dev in data['devices']:
2021-05-19 11:59:59 +00:00
# TODO @cayop this should be the author of confirm actions instead of
2021-05-10 09:47:56 +00:00
# author of trade
dev.owner = trade.author
if hasattr(dev, 'components'):
for c in dev.components:
c.owner = trade.author