diff --git a/ereuse_devicehub/resources/action/views/trade.py b/ereuse_devicehub/resources/action/views/trade.py index 5f5efd31..b0569caf 100644 --- a/ereuse_devicehub/resources/action/views/trade.py +++ b/ereuse_devicehub/resources/action/views/trade.py @@ -7,6 +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 class TradeView(): @@ -221,28 +222,55 @@ class RevokeView(ConfirmMixin): Model = Revoke + def __init__(self, data, resource_def, schema): + self.schema = schema + a = resource_def.schema.load(data) + 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 """ - real_devices = [] + ### check ### + devs_confirm = [] + if not data['devices']: + raise ValidationError('Devices not exist.') + 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 dev.last_action_trading.type == 'Confirm': + devs_confirm.append(dev) - if ac.t == 'Revoke' and ac.user == g.user: - break + if not len(data['devices']) == len(devs_confirm): + txt = "Some of this devices can't be reboked" + raise ValidationError(txt) + ### End check ### - if ac.t == Confirm.t and ac.user == g.user: - real_devices.append(dev) - break + lot = data['action'].lot + devices = set(data['devices']) + without_confirms = set() # set of devs without confirms of user2 - data['devices'] = OrderedSet(real_devices) + 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) + + # we need to mark one revoke for every devs + revoke = Revoke(action=lot.trade, user=g.user, devices=devices) + db.session.add(revoke) + + 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 + + self.model = revoke class ConfirmRevokeView(ConfirmMixin): diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 1833b027..852ed4ca 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -254,39 +254,32 @@ class Device(Thing): from ereuse_devicehub.resources.action.models import Price return self.last_action_of(Price) + @property + def last_action_trading(self): + """which is the last action trading""" + from ereuse_devicehub.resources.device import states + with suppress(LookupError, ValueError): + return self.last_action_of(*states.Trading.actions()) + @property def trading(self): """The trading state, or None if no Trade action has ever been performed to this device. This extract the posibilities for to do""" - # import pdb; pdb.set_trace() trade = 'Trade' confirm = 'Confirm' revoke = 'Revoke' revoke_pending = 'RevokePending' confirm_revoke = 'ConfirmRevoke' - revoke_confirmed = 'RevokeConfirmed' - - types = [trade, confirm, revoke, confirm_revoke] - actions = copy.copy(self.actions) - actions.sort(key=lambda x: x.created) - actions.reverse() - - actions_trade = [] - - # get only the actions trade of the last trade - for ac in actions: - if ac.type in types: - actions_trade.append(ac) - - if ac.type == trade: - break + # revoke_confirmed = 'RevokeConfirmed' # return the correct status of trade depending of the user ##### CASES ##### ## User1 == owner of trade (This user have automatic Confirmation) ## ======================= + ## if the last action is => only allow to do + ## ========================================== ## Confirmation not User1 => Revoke ## Confirmation User1 => Revoke ## Revoke not User1 => ConfirmRevoke @@ -296,32 +289,35 @@ class Device(Thing): ## ## User2 == Not owner of trade ## ======================= + ## if the last action is => only allow to do + ## ========================================== ## Confirmation not User2 => Confirm ## Confirmation User2 => Revoke ## Revoke not User2 => ConfirmRevoke ## Revoke User2 => RevokePending ## RevokeConfirmation => RevokeConfirmed - for ac in actions_trade: - if ac.type == confirm_revoke: - # can to do revoke_confirmed - return confirm_revoke + ac = self.last_action_trading - if ac.type == revoke and ac.user == g.user: - # can todo revoke_pending - return revoke_pending + if ac.type == confirm_revoke: + # can to do revoke_confirmed + return confirm_revoke - if ac.type == revoke and ac.user != g.user: - # can to do confirm_revoke - return revoke + if ac.type == revoke and ac.user == g.user: + # can todo revoke_pending + return revoke_pending - if ac.type == confirm and (ac.user == g.user or ac.action.author == g.user): - # can to do revoke - return confirm + if ac.type == revoke and ac.user != g.user: + # can to do confirm_revoke + return revoke - if ac.type == confirm and ac.user != g.user: - # can to do confirm - return trade + 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 @property def revoke(self): diff --git a/ereuse_devicehub/resources/lot/views.py b/ereuse_devicehub/resources/lot/views.py index 0a3ae13b..16e27bbe 100644 --- a/ereuse_devicehub/resources/lot/views.py +++ b/ereuse_devicehub/resources/lot/views.py @@ -13,7 +13,7 @@ from teal.resource import View from ereuse_devicehub.db import db from ereuse_devicehub.query import things_response from ereuse_devicehub.resources.device.models import Device, Computer -from ereuse_devicehub.resources.action.models import Trade, Confirm, Revoke +from ereuse_devicehub.resources.action.models import Trade, Confirm, Revoke, ConfirmRevoke from ereuse_devicehub.resources.lot.models import Lot, Path @@ -254,6 +254,7 @@ class LotDeviceView(LotBaseChildrenView): 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] @@ -263,10 +264,36 @@ class LotDeviceView(LotBaseChildrenView): devices = set(Device.query.filter(Device.id.in_(ids)).filter( Device.owner_id.in_(users))) - lot.devices.difference_update(devices) + if not lot.trade: + lot.devices.difference_update(devices) + return - if lot.trade: + # if is a trade + if not g.user in [lot.trade.user_from, lot.trade.user_to]: + # theoretically this case is impossible + return + + + # Now we need to know which devices we need extract of the lot + without_confirms = set() # set of devs without confirms of user2 + + 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) + + # we need to mark one revoke for every devs + revoke = Revoke(action=lot.trade, user=g.user, devices=devices) + db.session.add(revoke) + + 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 - if g.user in [lot.trade.user_from, lot.trade.user_to]: - revoke = Revoke(action=lot.trade, user=g.user, devices=devices) - db.session.add(revoke)