diff --git a/ereuse_devicehub/resources/action/views/trade.py b/ereuse_devicehub/resources/action/views/trade.py index 4aac48d4..842808ba 100644 --- a/ereuse_devicehub/resources/action/views/trade.py +++ b/ereuse_devicehub/resources/action/views/trade.py @@ -215,73 +215,12 @@ class RevokeView(ConfirmMixin): def validate(self, data): """All devices need to have the status of DoubleConfirmation.""" - ### check ### - if not data['devices']: + devices = data['devices'] + if not devices: raise ValidationError('Devices not exist.') lot = data['action'].lot - - revokeConfirmed = [] - for dev in data['devices']: - if dev.trading(lot) == 'RevokeConfirmed': - # this device is revoked before - revokeConfirmed.append(dev) - ### End check ### - - devices = {d for d in data['devices'] if d not in revokeConfirmed} - # self.model = delete_from_trade(lot, devices) - # TODO @cayop we dont need delete_from_trade - - drop_of_lot = [] - # import pdb; pdb.set_trace() - for dev in devices: - # import pdb; pdb.set_trace() - if dev.trading_for_web(lot) in ['NeedConfirmation', 'Confirm', 'NeedConfirmRevoke']: - drop_of_lot.append(dev) - dev.reset_owner() - - self.model = Revoke(action=lot.trade, user=g.user, devices=devices) - db.session.add(self.model) - lot.devices.difference_update(OrderedSet(drop_of_lot)) - - -# 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): -# """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) - -# lot = data['action'].lot -# for dev in data['devices']: -# if not dev.trading(lot) == '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) + self.model = delete_from_trade(lot, devices) class ConfirmDocumentMixin(): diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 842c009d..e74cad0a 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -1,5 +1,6 @@ import pathlib import copy +import time from flask import g from contextlib import suppress from fractions import Fraction @@ -337,6 +338,7 @@ class Device(Thing): user_from_revoke = False user_to_revoke = False status = 0 + last_action = {'confirm': 0, 'revoke': 0} if not hasattr(trade, 'acceptances'): return Status[status] @@ -351,19 +353,29 @@ class Device(Thing): if ac.t == 'Confirm' and ac.action == trade: if ac.user == user_from: user_from_confirm = True + # import pdb; pdb.set_trace() + last_action['confirm'] = time.mktime(ac.created.timetuple()) + user_from_revoke, user_to_revoke = False, False elif ac.user == user_to: user_to_confirm = True + last_action['confirm'] = time.mktime(ac.created.timetuple()) + user_from_revoke, user_to_revoke = False, False if ac.t == 'Revoke' and ac.action == trade: if ac.user == user_from: user_from_revoke = True + last_action['revoke'] = time.mktime(ac.created.timetuple()) + user_from_confirm, user_to_confirm = False, False elif ac.user == user_to: user_to_revoke = True + last_action['revoke'] = time.mktime(ac.created.timetuple()) + user_from_confirm, user_to_confirm = False, False confirms = [user_from_confirm, user_to_confirm] revokes = [user_from_revoke, user_to_revoke] - if any(confirms): + confirm_vs_revoke = 'confirm' if last_action['confirm'] > last_action['revoke'] else 'revoke' + if any(confirms) and confirm_vs_revoke == 'confirm': status = 1 if user_to_confirm and user_from == g.user: status = 2 @@ -373,7 +385,7 @@ class Device(Thing): if all(confirms): status = 3 - if any(revokes): + if any(revokes) and confirm_vs_revoke == 'revoke': status = 4 if user_to_revoke and user_from == g.user: status = 5 @@ -550,8 +562,7 @@ class Device(Thing): # search the automatic Confirm for ac in actions: if ac.type == 'Trade': - # import pdb; pdb.set_trace() - action_device = [x.device for x in ac.actions_device if x.device == self][0] + action_device = [x for x in ac.actions_device if x.device == self][0] if action_device.author: return action_device.author diff --git a/ereuse_devicehub/resources/lot/views.py b/ereuse_devicehub/resources/lot/views.py index 12309888..6ee86cdf 100644 --- a/ereuse_devicehub/resources/lot/views.py +++ b/ereuse_devicehub/resources/lot/views.py @@ -1,4 +1,5 @@ import uuid +from sqlalchemy.util import OrderedSet from collections import deque from enum import Enum from typing import Dict, List, Set, Union @@ -246,7 +247,8 @@ class LotDeviceView(LotBaseChildrenView): return if lot.trade: - return delete_from_trade(lot, ids) + devices = Device.query.filter(Device.id.in_(ids)).all() + return delete_from_trade(lot, devices) if not g.user == lot.owner: txt = 'This is not your lot' @@ -258,7 +260,46 @@ class LotDeviceView(LotBaseChildrenView): lot.devices.difference_update(devices) -def delete_from_trade(lot: Lot, ids: Set[int]): +def delete_from_trade(lot: Lot, devices: List): + users = [lot.trade.user_from.id, lot.trade.user_to.id] + if g.user.id not in users: + # theoretically this case is impossible + txt = 'This is not your trade' + raise ma.ValidationError(txt) + + drop_of_lot = [] + without_confirms = [] + for dev in devices: + if dev.trading_for_web(lot) in ['NeedConfirmation', 'Confirm', 'NeedConfirmRevoke']: + drop_of_lot.append(dev) + dev.reset_owner() + + if lot.trade.confirm: + drop_of_lot.append(dev) + without_confirms.append(dev) + dev.reset_owner() + + + revoke = Revoke(action=lot.trade, user=g.user, devices=set(devices)) + db.session.add(revoke) + + if without_confirms: + phantom = lot.trade.user_to + if lot.trade.user_to == g.user: + phantom = lot.trade.user_from + + phantom_revoke = Revoke( + action=lot.trade, + user=phantom, + devices=set(without_confirms) + ) + db.session.add(phantom_revoke) + + lot.devices.difference_update(OrderedSet(drop_of_lot)) + return revoke + + +def delete_from_trade2(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 @@ -280,7 +321,7 @@ def delete_from_trade(lot: Lot, ids: Set[int]): # then can be revoked and deleted of the lot # Confirm of dev.trading mean that there are only one confirmation # and the first user than put this device in trade is the actual g.user - if dev.trading(lot) == 'Confirm': + if dev.trading(lot) == 'Confirm': without_confirms.add(dev) dev.reset_owner()