Merge pull request #371 from eReuse/changes/3888-phid

Changes/3888 phid
This commit is contained in:
cayop 2022-10-05 14:23:24 +02:00 committed by GitHub
commit 6bb43575b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 143 additions and 143 deletions

View file

@ -322,7 +322,7 @@ class NewDeviceForm(FlaskForm):
default=1,
)
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
phid = StringField('Placeholder Hardware identity (Phid)', [validators.Optional()])
id_device_internal = StringField('Id Internal', [validators.Optional()])
pallet = StringField('Identity of pallet', [validators.Optional()])
components = TextAreaField('Components', [validators.Optional()])
info = TextAreaField('Info', [validators.Optional()])
@ -382,7 +382,7 @@ class NewDeviceForm(FlaskForm):
self.type.data = self._obj.type
self.amount.render_kw = disabled
self.id_device_supplier.data = self._obj.placeholder.id_device_supplier
self.phid.data = self._obj.placeholder.phid
self.id_device_internal.data = self._obj.placeholder.id_device_internal
self.pallet.data = self._obj.placeholder.pallet
self.info.data = self._obj.placeholder.info
self.components.data = self._obj.placeholder.components
@ -411,7 +411,7 @@ class NewDeviceForm(FlaskForm):
if self._obj.placeholder.is_abstract:
self.type.render_kw = disabled
self.amount.render_kw = disabled
self.id_device_supplier.render_kw = disabled
# self.id_device_supplier.render_kw = disabled
self.pallet.render_kw = disabled
self.info.render_kw = disabled
self.components.render_kw = disabled
@ -476,28 +476,6 @@ class NewDeviceForm(FlaskForm):
self.meid.errors = error
is_valid = False
if self.phid.data and self.amount.data == 1 and not self._obj:
dev = Placeholder.query.filter(
Placeholder.phid == self.phid.data, Placeholder.owner == g.user
).first()
if dev:
msg = "Error, exist one Placeholder device with this PHID"
self.phid.errors = [msg]
is_valid = False
if (
self.phid.data
and self._obj
and self.phid.data != self._obj.placeholder.phid
):
dev = Placeholder.query.filter(
Placeholder.phid == self.phid.data, Device.owner == g.user
).first()
if dev:
msg = "Error, exist one Placeholder device with this PHID"
self.phid.errors = [msg]
is_valid = False
if not is_valid:
return False
@ -579,8 +557,8 @@ class NewDeviceForm(FlaskForm):
def reset_ids(self):
if self.amount.data > 1:
self.phid.data = None
self.id_device_supplier.data = None
self.id_device_internal.data = None
self.serial_number.data = None
self.part_number.data = None
self.sku.data = None
@ -590,8 +568,8 @@ class NewDeviceForm(FlaskForm):
def get_placeholder(self):
self.placeholder = Placeholder(
**{
'phid': self.phid.data or None,
'id_device_supplier': self.id_device_supplier.data,
'id_device_internal': self.id_device_internal.data,
'info': self.info.data,
'components': self.components.data,
'pallet': self.pallet.data,
@ -601,11 +579,13 @@ class NewDeviceForm(FlaskForm):
return self.placeholder
def edit_device(self):
self._obj.placeholder.phid = self.phid.data or self._obj.placeholder.phid
if not self._obj.placeholder.is_abstract:
self._obj.placeholder.id_device_supplier = (
self.id_device_supplier.data or None
)
self._obj.placeholder.id_device_internal = (
self.id_device_internal.data or None
)
self._obj.placeholder.info = self.info.data or None
self._obj.placeholder.components = self.components.data or None
self._obj.placeholder.pallet = self.pallet.data or None
@ -1514,9 +1494,7 @@ class UploadPlaceholderForm(FlaskForm):
else:
self.source = "Excel File: {}".format(_file.filename)
try:
data = (
pd.read_excel(_file, converters={'Phid': str}).fillna('').to_dict()
)
data = pd.read_excel(_file).fillna('').to_dict()
except ValueError:
txt = ["File don't have a correct format"]
self.placeholder_file.errors = txt
@ -1538,12 +1516,12 @@ class UploadPlaceholderForm(FlaskForm):
return False
header = [
'Phid',
'Model',
'Manufacturer',
'Serial Number',
'Part Number',
'Id device Supplier',
'Id device Internal',
'Pallet',
'Info',
]
@ -1557,32 +1535,7 @@ class UploadPlaceholderForm(FlaskForm):
self.placeholders = []
schema = SnapshotSchema()
self.path_snapshots = {}
for i in data['Phid'].keys():
placeholder = None
data['Phid'][i] = str(data['Phid'][i])
if data['Phid'][i]:
placeholder = Placeholder.query.filter_by(phid=data['Phid'][i]).first()
# update one
if placeholder:
self.dev_update += 1
device = placeholder.device
device.model = "{}".format(data['Model'][i]).lower()
device.manufacturer = "{}".format(data['Manufacturer'][i]).lower()
device.serial_number = "{}".format(data['Serial Number'][i]).lower()
device.part_number = "{}".format(data['Part Number'][i]).lower()
placeholder.id_device_supplier = "{}".format(
data['Id device Supplier'][i]
)
placeholder.pallet = "{}".format(data['Pallet'][i])
placeholder.info = "{}".format(data['Info'][i])
placeholder_log = PlaceholdersLog(
type="Update", source=self.source, placeholder=device.placeholder
)
self.placeholders.append((device, placeholder_log))
continue
for i in data['Model'].keys():
# create a new one
json_snapshot = {
'type': 'Snapshot',
@ -1597,8 +1550,8 @@ class UploadPlaceholderForm(FlaskForm):
},
}
json_placeholder = {
'phid': data['Phid'][i] or None,
'id_device_supplier': data['Id device Supplier'][i],
'id_device_internal': data['Id device Internal'][i],
'pallet': data['Pallet'][i],
'info': data['Info'][i],
'is_abstract': False,
@ -1635,7 +1588,6 @@ class EditPlaceholderForm(FlaskForm):
serial_number = StringField('Serial Number', [validators.Optional()])
part_number = StringField('Part Number', [validators.Optional()])
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
phid = StringField('Phid', [validators.DataRequired()])
pallet = StringField('Pallet', [validators.Optional()])
info = StringField('Info', [validators.Optional()])

View file

@ -545,7 +545,7 @@ class DeviceCreateView(GenericMixin):
tpy = form.type.data
txt = f'{amount} placeholders Device "{tpy}" created successfully.'
placeholder = (
Placeholder.query.filter_by(owner=g.user)
Placeholder.query.filter(Placeholder.owner == g.user)
.order_by(Placeholder.id.desc())
.first()
)

View file

@ -0,0 +1,59 @@
"""id internal in placeholder
Revision ID: 626c17026ca7
Revises: e919fe0611ff
Create Date: 2022-10-03 19:25:00.581699
"""
import sqlalchemy as sa
from alembic import context, op
# revision identifiers, used by Alembic.
revision = '626c17026ca7'
down_revision = 'e919fe0611ff'
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_datas():
con = op.get_bind()
sql = 'select id from common.user where phantom=false and active=true'
users = con.execute(sql)
for user in users:
phid = 1
user_id = user.id
sql = f"""
select id from {get_inv()}.placeholder where owner_id='{user_id}'
order by id
"""
placeholders = con.execute(sql)
for p in placeholders:
p_id = p.id
sql = f"""
update {get_inv()}.placeholder set phid='{phid}'
where id='{p_id}'
"""
con.execute(sql)
phid += 1
def upgrade():
op.add_column(
'placeholder',
sa.Column('id_device_internal', sa.Unicode(), nullable=True),
schema=f'{get_inv()}',
)
upgrade_datas()
def downgrade():
op.drop_column('placeholder', 'id_device_internal', schema=f'{get_inv()}')

View file

@ -10,7 +10,6 @@ from boltons import urlutils
from citext import CIText
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
from flask import g, request
from flask_sqlalchemy import event
from more_itertools import unique_everseen
from sqlalchemy import BigInteger, Boolean, Column
from sqlalchemy import Enum as DBEnum
@ -75,11 +74,15 @@ def create_code(context):
return hashcode.encode(_id)
def create_phid(context):
_hid = Placeholder.query.order_by(Placeholder.id.desc()).first()
if _hid:
return str(_hid.id + 1)
return '1'
def create_phid(context, count=1):
phid = str(Placeholder.query.filter(Placeholder.owner == g.user).count() + count)
if (
Placeholder.query.filter(Placeholder.owner == g.user)
.filter(Placeholder.phid == phid)
.count()
):
return create_phid(context, count=count + 1)
return phid
class Device(Thing):
@ -901,8 +904,8 @@ class DisplayMixin:
class Placeholder(Thing):
id = Column(BigInteger, Sequence('placeholder_seq'), primary_key=True)
pallet = Column(Unicode(), nullable=True)
phid = Column(Unicode(), nullable=False, default=create_phid)
pallet = Column(Unicode(), nullable=True)
pallet.comment = "used for identification where from where is this placeholders"
info = db.Column(CIText())
components = Column(CIText())
@ -912,6 +915,8 @@ class Placeholder(Thing):
id_device_supplier.comment = (
"Identification used for one supplier of one placeholders"
)
id_device_internal = db.Column(CIText())
id_device_internal.comment = "Identification used internaly for the user"
device_id = db.Column(
BigInteger,
@ -1593,4 +1598,5 @@ def create_code_tag(mapper, connection, device):
db.session.add(tag)
# from flask_sqlalchemy import event
# event.listen(Device, 'after_insert', create_code_tag, propagate=True)

View file

@ -29,14 +29,18 @@ function amountInputs() {
if ($("#amount").val() > 1) {
$("#Phid").hide();
$("#Id_device_supplier").hide();
$("#Id_device_internal").hide();
$("#Serial_number").hide();
$("#Part_number").hide();
$("#Sku").hide();
$("#imei").hide();
$("#meid").hide();
} else {
$("#Phid").show();
$("#Id_device_supplier").show();
$("#Id_device_internal").show();
$("#Serial_number").show();
$("#Part_number").show();
$("#Sku").show();
deviceInputs();
};

View file

@ -90,19 +90,6 @@
{% endif %}
</div>
<div class="form-group mb-2" id="Phid">
<label for="label" class="form-label">{{ form.phid.label }}</label>
{{ form.phid(class_="form-control") }}
<small class="text-muted form-text">Label that you want link to this device</small>
{% if form.phid.errors %}
<p class="text-danger">
{% for error in form.phid.errors %}
{{ error }}<br/>
{% endfor %}
</p>
{% endif %}
</div>
<div class="form-group mb-2" id="Id_device_supplier">
<label for="label" class="form-label">{{ form.id_device_supplier.label }}</label>
{{ form.id_device_supplier(class_="form-control") }}
@ -116,6 +103,19 @@
{% endif %}
</div>
<div class="form-group mb-2" id="Id_device_internal">
<label for="label" class="form-label">{{ form.id_device_internal.label }}</label>
{{ form.id_device_internal(class_="form-control") }}
<small class="text-muted form-text">Identity of device for the internal</small>
{% if form.id_device_internal.errors %}
<p class="text-danger">
{% for error in form.id_device_internal.errors %}
{{ error }}<br/>
{% endfor %}
</p>
{% endif %}
</div>
<div class="form-group mb-2">
<label for="label" class="form-label">{{ form.pallet.label }}</label>
{{ form.pallet(class_="form-control") }}

View file

@ -98,6 +98,11 @@
<div class="col-lg-9 col-md-8">{{ placeholder.phid }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label ">Id device internal</div>
<div class="col-lg-9 col-md-8">{{ placeholder.id_device_internal or '' }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label ">Type</div>
<div class="col-lg-9 col-md-8">{{ placeholder.device.type }}</div>

View file

@ -1,4 +1,4 @@
Phid;Model;Manufacturer;Serial Number;Part Number;Id device Supplier;Pallet;Info
a123;Vaio;Sony;12345678;;TTT;24A;Good conditions
a124;Vaio;Sony;12345679;;TTT;24A;Good conditions
a125;Vaio;Sony;12345680;;TTT;24A;Good conditions
Model;Manufacturer;Serial Number;Part Number;Id device Supplier;Id device Internal;Pallet;Info
Vaio;Sony;12345678;;TTT;AA;24A;Good conditions
Vaio;Sony;12345679;;TTT;BB;24A;Good conditions
Vaio;Sony;12345680;;TTT;CC;24A;Good conditions

1 Phid Model Manufacturer Serial Number Part Number Id device Supplier Id device Internal Pallet Info
2 a123 Vaio Sony 12345678 TTT AA 24A Good conditions
3 a124 Vaio Sony 12345679 TTT BB 24A Good conditions
4 a125 Vaio Sony 12345680 TTT CC 24A Good conditions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -561,7 +561,6 @@ def test_update_monitor(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Monitor",
'phid': '1',
'serial_number': "AAAAB",
'model': "LCD 43 b",
'manufacturer': "Samsung",
@ -574,8 +573,9 @@ def test_update_monitor(user3: UserClientFlask):
}
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert 'Error, exist one Placeholder device with this PHID' in body
dev = Device.query.one()
# assert 'Error, exist one Placeholder device with this PHID' in body
dev = Device.query.all()[0]
assert Device.query.count() == 2
assert dev.type == 'Monitor'
assert dev.placeholder.id_device_supplier == "b2"
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
@ -596,7 +596,6 @@ def test_add_2_monitor(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Monitor",
'phid': "AAB",
'serial_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
@ -618,7 +617,7 @@ def test_add_2_monitor(user3: UserClientFlask):
assert typ == 'Monitor'
assert dev.placeholder.id_device_supplier == "b1"
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
assert phid == 'AAB'
assert phid == '1'
assert dhid == 'O48N2'
assert dev.model == 'lc27t55'
assert dev.placeholder.pallet == "l34"
@ -736,35 +735,6 @@ def test_add_with_ammount_laptops(user3: UserClientFlask):
assert Device.query.count() == num
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_add_laptop_duplicate(user3: UserClientFlask):
uri = '/inventory/device/add/'
body, status = user3.get(uri)
assert status == '200 OK'
assert "New Device" in body
data = {
'csrf_token': generate_csrf(),
'type': "Laptop",
'phid': 'laptop-asustek_computer_inc-1001pxd-b8oaas048285-14:da:e9:42:f6:7b',
'serial_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
'generation': 1,
'weight': 0.1,
'height': 0.1,
'depth': 0.1,
}
body, status = user3.post(uri, data=data)
assert status == '200 OK'
assert Device.query.count() == 1
body, status = user3.post(uri, data=data)
assert 'Error, exist one Placeholder device with this PHID' in body
assert Device.query.count() == 1
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_filter_monitor(user3: UserClientFlask):
@ -1728,7 +1698,7 @@ def test_add_placeholder_excel(user3: UserClientFlask):
assert Device.query.count() == 3
dev = Device.query.first()
assert dev.hid == 'laptop-sony-vaio-12345678'
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
assert dev.placeholder.info == 'Good conditions'
assert dev.placeholder.pallet == '24A'
assert dev.placeholder.id_device_supplier == 'TTT'
@ -1754,7 +1724,7 @@ def test_add_placeholder_csv(user3: UserClientFlask):
assert Device.query.count() == 3
dev = Device.query.first()
assert dev.hid == 'laptop-sony-vaio-12345678'
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
assert dev.placeholder.info == 'Good conditions'
assert dev.placeholder.pallet == '24A'
assert dev.placeholder.id_device_supplier == 'TTT'
@ -1780,7 +1750,7 @@ def test_add_placeholder_ods(user3: UserClientFlask):
assert Device.query.count() == 3
dev = Device.query.first()
assert dev.hid == 'laptop-sony-vaio-12345678'
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
assert dev.placeholder.info == 'Good conditions'
assert dev.placeholder.pallet == '24A'
assert dev.placeholder.id_device_supplier == 'TTT'
@ -1808,10 +1778,11 @@ def test_add_placeholder_office_open_xml(user3: UserClientFlask):
assert Device.query.count() == 3
dev = Device.query.first()
assert dev.hid == 'laptop-sony-vaio-12345678'
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
assert dev.placeholder.info == 'Good conditions'
assert dev.placeholder.pallet == '24A'
assert dev.placeholder.id_device_supplier == 'TTT'
assert dev.placeholder.id_device_internal == 'AA'
@pytest.mark.mvp
@ -1920,8 +1891,8 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Laptop",
'phid': 'ace',
'serial_number': "AAAAB",
'part_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
'generation': 1,
@ -1929,9 +1900,13 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
'height': 0.1,
'depth': 0.1,
'id_device_supplier': "b2",
'id_device_internal': "b2i",
}
user3.post(uri, data=data)
dev = Device.query.one()
plz = Placeholder.query.first()
assert plz.id_device_supplier == "b2"
assert plz.id_device_internal == "b2i"
uri = '/inventory/device/edit/{}/'.format(dev.devicehub_id)
user3.get(uri)
@ -1947,16 +1922,20 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
'height': 0.1,
'depth': 0.1,
'id_device_supplier': "a2",
'id_device_internal': "a2i",
}
user3.post(uri, data=data)
plz = Placeholder.query.first()
assert plz.id_device_supplier == "a2"
assert plz.id_device_internal == "a2i"
uri = '/inventory/placeholder-logs/'
body, status = user3.get(uri)
assert status == '200 OK'
assert "Placeholder Logs" in body
assert "Web form" in body
assert "ace" in body
assert "Update" in body
assert "Web form" in body
assert "1" in body
assert dev.devicehub_id in body
assert "" in body
assert "CSV" not in body
@ -1979,7 +1958,7 @@ def test_placeholder_log_excel_new(user3: UserClientFlask):
}
user3.post(uri, data=data, content_type="multipart/form-data")
dev = Device.query.first()
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
uri = '/inventory/placeholder-logs/'
body, status = user3.get(uri)
@ -1988,7 +1967,6 @@ def test_placeholder_log_excel_new(user3: UserClientFlask):
assert dev.placeholder.phid in body
assert dev.devicehub_id in body
assert "Web form" not in body
assert "Update" not in body
assert "New device" in body
assert "" in body
assert "CSV" not in body
@ -2022,7 +2000,7 @@ def test_placeholder_log_excel_update(user3: UserClientFlask):
user3.post(uri, data=data, content_type="multipart/form-data")
dev = Device.query.first()
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
uri = '/inventory/placeholder-logs/'
body, status = user3.get(uri)
@ -2031,7 +2009,6 @@ def test_placeholder_log_excel_update(user3: UserClientFlask):
assert dev.placeholder.phid in body
assert dev.devicehub_id in body
assert "Web form" not in body
assert "Update" in body
assert "New device" in body
assert "" in body
assert "CSV" in body
@ -2069,7 +2046,7 @@ def test_add_placeholder_excel_from_lot(user3: UserClientFlask):
assert Device.query.count() == 3
dev = Device.query.first()
assert dev.hid == 'laptop-sony-vaio-12345678'
assert dev.placeholder.phid == 'a123'
assert dev.placeholder.phid == '1'
assert dev.placeholder.info == 'Good conditions'
assert dev.placeholder.pallet == '24A'
assert dev.placeholder.id_device_supplier == 'TTT'
@ -2096,7 +2073,6 @@ def test_add_new_placeholder_from_lot(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Laptop",
'phid': 'ace',
'serial_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
@ -2109,7 +2085,7 @@ def test_add_new_placeholder_from_lot(user3: UserClientFlask):
user3.post(uri, data=data)
dev = Device.query.one()
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
assert dev.placeholder.phid == 'ace'
assert dev.placeholder.phid == '1'
assert len(lot.devices) == 1
@ -2123,7 +2099,6 @@ def test_manual_binding(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Laptop",
'phid': 'sid',
'serial_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
@ -2135,7 +2110,7 @@ def test_manual_binding(user3: UserClientFlask):
user3.post(uri, data=data)
dev = Device.query.one()
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
assert dev.placeholder.phid == 'sid'
assert dev.placeholder.phid == '1'
assert dev.placeholder.is_abstract is False
# add device from wb
@ -2154,7 +2129,7 @@ def test_manual_binding(user3: UserClientFlask):
# page binding
dhid = dev_wb.dhid
uri = f'/inventory/binding/{dhid}/sid/'
uri = f'/inventory/binding/{dhid}/1/'
body, status = user3.get(uri)
assert status == '200 OK'
assert 'sid' in body
@ -2173,7 +2148,7 @@ def test_manual_binding(user3: UserClientFlask):
assert txt in body
# check new structure
assert dev_wb.binding.phid == 'sid'
assert dev_wb.binding.phid == '1'
assert dev_wb.binding.device == dev
assert Placeholder.query.filter_by(id=old_placeholder.id).first() is None
assert Device.query.filter_by(id=old_placeholder.device.id).first() is None
@ -2236,7 +2211,6 @@ def test_unbinding(user3: UserClientFlask):
data = {
'csrf_token': generate_csrf(),
'type': "Laptop",
'phid': 'sid',
'serial_number': "AAAAB",
'model': "LC27T55",
'manufacturer': "Samsung",
@ -2261,7 +2235,7 @@ def test_unbinding(user3: UserClientFlask):
# page binding
dhid = dev_wb.dhid
uri = f'/inventory/binding/{dhid}/sid/'
uri = f'/inventory/binding/{dhid}/1/'
user3.get(uri)
# action binding
@ -2271,10 +2245,10 @@ def test_unbinding(user3: UserClientFlask):
dhid = dev.dhid
# action unbinding
uri = '/inventory/unbinding/sid/'
uri = '/inventory/unbinding/1/'
body, status = user3.post(uri, data={})
assert status == '200 OK'
txt = f'Device with PHID:&#34;sid&#34; and DHID: {dhid} unbind successfully!'
txt = f'Device with PHID:&#34;1&#34; and DHID: {dhid} unbind successfully!'
assert txt in body
# assert 'Device &#34;sid&#34; unbind successfully!' in body
@ -2399,8 +2373,8 @@ def test_bug_3821_binding(user3: UserClientFlask):
user3.post(uri, data=data)
dev = Device.query.one()
dhid = dev.dhid
assert dev.phid() == 'sid'
uri = f'/inventory/binding/{dhid}/sid/'
assert dev.phid() == '1'
uri = f'/inventory/binding/{dhid}/1/'
body, status = user3.get(uri)
assert status == '200 OK'
assert 'is not a Snapshot device!' in body