simplify the algorithm for to manager the confirms flow
This commit is contained in:
parent
6dc7fb830b
commit
21cdcb5350
|
@ -7,7 +7,7 @@ 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
|
||||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
from ereuse_devicehub.resources.lot.views import delete_from_trade
|
||||
|
||||
|
||||
class TradeView():
|
||||
|
@ -172,41 +172,16 @@ class ConfirmView(ConfirmMixin):
|
|||
# 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
|
||||
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']:
|
||||
dev.owner = data['action'].user_to
|
||||
if hasattr(dev, 'components'):
|
||||
for c in dev.components:
|
||||
c.owner = data['action'].user_to
|
||||
user_to = data['action'].user_to
|
||||
dev.change_owner(user_to)
|
||||
|
||||
|
||||
class RevokeView(ConfirmMixin):
|
||||
|
@ -228,49 +203,48 @@ class RevokeView(ConfirmMixin):
|
|||
self.validate(a)
|
||||
|
||||
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
|
||||
"""
|
||||
"""All devices need to have the status of DoubleConfirmation."""
|
||||
|
||||
### check ###
|
||||
devs_confirm = []
|
||||
if not data['devices']:
|
||||
raise ValidationError('Devices not exist.')
|
||||
|
||||
for dev in data['devices']:
|
||||
if dev.last_action_trading.type == 'Confirm':
|
||||
devs_confirm.append(dev)
|
||||
|
||||
if not len(data['devices']) == len(devs_confirm):
|
||||
txt = "Some of this devices can't be reboked"
|
||||
raise ValidationError(txt)
|
||||
if not dev.trading == 'TradeConfirmed':
|
||||
txt = 'Some of devices do not have enough to confirm for to do a revoke'
|
||||
ValidationError(txt)
|
||||
### End check ###
|
||||
|
||||
ids = {d.id for d in data['devices']}
|
||||
lot = data['action'].lot
|
||||
devices = set(data['devices'])
|
||||
without_confirms = set() # set of devs without confirms of user2
|
||||
# import pdb; pdb.set_trace()
|
||||
self.model = delete_from_trade(lot, ids)
|
||||
|
||||
if g.user == lot.trade.author:
|
||||
for dev in devices:
|
||||
ac = dev.last_action_trading
|
||||
if ac.type == 'Confirm' and ac.user == g.user:
|
||||
without_confirms.add(dev)
|
||||
# devices = set(data['devices'])
|
||||
# without_confirms = set() # set of devs without confirms of user2
|
||||
|
||||
# we need to mark one revoke for every devs
|
||||
revoke = Revoke(action=lot.trade, user=g.user, devices=devices)
|
||||
db.session.add(revoke)
|
||||
# if g.user == lot.trade.author:
|
||||
# for dev in devices:
|
||||
# ac = dev.last_action_trading
|
||||
# if ac.type == 'Confirm' and ac.user == g.user:
|
||||
# without_confirms.add(dev)
|
||||
|
||||
if without_confirms:
|
||||
confirm_revoke = ConfirmRevoke(
|
||||
action=revoke,
|
||||
user=g.user,
|
||||
devices=without_confirms
|
||||
)
|
||||
db.session.add(confirm_revoke)
|
||||
# # we need to mark one revoke for every devs
|
||||
# revoke = Revoke(action=lot.trade, user=g.user, devices=devices)
|
||||
# db.session.add(revoke)
|
||||
|
||||
lot.devices.difference_update(without_confirms)
|
||||
lot.trade.devices = lot.devices
|
||||
# if without_confirms:
|
||||
# confirm_revoke = ConfirmRevoke(
|
||||
# action=revoke,
|
||||
# user=g.user,
|
||||
# devices=without_confirms
|
||||
# )
|
||||
# db.session.add(confirm_revoke)
|
||||
|
||||
self.model = revoke
|
||||
# lot.devices.difference_update(without_confirms)
|
||||
# lot.trade.devices = lot.devices
|
||||
|
||||
# self.model = revoke
|
||||
|
||||
|
||||
class ConfirmRevokeView(ConfirmMixin):
|
||||
|
@ -287,38 +261,18 @@ class ConfirmRevokeView(ConfirmMixin):
|
|||
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 = []
|
||||
"""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']:
|
||||
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 not dev.trading == 'Revoke':
|
||||
txt = 'Some of devices do not have revoke to confirm'
|
||||
ValidationError(txt)
|
||||
|
||||
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
|
||||
|
||||
devices = OrderedSet(real_devices)
|
||||
devices = OrderedSet(data['devices'])
|
||||
data['devices'] = devices
|
||||
|
||||
# Change the owner for every devices
|
||||
|
@ -326,10 +280,6 @@ class ConfirmRevokeView(ConfirmMixin):
|
|||
|
||||
trade = data['action'].action
|
||||
for dev in devices:
|
||||
# TODO @cayop if it's possible the both users insert devices into a lot, then there are problems
|
||||
dev.owner = trade.author
|
||||
if hasattr(dev, 'components'):
|
||||
for c in dev.components:
|
||||
c.owner = trade.author
|
||||
dev.reset_owner()
|
||||
|
||||
trade.lot.devices.difference_update(devices)
|
||||
|
|
|
@ -266,8 +266,10 @@ class Device(Thing):
|
|||
"""The trading state, or None if no Trade action has
|
||||
ever been performed to this device. This extract the posibilities for to do"""
|
||||
|
||||
trade = 'Trade'
|
||||
# trade = 'Trade'
|
||||
confirm = 'Confirm'
|
||||
need_confirm = 'NeedConfirmation'
|
||||
double_confirm = 'TradeConfirmed'
|
||||
revoke = 'Revoke'
|
||||
revoke_pending = 'RevokePending'
|
||||
confirm_revoke = 'ConfirmRevoke'
|
||||
|
@ -298,26 +300,37 @@ class Device(Thing):
|
|||
## RevokeConfirmation => RevokeConfirmed
|
||||
|
||||
ac = self.last_action_trading
|
||||
if not ac:
|
||||
return
|
||||
|
||||
first_owner = self.which_user_put_this_device_in_trace()
|
||||
|
||||
if ac.type == confirm_revoke:
|
||||
# can to do revoke_confirmed
|
||||
return confirm_revoke
|
||||
|
||||
if ac.type == revoke and ac.user == g.user:
|
||||
# can todo revoke_pending
|
||||
return revoke_pending
|
||||
if ac.type == revoke:
|
||||
if ac.user == g.user:
|
||||
# can todo revoke_pending
|
||||
return revoke_pending
|
||||
else:
|
||||
# can to do confirm_revoke
|
||||
return revoke
|
||||
|
||||
if ac.type == revoke and ac.user != g.user:
|
||||
# can to do confirm_revoke
|
||||
return revoke
|
||||
if ac.type == confirm:
|
||||
if not first_owner:
|
||||
return
|
||||
|
||||
if ac.type == confirm and (ac.user == g.user or ac.action.author == g.user):
|
||||
# can to do revoke
|
||||
return confirm
|
||||
|
||||
if ac.type == confirm and ac.user != g.user:
|
||||
# can to do confirm
|
||||
return trade
|
||||
if ac.user == first_owner:
|
||||
if first_owner == g.user:
|
||||
# can to do revoke
|
||||
return confirm
|
||||
else:
|
||||
# can to do confirm
|
||||
return need_confirm
|
||||
else:
|
||||
# can to do revoke
|
||||
return double_confirm
|
||||
|
||||
@property
|
||||
def revoke(self):
|
||||
|
@ -421,12 +434,37 @@ class Device(Thing):
|
|||
"""
|
||||
try:
|
||||
# noinspection PyTypeHints
|
||||
actions = self.actions
|
||||
actions = copy.copy(self.actions)
|
||||
actions.sort(key=lambda x: x.created)
|
||||
return next(e for e in reversed(actions) if isinstance(e, types))
|
||||
except StopIteration:
|
||||
raise LookupError('{!r} does not contain actions of types {}.'.format(self, types))
|
||||
|
||||
def which_user_put_this_device_in_trace(self):
|
||||
"""which is the user than put this device in this trade"""
|
||||
actions = copy.copy(self.actions)
|
||||
actions.sort(key=lambda x: x.created)
|
||||
actions.reverse()
|
||||
last_ac = None
|
||||
# search the automatic Confirm
|
||||
for ac in actions:
|
||||
if ac.type == 'Trade':
|
||||
return last_ac.user
|
||||
if ac.type == 'Confirm':
|
||||
last_ac = ac
|
||||
|
||||
def change_owner(self, new_user):
|
||||
"""util for change the owner one device"""
|
||||
self.owner = new_user
|
||||
if hasattr(self, 'components'):
|
||||
for c in self.components:
|
||||
c.owner = new_user
|
||||
|
||||
def reset_owner(self):
|
||||
"""Change the owner with the user put the device into the trade"""
|
||||
user = self.which_user_put_this_device_in_trace()
|
||||
self.change_owner(user)
|
||||
|
||||
def _warning_actions(self, actions):
|
||||
return sorted(ev for ev in actions if ev.severity >= Severity.Warning)
|
||||
|
||||
|
|
|
@ -230,12 +230,11 @@ class LotDeviceView(LotBaseChildrenView):
|
|||
return
|
||||
|
||||
users = [g.user.id]
|
||||
# Not for the moment
|
||||
# if lot.trade:
|
||||
if lot.trade:
|
||||
# all users involved in the trade action can modify the lot
|
||||
# trade_users = [lot.trade.user_from.id, lot.trade.user_to.id]
|
||||
# if g.user in trade_users:
|
||||
# users = trade_users
|
||||
trade_users = [lot.trade.user_from.id, lot.trade.user_to.id]
|
||||
if g.user in trade_users:
|
||||
users = trade_users
|
||||
|
||||
devices = set(Device.query.filter(Device.id.in_(ids)).filter(
|
||||
Device.owner_id.in_(users)))
|
||||
|
@ -253,47 +252,60 @@ class LotDeviceView(LotBaseChildrenView):
|
|||
if not ids.issubset({x.id for x in lot.devices}):
|
||||
return
|
||||
|
||||
users = [g.user.id]
|
||||
# import pdb; pdb.set_trace()
|
||||
if lot.trade:
|
||||
# all users involved in the trade action can modify the lot
|
||||
trade_users = [lot.trade.user_from.id, lot.trade.user_to.id]
|
||||
if g.user in trade_users:
|
||||
users = trade_users
|
||||
return delete_from_trade(lot, ids)
|
||||
|
||||
if not g.user in lot.owner:
|
||||
txt = 'This is not your trade'
|
||||
raise ma.ValidationError(txt)
|
||||
devices = set(Device.query.filter(Device.id.in_(ids)).filter(
|
||||
Device.owner_id.in_(users)))
|
||||
Device.owner_id.in_(g.user.id)))
|
||||
|
||||
if not lot.trade:
|
||||
lot.devices.difference_update(devices)
|
||||
return
|
||||
|
||||
# if is a trade
|
||||
if not g.user in [lot.trade.user_from, lot.trade.user_to]:
|
||||
# theoretically this case is impossible
|
||||
return
|
||||
lot.devices.difference_update(devices)
|
||||
|
||||
|
||||
# Now we need to know which devices we need extract of the lot
|
||||
without_confirms = set() # set of devs without confirms of user2
|
||||
def delete_from_trade(lot: Lot, ids: Set[int]):
|
||||
users = [lot.trade.user_from.id, lot.trade.user_to.id]
|
||||
if not g.user.id in users:
|
||||
# theoretically this case is impossible
|
||||
txt = 'This is not your trade'
|
||||
raise ma.ValidationError(txt)
|
||||
|
||||
if g.user == lot.trade.author:
|
||||
for dev in devices:
|
||||
ac = dev.last_action_trading
|
||||
if ac.type == 'Confirm' and ac.user == g.user:
|
||||
without_confirms.add(dev)
|
||||
# import pdb; pdb.set_trace()
|
||||
devices = set(Device.query.filter(Device.id.in_(ids)).filter(
|
||||
Device.owner_id.in_(users)))
|
||||
|
||||
# we need to mark one revoke for every devs
|
||||
revoke = Revoke(action=lot.trade, user=g.user, devices=devices)
|
||||
db.session.add(revoke)
|
||||
# Now we need to know which devices we need extract of the lot
|
||||
without_confirms = set() # set of devs without confirms of user2
|
||||
|
||||
if without_confirms:
|
||||
confirm_revoke = ConfirmRevoke(
|
||||
action=revoke,
|
||||
user=g.user,
|
||||
devices=without_confirms
|
||||
)
|
||||
db.session.add(confirm_revoke)
|
||||
# if the trade need confirmation, then extract all devs than
|
||||
# have only one confirmation and is from the same user than try to do
|
||||
# now the revoke action
|
||||
if lot.trade.confirm:
|
||||
for dev in devices:
|
||||
# if have only one confirmation
|
||||
# then can be revoked and deleted of the lot
|
||||
if dev.trading == 'NeedConfirmation':
|
||||
without_confirms.add(dev)
|
||||
dev.reset_owner()
|
||||
|
||||
lot.devices.difference_update(without_confirms)
|
||||
lot.trade.devices = lot.devices
|
||||
# we need to mark one revoke for every devs
|
||||
revoke = Revoke(action=lot.trade, user=g.user, devices=devices)
|
||||
db.session.add(revoke)
|
||||
|
||||
if not lot.trade.confirm:
|
||||
# if the trade is with phantom account
|
||||
without_confirms = devices
|
||||
|
||||
if without_confirms:
|
||||
confirm_revoke = ConfirmRevoke(
|
||||
action=revoke,
|
||||
user=g.user,
|
||||
devices=without_confirms
|
||||
)
|
||||
db.session.add(confirm_revoke)
|
||||
|
||||
lot.devices.difference_update(without_confirms)
|
||||
lot.trade.devices = lot.devices
|
||||
|
||||
return revoke
|
||||
|
|
Reference in a new issue