resolve conflict
This commit is contained in:
commit
5ec005e63b
|
@ -14,6 +14,7 @@ ml).
|
||||||
## [1.0.10-beta]
|
## [1.0.10-beta]
|
||||||
- [addend] #170 can delete/deactivate devices.
|
- [addend] #170 can delete/deactivate devices.
|
||||||
- [bugfix] #168 can to do a trade without devices.
|
- [bugfix] #168 can to do a trade without devices.
|
||||||
|
- [addend] #167 new actions of status devices: use, recycling, refurbish and management.
|
||||||
|
|
||||||
## [1.0.9-beta]
|
## [1.0.9-beta]
|
||||||
- [addend] #159 external document as proof of erase of disk
|
- [addend] #159 external document as proof of erase of disk
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "1.0.9-beta"
|
__version__ = "1.0.10-beta"
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
"""adding state actions
|
||||||
|
|
||||||
|
Revision ID: a0978ac6cf4a
|
||||||
|
Revises: 7ecb8ff7abad
|
||||||
|
Create Date: 2021-09-24 12:03:01.661679
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op, context
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a0978ac6cf4a'
|
||||||
|
down_revision = '3ac2bc1897ce'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_inv():
|
||||||
|
INV = context.get_x_argument(as_dictionary=True).get('inventory')
|
||||||
|
if not INV:
|
||||||
|
raise ValueError("Inventory value is not specified")
|
||||||
|
return INV
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.create_table('action_status',
|
||||||
|
sa.Column('rol_user_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
|
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['id'], [f'{get_inv()}.action.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['rol_user_id'], ['common.user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
schema=f'{get_inv()}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_table('action_status', schema=f'{get_inv()}')
|
|
@ -194,6 +194,26 @@ class ReadyDef(ActionDef):
|
||||||
SCHEMA = schemas.Ready
|
SCHEMA = schemas.Ready
|
||||||
|
|
||||||
|
|
||||||
|
class RecyclingDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.Recycling
|
||||||
|
|
||||||
|
|
||||||
|
class UseDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.Use
|
||||||
|
|
||||||
|
|
||||||
|
class RefurbishDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.Refurbish
|
||||||
|
|
||||||
|
|
||||||
|
class ManagementDef(ActionDef):
|
||||||
|
VIEW = None
|
||||||
|
SCHEMA = schemas.Management
|
||||||
|
|
||||||
|
|
||||||
class ToPrepareDef(ActionDef):
|
class ToPrepareDef(ActionDef):
|
||||||
VIEW = None
|
VIEW = None
|
||||||
SCHEMA = schemas.ToPrepare
|
SCHEMA = schemas.ToPrepare
|
||||||
|
|
|
@ -1350,6 +1350,33 @@ class DataWipe(JoinedTableMixin, ActionWithMultipleDevices):
|
||||||
primaryjoin='DataWipe.document_id == DataWipeDocument.id')
|
primaryjoin='DataWipe.document_id == DataWipeDocument.id')
|
||||||
|
|
||||||
|
|
||||||
|
class ActionStatus(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
||||||
|
"""This is a meta-action than mark the status of the devices"""
|
||||||
|
|
||||||
|
rol_user_id = db.Column(UUID(as_uuid=True),
|
||||||
|
db.ForeignKey(User.id),
|
||||||
|
nullable=False,
|
||||||
|
default=lambda: g.user.id)
|
||||||
|
rol_user = db.relationship(User, primaryjoin=rol_user_id == User.id)
|
||||||
|
rol_user_comment = """The user that ."""
|
||||||
|
|
||||||
|
|
||||||
|
class Recycling(ActionStatus):
|
||||||
|
"""This action mark devices as recycling"""
|
||||||
|
|
||||||
|
|
||||||
|
class Use(ActionStatus):
|
||||||
|
"""This action mark one devices or container as use"""
|
||||||
|
|
||||||
|
|
||||||
|
class Refurbish(ActionStatus):
|
||||||
|
"""This action mark one devices or container as refurbish"""
|
||||||
|
|
||||||
|
|
||||||
|
class Management(ActionStatus):
|
||||||
|
"""This action mark one devices or container as management"""
|
||||||
|
|
||||||
|
|
||||||
class Prepare(ActionWithMultipleDevices):
|
class Prepare(ActionWithMultipleDevices):
|
||||||
"""Work has been performed to the device to a defined point of
|
"""Work has been performed to the device to a defined point of
|
||||||
acceptance.
|
acceptance.
|
||||||
|
@ -1471,6 +1498,20 @@ class CancelReservation(Organize):
|
||||||
"""The act of cancelling a reservation."""
|
"""The act of cancelling a reservation."""
|
||||||
|
|
||||||
|
|
||||||
|
class ActionStatusDocuments(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
||||||
|
"""This is a meta-action that marks the state of the devices."""
|
||||||
|
rol_user_id = db.Column(UUID(as_uuid=True),
|
||||||
|
db.ForeignKey(User.id),
|
||||||
|
nullable=False,
|
||||||
|
default=lambda: g.user.id)
|
||||||
|
rol_user = db.relationship(User, primaryjoin=rol_user_id == User.id)
|
||||||
|
rol_user_comment = """The user that ."""
|
||||||
|
|
||||||
|
|
||||||
|
class RecyclingDocument(ActionStatusDocuments):
|
||||||
|
"""This action mark one document or container as recycling"""
|
||||||
|
|
||||||
|
|
||||||
class ConfirmDocument(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
class ConfirmDocument(JoinedTableMixin, ActionWithMultipleTradeDocuments):
|
||||||
"""Users confirm the one action trade this confirmation it's link to trade
|
"""Users confirm the one action trade this confirmation it's link to trade
|
||||||
and the document that confirm
|
and the document that confirm
|
||||||
|
|
|
@ -424,6 +424,50 @@ class Ready(ActionWithMultipleDevices):
|
||||||
__doc__ = m.Ready.__doc__
|
__doc__ = m.Ready.__doc__
|
||||||
|
|
||||||
|
|
||||||
|
class ActionStatus(Action):
|
||||||
|
rol_user = NestedOn(s_user.User, dump_only=True, exclude=('token',))
|
||||||
|
devices = NestedOn(s_device.Device,
|
||||||
|
many=True,
|
||||||
|
required=False, # todo test ensuring len(devices) >= 1
|
||||||
|
only_query='id',
|
||||||
|
collection_class=OrderedSet)
|
||||||
|
documents = NestedOn(s_document.TradeDocument,
|
||||||
|
many=True,
|
||||||
|
required=False, # todo test ensuring len(devices) >= 1
|
||||||
|
only_query='id',
|
||||||
|
collection_class=OrderedSet)
|
||||||
|
|
||||||
|
@pre_load
|
||||||
|
def put_devices(self, data: dict):
|
||||||
|
if not 'devices' in data.keys():
|
||||||
|
data['devices'] = []
|
||||||
|
|
||||||
|
@post_load
|
||||||
|
def put_rol_user(self, data: dict):
|
||||||
|
for dev in data['devices']:
|
||||||
|
if dev.trading in [None, 'Revoke', 'ConfirmRevoke']:
|
||||||
|
return data
|
||||||
|
trade = [ac for ac in dev.actions if ac.t == 'Trade'][-1]
|
||||||
|
if trade.user_to != g.user:
|
||||||
|
data['rol_user'] = trade.user_to
|
||||||
|
|
||||||
|
|
||||||
|
class Recycling(ActionStatus):
|
||||||
|
__doc__ = m.Recycling.__doc__
|
||||||
|
|
||||||
|
|
||||||
|
class Use(ActionStatus):
|
||||||
|
__doc__ = m.Use.__doc__
|
||||||
|
|
||||||
|
|
||||||
|
class Refurbish(ActionStatus):
|
||||||
|
__doc__ = m.Refurbish.__doc__
|
||||||
|
|
||||||
|
|
||||||
|
class Management(ActionStatus):
|
||||||
|
__doc__ = m.Management.__doc__
|
||||||
|
|
||||||
|
|
||||||
class ToPrepare(ActionWithMultipleDevices):
|
class ToPrepare(ActionWithMultipleDevices):
|
||||||
__doc__ = m.ToPrepare.__doc__
|
__doc__ = m.ToPrepare.__doc__
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,46 @@ class Device(Thing):
|
||||||
with suppress(LookupError, ValueError):
|
with suppress(LookupError, ValueError):
|
||||||
return self.last_action_of(*states.Trading.actions())
|
return self.last_action_of(*states.Trading.actions())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
"""Show the actual status of device for this owner.
|
||||||
|
The status depend of one of this 4 actions:
|
||||||
|
- Use
|
||||||
|
- Refurbish
|
||||||
|
- Recycling
|
||||||
|
- Management
|
||||||
|
"""
|
||||||
|
from ereuse_devicehub.resources.device import states
|
||||||
|
with suppress(LookupError, ValueError):
|
||||||
|
return self.last_action_of(*states.Status.actions())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def history_status(self):
|
||||||
|
"""Show the history of the status actions of the device.
|
||||||
|
The status depend of one of this 4 actions:
|
||||||
|
- Use
|
||||||
|
- Refurbish
|
||||||
|
- Recycling
|
||||||
|
- Management
|
||||||
|
"""
|
||||||
|
from ereuse_devicehub.resources.device import states
|
||||||
|
status_actions = [ac.t for ac in states.Status.actions()]
|
||||||
|
history = []
|
||||||
|
for ac in self.actions:
|
||||||
|
if not ac.t in status_actions:
|
||||||
|
continue
|
||||||
|
if not history:
|
||||||
|
history.append(ac)
|
||||||
|
continue
|
||||||
|
if ac.rol_user == history[-1].rol_user:
|
||||||
|
# get only the last action consecutive for the same user
|
||||||
|
history = history[:-1] + [ac]
|
||||||
|
continue
|
||||||
|
|
||||||
|
history.append(ac)
|
||||||
|
|
||||||
|
return history
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def trading(self):
|
def trading(self):
|
||||||
"""The trading state, or None if no Trade action has
|
"""The trading state, or None if no Trade action has
|
||||||
|
|
|
@ -83,3 +83,16 @@ class Usage(State):
|
||||||
Allocate = e.Allocate
|
Allocate = e.Allocate
|
||||||
Deallocate = e.Deallocate
|
Deallocate = e.Deallocate
|
||||||
InUse = e.Live
|
InUse = e.Live
|
||||||
|
|
||||||
|
|
||||||
|
class Status(State):
|
||||||
|
"""Define status of device for one user.
|
||||||
|
:cvar Use: The device is in use for one final user.
|
||||||
|
:cvar Refurbish: The device is owned by one refurbisher.
|
||||||
|
:cvar Recycling: The device is sended to recycling.
|
||||||
|
:cvar Management: The device is owned by one Manager.
|
||||||
|
"""
|
||||||
|
Use = e.Use
|
||||||
|
Refurbish = e.Refurbish
|
||||||
|
Recycling = e.Recycling
|
||||||
|
Management = e.Management
|
||||||
|
|
|
@ -256,6 +256,282 @@ def test_generic_action(action_model_state: Tuple[models.Action, states.Trading]
|
||||||
assert snapshot['device']['updated'] != device['updated']
|
assert snapshot['device']['updated'] != device['updated']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.parametrize('action_model',
|
||||||
|
(pytest.param(ams, id=ams.__class__.__name__)
|
||||||
|
for ams in [
|
||||||
|
models.Recycling,
|
||||||
|
models.Use,
|
||||||
|
models.Refurbish,
|
||||||
|
models.Management
|
||||||
|
]))
|
||||||
|
def test_simple_status_actions(action_model: models.Action, user: UserClient, user2: UserClient):
|
||||||
|
"""Simple test of status action."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
|
||||||
|
action = {'type': action_model.t, 'devices': [snap['device']['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
assert action['author']['id'] == user.user['id']
|
||||||
|
assert action['rol_user']['id'] == user.user['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.parametrize('action_model',
|
||||||
|
(pytest.param(ams, id=ams.__class__.__name__)
|
||||||
|
for ams in [
|
||||||
|
models.Recycling,
|
||||||
|
models.Use,
|
||||||
|
models.Refurbish,
|
||||||
|
models.Management
|
||||||
|
]))
|
||||||
|
def test_outgoinlot_status_actions(action_model: models.Action, user: UserClient, user2: UserClient):
|
||||||
|
"""Test of status actions in outgoinlot."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||||
|
user.post({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device['id'])])
|
||||||
|
|
||||||
|
request_post = {
|
||||||
|
'type': 'Trade',
|
||||||
|
'devices': [device['id']],
|
||||||
|
'userFromEmail': user.email,
|
||||||
|
'userToEmail': user2.email,
|
||||||
|
'price': 10,
|
||||||
|
'date': "2020-12-01T02:00:00+00:00",
|
||||||
|
'lot': lot['id'],
|
||||||
|
'confirms': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
user.post(res=models.Action, data=request_post)
|
||||||
|
action = {'type': action_model.t, 'devices': [device['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
assert action['author']['id'] == user.user['id']
|
||||||
|
assert action['rol_user']['id'] == user2.user['id']
|
||||||
|
|
||||||
|
# Remove device from lot
|
||||||
|
lot, _ = user.delete({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device['id'])], status=200)
|
||||||
|
|
||||||
|
action = {'type': action_model.t, 'devices': [device['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
assert action['author']['id'] == user.user['id']
|
||||||
|
assert action['rol_user']['id'] == user.user['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.parametrize('action_model',
|
||||||
|
(pytest.param(ams, id=ams.__class__.__name__)
|
||||||
|
for ams in [
|
||||||
|
models.Recycling,
|
||||||
|
models.Use,
|
||||||
|
models.Refurbish,
|
||||||
|
models.Management
|
||||||
|
]))
|
||||||
|
def test_incominglot_status_actions(action_model: models.Action, user: UserClient, user2: UserClient):
|
||||||
|
"""Test of status actions in outgoinlot."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||||
|
user.post({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device['id'])])
|
||||||
|
|
||||||
|
request_post = {
|
||||||
|
'type': 'Trade',
|
||||||
|
'devices': [device['id']],
|
||||||
|
'userFromEmail': user2.email,
|
||||||
|
'userToEmail': user.email,
|
||||||
|
'price': 10,
|
||||||
|
'date': "2020-12-01T02:00:00+00:00",
|
||||||
|
'lot': lot['id'],
|
||||||
|
'confirms': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
user.post(res=models.Action, data=request_post)
|
||||||
|
action = {'type': action_model.t, 'devices': [device['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
assert action['author']['id'] == user.user['id']
|
||||||
|
assert action['rol_user']['id'] == user.user['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_history_status_actions(user: UserClient, user2: UserClient):
|
||||||
|
"""Test for check the status actions."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
device = Device.query.filter_by(id=snap['device']['id']).one()
|
||||||
|
|
||||||
|
# Case 1
|
||||||
|
action = {'type': models.Recycling.t, 'devices': [device.id]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
|
||||||
|
assert str(device.actions[-1].id) == action['id']
|
||||||
|
assert action['id'] == str(device.status.id)
|
||||||
|
assert device.status.t == models.Recycling.t
|
||||||
|
assert [action['id']] == [str(ac.id) for ac in device.history_status]
|
||||||
|
|
||||||
|
# Case 2
|
||||||
|
action2 = {'type': models.Refurbish.t, 'devices': [device.id]}
|
||||||
|
action2, _ = user.post(action2, res=models.Action)
|
||||||
|
assert action2['id'] == str(device.status.id)
|
||||||
|
assert device.status.t == models.Refurbish.t
|
||||||
|
assert [action2['id']] == [str(ac.id) for ac in device.history_status]
|
||||||
|
|
||||||
|
# Case 3
|
||||||
|
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||||
|
user.post({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device.id)])
|
||||||
|
|
||||||
|
request_post = {
|
||||||
|
'type': 'Trade',
|
||||||
|
'devices': [device.id],
|
||||||
|
'userFromEmail': user.email,
|
||||||
|
'userToEmail': user2.email,
|
||||||
|
'price': 10,
|
||||||
|
'date': "2020-12-01T02:00:00+00:00",
|
||||||
|
'lot': lot['id'],
|
||||||
|
'confirms': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
user.post(res=models.Action, data=request_post)
|
||||||
|
action3 = {'type': models.Use.t, 'devices': [device.id]}
|
||||||
|
action3, _ = user.post(action3, res=models.Action)
|
||||||
|
assert action3['id'] == str(device.status.id)
|
||||||
|
assert device.status.t == models.Use.t
|
||||||
|
assert [action2['id'], action3['id']] == [str(ac.id) for ac in device.history_status]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_use_changing_owner(user: UserClient, user2: UserClient):
|
||||||
|
"""Check if is it possible to do a use action for one device
|
||||||
|
when you are not the owner.
|
||||||
|
"""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
device = Device.query.filter_by(id=snap['device']['id']).one()
|
||||||
|
|
||||||
|
assert device.owner.email == user.email
|
||||||
|
|
||||||
|
# Trade
|
||||||
|
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||||
|
user.post({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device.id)])
|
||||||
|
|
||||||
|
request_post = {
|
||||||
|
'type': 'Trade',
|
||||||
|
'devices': [device.id],
|
||||||
|
'userFromEmail': user.email,
|
||||||
|
'userToEmail': user2.email,
|
||||||
|
'price': 10,
|
||||||
|
'date': "2020-12-01T02:00:00+00:00",
|
||||||
|
'lot': lot['id'],
|
||||||
|
'confirms': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
user.post(res=models.Action, data=request_post)
|
||||||
|
trade = models.Trade.query.one()
|
||||||
|
|
||||||
|
# Doble confirmation and change of owner
|
||||||
|
request_confirm = {
|
||||||
|
'type': 'Confirm',
|
||||||
|
'action': trade.id,
|
||||||
|
'devices': [device.id]
|
||||||
|
}
|
||||||
|
|
||||||
|
user2.post(res=models.Action, data=request_confirm)
|
||||||
|
assert device.owner.email == user2.email
|
||||||
|
|
||||||
|
# Adding action Use
|
||||||
|
action3 = {'type': models.Use.t, 'devices': [device.id]}
|
||||||
|
action3, _ = user.post(action3, res=models.Action)
|
||||||
|
assert action3['id'] == str(device.status.id)
|
||||||
|
assert device.status.t == models.Use.t
|
||||||
|
assert device.owner.email == user2.email
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_recycling_container(user: UserClient):
|
||||||
|
"""Test of status action recycling for a container."""
|
||||||
|
lot, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
||||||
|
url = 'http://www.ereuse.org/',
|
||||||
|
request_post = {
|
||||||
|
'filename': 'test.pdf',
|
||||||
|
'hash': 'bbbbbbbb',
|
||||||
|
'url': url,
|
||||||
|
'weight': 150,
|
||||||
|
'lot': lot['id']
|
||||||
|
}
|
||||||
|
tradedocument, _ = user.post(res=TradeDocument, data=request_post)
|
||||||
|
action = {'type': models.Recycling.t, 'devices': [], 'documents': [tradedocument['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
trade = TradeDocument.query.one()
|
||||||
|
assert str(trade.actions[0].id) == action['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.parametrize('action_model',
|
||||||
|
(pytest.param(ams, id=ams.__class__.__name__)
|
||||||
|
for ams in [
|
||||||
|
models.Recycling,
|
||||||
|
models.Use,
|
||||||
|
models.Refurbish,
|
||||||
|
models.Management
|
||||||
|
]))
|
||||||
|
def test_status_without_lot(action_model: models.Action, user: UserClient):
|
||||||
|
"""Test of status actions for devices without lot."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
action = {'type': action_model.t, 'devices': [snap['device']['id']]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.parametrize('action_model',
|
||||||
|
(pytest.param(ams, id=ams.__class__.__name__)
|
||||||
|
for ams in [
|
||||||
|
models.Recycling,
|
||||||
|
models.Use,
|
||||||
|
models.Refurbish,
|
||||||
|
models.Management
|
||||||
|
]))
|
||||||
|
def test_status_in_temporary_lot(action_model: models.Action, user: UserClient):
|
||||||
|
"""Test of status actions for devices in a temporary lot."""
|
||||||
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
device_id = snap['device']['id']
|
||||||
|
lot, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
||||||
|
lot, _ = user.post({},
|
||||||
|
res=Lot,
|
||||||
|
item='{}/devices'.format(lot['id']),
|
||||||
|
query=[('id', device_id)])
|
||||||
|
action = {'type': action_model.t, 'devices': [device_id]}
|
||||||
|
action, _ = user.post(action, res=models.Action)
|
||||||
|
device, _ = user.get(res=Device, item=snap['device']['devicehubID'])
|
||||||
|
assert device['actions'][-1]['id'] == action['id']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_live(user: UserClient, client: Client, app: Devicehub):
|
def test_live(user: UserClient, client: Client, app: Devicehub):
|
||||||
|
|
|
@ -59,59 +59,6 @@ def test_api_docs(client: Client):
|
||||||
'/users/',
|
'/users/',
|
||||||
'/users/login/',
|
'/users/login/',
|
||||||
'/users/logout/',
|
'/users/logout/',
|
||||||
# '/devices/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/batteries/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/bikes/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/cameras/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/cellphones/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/components/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/computer-accessories/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/computer-monitors/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/computers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/cookings/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/data-storages/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/dehumidifiers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/desktops/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/displays/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/diy-and-gardenings/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/drills/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/graphic-cards/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/hard-drives/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/homes/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/hubs/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/keyboards/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/label-printers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/laptops/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/memory-card-readers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/mice/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/microphones/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/mixers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/mobiles/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/monitors/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/motherboards/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/network-adapters/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/networkings/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/pack-of-screwdrivers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/printers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/processors/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/rackets/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/ram-modules/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/recreations/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/routers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/sais/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/servers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/smartphones/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/solid-state-drives/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/sound-cards/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/sounds/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/stairs/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/switches/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/tablets/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/television-sets/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/video-scalers/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/videoconferences/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/videos/{dev1_id}/merge/{dev2_id}',
|
|
||||||
# '/wireless-access-points/{dev1_id}/merge/{dev2_id}',
|
|
||||||
}
|
}
|
||||||
assert docs['info'] == {'title': 'Devicehub', 'version': '0.2'}
|
assert docs['info'] == {'title': 'Devicehub', 'version': '0.2'}
|
||||||
assert docs['components']['securitySchemes']['bearerAuth'] == {
|
assert docs['components']['securitySchemes']['bearerAuth'] == {
|
||||||
|
@ -122,4 +69,4 @@ def test_api_docs(client: Client):
|
||||||
'scheme': 'basic',
|
'scheme': 'basic',
|
||||||
'name': 'Authorization'
|
'name': 'Authorization'
|
||||||
}
|
}
|
||||||
assert len(docs['definitions']) == 128
|
assert len(docs['definitions']) == 132
|
||||||
|
|
Reference in New Issue