Merge branch 'testing' into feature/3729-user-registration
This commit is contained in:
commit
c2d81b1b29
|
@ -1,10 +1,8 @@
|
||||||
name: Selenium
|
name: Selenium
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches: [master, testing]
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master, testing]
|
types: [ready_for_review, review_requested]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -19,5 +19,13 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: build-js
|
- id: build-js
|
||||||
name: build-js
|
name: build-js
|
||||||
|
# pre-commit pass as parameters files included on the commit
|
||||||
|
# so babel command should be wrapped to ignore these files on
|
||||||
|
# package.json script
|
||||||
entry: npm run babel
|
entry: npm run babel
|
||||||
language: node
|
language: node
|
||||||
|
files: ^ereuse_devicehub/static/js/main_inventory.js
|
||||||
|
- repo: https://github.com/jazzband/pip-tools
|
||||||
|
rev: 6.8.0
|
||||||
|
hooks:
|
||||||
|
- id: pip-compile
|
||||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -7,6 +7,31 @@ ml).
|
||||||
|
|
||||||
## testing
|
## testing
|
||||||
|
|
||||||
|
## [2.4.2] - 2022-10-18
|
||||||
|
- [added] #373 Enhancement - UX Lots.
|
||||||
|
- [added] #377 add prefix in lots in device list.
|
||||||
|
- [added] #378 add new button transfer.
|
||||||
|
- [added] #381 add servers erase and show storage disk in list of device.
|
||||||
|
- [added] #383 new setup page and add server_erase in placeholder.
|
||||||
|
- [added] #384 add redirect snapshot to twin public page.
|
||||||
|
- [changed] #371 changes phid.
|
||||||
|
- [changed] #372 remove logo.
|
||||||
|
- [changed] #374 changes links UI management and Data Storage Erasure.
|
||||||
|
- [changed] #375 changes columns in snapshot logs.
|
||||||
|
- [changed] #379 changes representation date times.
|
||||||
|
- [fixed] #380 fix layout print label.
|
||||||
|
- [fixed] #382 fix template device list.
|
||||||
|
- [fixed] #385 components in unbinding process.
|
||||||
|
|
||||||
|
## [2.4.1] - 2022-10-05
|
||||||
|
- [added] #365 Manage dependencies using pip-tools.
|
||||||
|
- [added] #368 add migrations of monitors and mobiles.
|
||||||
|
- [changed]] #371 changes about phid, incremental per user.
|
||||||
|
- [fixed] #364 bad redirect to all devices.
|
||||||
|
- [fixed] #367 column PHID Erasure host.
|
||||||
|
- [fixed] #369 bug in test data storage.
|
||||||
|
- [fixed] #370 print label in details of the label.
|
||||||
|
|
||||||
## [2.4.0] - 2022-09-23
|
## [2.4.0] - 2022-09-23
|
||||||
- [added] #312 Placeholder: new, edit, update. (manually and with excel).
|
- [added] #312 Placeholder: new, edit, update. (manually and with excel).
|
||||||
- [added] #316 Placeholder: binding/unbinding. (manually).
|
- [added] #316 Placeholder: binding/unbinding. (manually).
|
||||||
|
|
|
@ -30,3 +30,29 @@ pre-commit install
|
||||||
Do this: `device_detail.html`
|
Do this: `device_detail.html`
|
||||||
|
|
||||||
Don't do this: `DeviceDetail.html`, `Device-detail.html`
|
Don't do this: `DeviceDetail.html`, `Device-detail.html`
|
||||||
|
|
||||||
|
|
||||||
|
## Adding a new dependency to the project
|
||||||
|
This project tracks its packages using pip-tools, it could be installed by running:
|
||||||
|
```
|
||||||
|
pip install pip-tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Whenever you need to install a new package using pip install <package-name>:
|
||||||
|
1. Put the package name into `requirements.in` instead.
|
||||||
|
```
|
||||||
|
# requirements.in
|
||||||
|
...
|
||||||
|
new_package
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Compile the requirements
|
||||||
|
```
|
||||||
|
pip-compile requirements.in --output-file=requirements.txt
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Then install upgraded dependencies:
|
||||||
|
```
|
||||||
|
pip install -U -r requirements.txt
|
||||||
|
```
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "2.4.0"
|
__version__ = "2.4.2"
|
||||||
|
|
|
@ -86,12 +86,18 @@ DEVICES = {
|
||||||
"Smartphone",
|
"Smartphone",
|
||||||
"Cellphone",
|
"Cellphone",
|
||||||
],
|
],
|
||||||
|
"Drives & Storage": [
|
||||||
|
"All DataStorage",
|
||||||
|
"HardDrives",
|
||||||
|
"SolidStageDrive",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer']
|
COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer']
|
||||||
|
|
||||||
MONITORS = ["ComputerMonitor", "Monitor", "TelevisionSet", "Projector"]
|
MONITORS = ["ComputerMonitor", "Monitor", "TelevisionSet", "Projector"]
|
||||||
MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"]
|
MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"]
|
||||||
|
STORAGE = ["HardDrive", "SolidStateDrive"]
|
||||||
|
|
||||||
|
|
||||||
class AdvancedSearchForm(FlaskForm):
|
class AdvancedSearchForm(FlaskForm):
|
||||||
|
@ -175,9 +181,16 @@ class FilterForm(FlaskForm):
|
||||||
elif "All Mobile" == self.device_type:
|
elif "All Mobile" == self.device_type:
|
||||||
filter_type = MOBILE
|
filter_type = MOBILE
|
||||||
|
|
||||||
|
elif "All DataStorage" == self.device_type:
|
||||||
|
filter_type = STORAGE
|
||||||
|
|
||||||
if filter_type:
|
if filter_type:
|
||||||
self.devices = self.devices.filter(Device.type.in_(filter_type))
|
self.devices = self.devices.filter(Device.type.in_(filter_type))
|
||||||
|
|
||||||
|
# if self.device_type in STORAGE + ["All DataStorage"]:
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
|
# self.devices = self.devices.filter(Component.parent_id.is_(None))
|
||||||
|
|
||||||
return self.devices.order_by(Device.updated.desc())
|
return self.devices.order_by(Device.updated.desc())
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,7 +335,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
default=1,
|
default=1,
|
||||||
)
|
)
|
||||||
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
|
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()])
|
pallet = StringField('Identity of pallet', [validators.Optional()])
|
||||||
components = TextAreaField('Components', [validators.Optional()])
|
components = TextAreaField('Components', [validators.Optional()])
|
||||||
info = TextAreaField('Info', [validators.Optional()])
|
info = TextAreaField('Info', [validators.Optional()])
|
||||||
|
@ -382,7 +395,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
self.type.data = self._obj.type
|
self.type.data = self._obj.type
|
||||||
self.amount.render_kw = disabled
|
self.amount.render_kw = disabled
|
||||||
self.id_device_supplier.data = self._obj.placeholder.id_device_supplier
|
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.pallet.data = self._obj.placeholder.pallet
|
||||||
self.info.data = self._obj.placeholder.info
|
self.info.data = self._obj.placeholder.info
|
||||||
self.components.data = self._obj.placeholder.components
|
self.components.data = self._obj.placeholder.components
|
||||||
|
@ -411,7 +424,7 @@ class NewDeviceForm(FlaskForm):
|
||||||
if self._obj.placeholder.is_abstract:
|
if self._obj.placeholder.is_abstract:
|
||||||
self.type.render_kw = disabled
|
self.type.render_kw = disabled
|
||||||
self.amount.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.pallet.render_kw = disabled
|
||||||
self.info.render_kw = disabled
|
self.info.render_kw = disabled
|
||||||
self.components.render_kw = disabled
|
self.components.render_kw = disabled
|
||||||
|
@ -476,28 +489,6 @@ class NewDeviceForm(FlaskForm):
|
||||||
self.meid.errors = error
|
self.meid.errors = error
|
||||||
is_valid = False
|
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:
|
if not is_valid:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -579,8 +570,8 @@ class NewDeviceForm(FlaskForm):
|
||||||
|
|
||||||
def reset_ids(self):
|
def reset_ids(self):
|
||||||
if self.amount.data > 1:
|
if self.amount.data > 1:
|
||||||
self.phid.data = None
|
|
||||||
self.id_device_supplier.data = None
|
self.id_device_supplier.data = None
|
||||||
|
self.id_device_internal.data = None
|
||||||
self.serial_number.data = None
|
self.serial_number.data = None
|
||||||
self.part_number.data = None
|
self.part_number.data = None
|
||||||
self.sku.data = None
|
self.sku.data = None
|
||||||
|
@ -590,8 +581,8 @@ class NewDeviceForm(FlaskForm):
|
||||||
def get_placeholder(self):
|
def get_placeholder(self):
|
||||||
self.placeholder = Placeholder(
|
self.placeholder = Placeholder(
|
||||||
**{
|
**{
|
||||||
'phid': self.phid.data or None,
|
|
||||||
'id_device_supplier': self.id_device_supplier.data,
|
'id_device_supplier': self.id_device_supplier.data,
|
||||||
|
'id_device_internal': self.id_device_internal.data,
|
||||||
'info': self.info.data,
|
'info': self.info.data,
|
||||||
'components': self.components.data,
|
'components': self.components.data,
|
||||||
'pallet': self.pallet.data,
|
'pallet': self.pallet.data,
|
||||||
|
@ -601,11 +592,13 @@ class NewDeviceForm(FlaskForm):
|
||||||
return self.placeholder
|
return self.placeholder
|
||||||
|
|
||||||
def edit_device(self):
|
def edit_device(self):
|
||||||
self._obj.placeholder.phid = self.phid.data or self._obj.placeholder.phid
|
|
||||||
if not self._obj.placeholder.is_abstract:
|
if not self._obj.placeholder.is_abstract:
|
||||||
self._obj.placeholder.id_device_supplier = (
|
self._obj.placeholder.id_device_supplier = (
|
||||||
self.id_device_supplier.data or None
|
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.info = self.info.data or None
|
||||||
self._obj.placeholder.components = self.components.data or None
|
self._obj.placeholder.components = self.components.data or None
|
||||||
self._obj.placeholder.pallet = self.pallet.data or None
|
self._obj.placeholder.pallet = self.pallet.data or None
|
||||||
|
@ -1279,6 +1272,12 @@ class TradeDocumentForm(FlaskForm):
|
||||||
|
|
||||||
|
|
||||||
class TransferForm(FlaskForm):
|
class TransferForm(FlaskForm):
|
||||||
|
lot_name = StringField(
|
||||||
|
'Lot Name',
|
||||||
|
[validators.DataRequired()],
|
||||||
|
render_kw={'class': "form-control"},
|
||||||
|
description="You need put a lot name",
|
||||||
|
)
|
||||||
code = StringField(
|
code = StringField(
|
||||||
'Code',
|
'Code',
|
||||||
[validators.DataRequired()],
|
[validators.DataRequired()],
|
||||||
|
@ -1295,14 +1294,14 @@ class TransferForm(FlaskForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self._type = kwargs.get('type')
|
self._type = kwargs.get('type')
|
||||||
lot_id = kwargs.pop('lot_id', None)
|
lot_id = kwargs.pop('lot_id', None)
|
||||||
self._tmp_lot = Lot.query.filter(Lot.id == lot_id).one()
|
self._tmp_lot = None
|
||||||
|
if lot_id:
|
||||||
|
self._tmp_lot = Lot.query.filter(Lot.id == lot_id).one()
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._obj = None
|
self._obj = None
|
||||||
|
|
||||||
def validate(self, extra_validators=None):
|
def validate(self, extra_validators=None):
|
||||||
is_valid = super().validate(extra_validators)
|
is_valid = super().validate(extra_validators)
|
||||||
if not self._tmp_lot:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if self._type and self.type.data not in ['incoming', 'outgoing']:
|
if self._type and self.type.data not in ['incoming', 'outgoing']:
|
||||||
return False
|
return False
|
||||||
|
@ -1323,8 +1322,10 @@ class TransferForm(FlaskForm):
|
||||||
return self._obj
|
return self._obj
|
||||||
|
|
||||||
def set_obj(self):
|
def set_obj(self):
|
||||||
self.newlot = Lot(name=self._tmp_lot.name)
|
name = self.lot_name.data
|
||||||
self.newlot.devices = self._tmp_lot.devices
|
self.newlot = Lot(name=name)
|
||||||
|
if self._tmp_lot:
|
||||||
|
self.newlot.devices = self._tmp_lot.devices
|
||||||
db.session.add(self.newlot)
|
db.session.add(self.newlot)
|
||||||
|
|
||||||
self._obj = Transfer(lot=self.newlot)
|
self._obj = Transfer(lot=self.newlot)
|
||||||
|
@ -1355,6 +1356,7 @@ class EditTransferForm(TransferForm):
|
||||||
self.code.data = self._obj.code
|
self.code.data = self._obj.code
|
||||||
self.description.data = self._obj.description
|
self.description.data = self._obj.description
|
||||||
self.date.data = self._obj.date
|
self.date.data = self._obj.date
|
||||||
|
self.lot_name.data = self._obj.lot.name
|
||||||
|
|
||||||
def validate(self, extra_validators=None):
|
def validate(self, extra_validators=None):
|
||||||
is_valid = super().validate(extra_validators)
|
is_valid = super().validate(extra_validators)
|
||||||
|
@ -1366,6 +1368,7 @@ class EditTransferForm(TransferForm):
|
||||||
|
|
||||||
def set_obj(self, commit=True):
|
def set_obj(self, commit=True):
|
||||||
self.populate_obj(self._obj)
|
self.populate_obj(self._obj)
|
||||||
|
self._obj.lot.name = self.lot_name.data
|
||||||
|
|
||||||
|
|
||||||
class NotesForm(FlaskForm):
|
class NotesForm(FlaskForm):
|
||||||
|
@ -1514,9 +1517,7 @@ class UploadPlaceholderForm(FlaskForm):
|
||||||
else:
|
else:
|
||||||
self.source = "Excel File: {}".format(_file.filename)
|
self.source = "Excel File: {}".format(_file.filename)
|
||||||
try:
|
try:
|
||||||
data = (
|
data = pd.read_excel(_file).fillna('').to_dict()
|
||||||
pd.read_excel(_file, converters={'Phid': str}).fillna('').to_dict()
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
txt = ["File don't have a correct format"]
|
txt = ["File don't have a correct format"]
|
||||||
self.placeholder_file.errors = txt
|
self.placeholder_file.errors = txt
|
||||||
|
@ -1538,12 +1539,12 @@ class UploadPlaceholderForm(FlaskForm):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
header = [
|
header = [
|
||||||
'Phid',
|
|
||||||
'Model',
|
'Model',
|
||||||
'Manufacturer',
|
'Manufacturer',
|
||||||
'Serial Number',
|
'Serial Number',
|
||||||
'Part Number',
|
'Part Number',
|
||||||
'Id device Supplier',
|
'Id device Supplier',
|
||||||
|
'Id device Internal',
|
||||||
'Pallet',
|
'Pallet',
|
||||||
'Info',
|
'Info',
|
||||||
]
|
]
|
||||||
|
@ -1557,32 +1558,7 @@ class UploadPlaceholderForm(FlaskForm):
|
||||||
self.placeholders = []
|
self.placeholders = []
|
||||||
schema = SnapshotSchema()
|
schema = SnapshotSchema()
|
||||||
self.path_snapshots = {}
|
self.path_snapshots = {}
|
||||||
for i in data['Phid'].keys():
|
for i in data['Model'].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
|
|
||||||
|
|
||||||
# create a new one
|
# create a new one
|
||||||
json_snapshot = {
|
json_snapshot = {
|
||||||
'type': 'Snapshot',
|
'type': 'Snapshot',
|
||||||
|
@ -1597,8 +1573,8 @@ class UploadPlaceholderForm(FlaskForm):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
json_placeholder = {
|
json_placeholder = {
|
||||||
'phid': data['Phid'][i] or None,
|
|
||||||
'id_device_supplier': data['Id device Supplier'][i],
|
'id_device_supplier': data['Id device Supplier'][i],
|
||||||
|
'id_device_internal': data['Id device Internal'][i],
|
||||||
'pallet': data['Pallet'][i],
|
'pallet': data['Pallet'][i],
|
||||||
'info': data['Info'][i],
|
'info': data['Info'][i],
|
||||||
'is_abstract': False,
|
'is_abstract': False,
|
||||||
|
@ -1635,7 +1611,6 @@ class EditPlaceholderForm(FlaskForm):
|
||||||
serial_number = StringField('Serial Number', [validators.Optional()])
|
serial_number = StringField('Serial Number', [validators.Optional()])
|
||||||
part_number = StringField('Part Number', [validators.Optional()])
|
part_number = StringField('Part Number', [validators.Optional()])
|
||||||
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
|
id_device_supplier = StringField('Id Supplier', [validators.Optional()])
|
||||||
phid = StringField('Phid', [validators.DataRequired()])
|
|
||||||
pallet = StringField('Pallet', [validators.Optional()])
|
pallet = StringField('Pallet', [validators.Optional()])
|
||||||
info = StringField('Info', [validators.Optional()])
|
info = StringField('Info', [validators.Optional()])
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,8 @@ class BindingView(GenericMixin):
|
||||||
self.real_phid = self.new_placeholder.phid
|
self.real_phid = self.new_placeholder.phid
|
||||||
self.abstract_dhid = self.old_device.devicehub_id
|
self.abstract_dhid = self.old_device.devicehub_id
|
||||||
self.abstract_phid = self.old_placeholder.phid
|
self.abstract_phid = self.old_placeholder.phid
|
||||||
|
if self.old_placeholder.kangaroo:
|
||||||
|
self.new_placeholder.kangaroo = True
|
||||||
|
|
||||||
# to do a backup of abstract_dhid and abstract_phid in
|
# to do a backup of abstract_dhid and abstract_phid in
|
||||||
# workbench device
|
# workbench device
|
||||||
|
@ -380,9 +382,14 @@ class UnBindingView(GenericMixin):
|
||||||
return flask.render_template(self.template_name, **self.context)
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
def clone_device(self, device):
|
def clone_device(self, device):
|
||||||
if device.binding.is_abstract:
|
if device.binding and device.binding.is_abstract:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
kangaroo = False
|
||||||
|
if device.binding:
|
||||||
|
kangaroo = device.binding.kangaroo
|
||||||
|
device.binding.kangaroo = False
|
||||||
|
|
||||||
dict_device = copy.copy(device.__dict__)
|
dict_device = copy.copy(device.__dict__)
|
||||||
dict_device.pop('_sa_instance_state')
|
dict_device.pop('_sa_instance_state')
|
||||||
dict_device.pop('id', None)
|
dict_device.pop('id', None)
|
||||||
|
@ -401,8 +408,14 @@ class UnBindingView(GenericMixin):
|
||||||
for c in device.components:
|
for c in device.components:
|
||||||
if c.binding:
|
if c.binding:
|
||||||
c.binding.device.parent = new_device
|
c.binding.device.parent = new_device
|
||||||
|
else:
|
||||||
|
new_c = self.clone_device(c)
|
||||||
|
new_c.parent = new_device
|
||||||
|
|
||||||
|
placeholder = Placeholder(
|
||||||
|
device=new_device, binding=device, is_abstract=True, kangaroo=kangaroo
|
||||||
|
)
|
||||||
|
|
||||||
placeholder = Placeholder(device=new_device, binding=device, is_abstract=True)
|
|
||||||
if (
|
if (
|
||||||
device.dhid_bk
|
device.dhid_bk
|
||||||
and not Device.query.filter_by(devicehub_id=device.dhid_bk).first()
|
and not Device.query.filter_by(devicehub_id=device.dhid_bk).first()
|
||||||
|
@ -545,7 +558,7 @@ class DeviceCreateView(GenericMixin):
|
||||||
tpy = form.type.data
|
tpy = form.type.data
|
||||||
txt = f'{amount} placeholders Device "{tpy}" created successfully.'
|
txt = f'{amount} placeholders Device "{tpy}" created successfully.'
|
||||||
placeholder = (
|
placeholder = (
|
||||||
Placeholder.query.filter_by(owner=g.user)
|
Placeholder.query.filter(Placeholder.owner == g.user)
|
||||||
.order_by(Placeholder.id.desc())
|
.order_by(Placeholder.id.desc())
|
||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
|
@ -753,9 +766,11 @@ class NewTransferView(GenericMixin):
|
||||||
form_class = TransferForm
|
form_class = TransferForm
|
||||||
title = "Add new transfer"
|
title = "Add new transfer"
|
||||||
|
|
||||||
def dispatch_request(self, lot_id, type_id):
|
def dispatch_request(self, type_id, lot_id=None):
|
||||||
self.form = self.form_class(lot_id=lot_id, type=type_id)
|
self.form = self.form_class(lot_id=lot_id, type=type_id)
|
||||||
self.get_context()
|
self.get_context()
|
||||||
|
referrer = request.referrer or url_for('inventory.devicelist')
|
||||||
|
self.context.update({'referrer': referrer})
|
||||||
|
|
||||||
if self.form.validate_on_submit():
|
if self.form.validate_on_submit():
|
||||||
self.form.save()
|
self.form.save()
|
||||||
|
@ -767,7 +782,12 @@ class NewTransferView(GenericMixin):
|
||||||
next_url = url_for('inventory.lotdevicelist', lot_id=str(new_lot_id))
|
next_url = url_for('inventory.lotdevicelist', lot_id=str(new_lot_id))
|
||||||
return flask.redirect(next_url)
|
return flask.redirect(next_url)
|
||||||
|
|
||||||
self.context.update({'form': self.form, 'title': self.title})
|
self.context.update(
|
||||||
|
{
|
||||||
|
'form': self.form,
|
||||||
|
'title': self.title,
|
||||||
|
}
|
||||||
|
)
|
||||||
return flask.render_template(self.template_name, **self.context)
|
return flask.render_template(self.template_name, **self.context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1355,6 +1375,10 @@ devices.add_url_rule(
|
||||||
)
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
'/lot/<string:lot_id>/transfer/<string:type_id>/',
|
'/lot/<string:lot_id>/transfer/<string:type_id>/',
|
||||||
|
view_func=NewTransferView.as_view('lot_new_transfer'),
|
||||||
|
)
|
||||||
|
devices.add_url_rule(
|
||||||
|
'/lot/transfer/<string:type_id>/',
|
||||||
view_func=NewTransferView.as_view('new_transfer'),
|
view_func=NewTransferView.as_view('new_transfer'),
|
||||||
)
|
)
|
||||||
devices.add_url_rule(
|
devices.add_url_rule(
|
||||||
|
|
|
@ -114,21 +114,35 @@ class PrintLabelsView(View):
|
||||||
|
|
||||||
|
|
||||||
class LabelDetailView(View):
|
class LabelDetailView(View):
|
||||||
|
"""This View is used to print labels from multiple devices"""
|
||||||
|
|
||||||
|
methods = ['POST', 'GET']
|
||||||
decorators = [login_required]
|
decorators = [login_required]
|
||||||
template_name = 'labels/label_detail.html'
|
template_name = 'labels/print_labels.html'
|
||||||
|
title = 'Design and implementation of labels'
|
||||||
|
|
||||||
def dispatch_request(self, id):
|
def dispatch_request(self, id):
|
||||||
lots = Lot.query.filter(Lot.owner_id == current_user.id)
|
lots = Lot.query.filter(Lot.owner_id == current_user.id)
|
||||||
tag = (
|
tag = (
|
||||||
Tag.query.filter(Tag.owner_id == current_user.id).filter(Tag.id == id).one()
|
Tag.query.filter(Tag.owner_id == current_user.id).filter(Tag.id == id).one()
|
||||||
)
|
)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'lots': lots,
|
'lots': lots,
|
||||||
'tag': tag,
|
'page_title': self.title,
|
||||||
'page_title': '{} Tag'.format(tag.code),
|
|
||||||
'version': __version__,
|
'version': __version__,
|
||||||
|
'referrer': request.referrer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devices = []
|
||||||
|
if tag.device:
|
||||||
|
form = PrintLabelsForm(devices=str(tag.device.id))
|
||||||
|
devices = [tag.device]
|
||||||
|
else:
|
||||||
|
form = PrintLabelsForm()
|
||||||
|
|
||||||
|
form._devices = devices
|
||||||
|
context['form'] = form
|
||||||
|
context['devices'] = devices
|
||||||
return flask.render_template(self.template_name, **context)
|
return flask.render_template(self.template_name, **context)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()}')
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""add kangaroo in placeholder
|
||||||
|
|
||||||
|
Revision ID: a13ed6ad0e3e
|
||||||
|
Revises: 626c17026ca7
|
||||||
|
Create Date: 2022-10-13 11:56:15.303218
|
||||||
|
|
||||||
|
"""
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from alembic import context, op
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a13ed6ad0e3e'
|
||||||
|
down_revision = '626c17026ca7'
|
||||||
|
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.add_column(
|
||||||
|
'placeholder',
|
||||||
|
sa.Column('kangaroo', sa.Boolean(), nullable=True),
|
||||||
|
schema=f'{get_inv()}',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('placeholder', 'kangaroo', schema=f'{get_inv()}')
|
|
@ -0,0 +1,34 @@
|
||||||
|
"""add is_server_erase
|
||||||
|
|
||||||
|
Revision ID: d65745749e34
|
||||||
|
Revises: a13ed6ad0e3e
|
||||||
|
Create Date: 2022-10-17 13:20:29.875274
|
||||||
|
|
||||||
|
"""
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from alembic import context, op
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd65745749e34'
|
||||||
|
down_revision = 'a13ed6ad0e3e'
|
||||||
|
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.add_column(
|
||||||
|
'snapshot',
|
||||||
|
sa.Column('is_server_erase', sa.Boolean(), nullable=True),
|
||||||
|
schema=f'{get_inv()}',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('snapshot', 'is_server_erase', schema=f'{get_inv()}')
|
|
@ -676,6 +676,7 @@ class Snapshot(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
||||||
of time it took to complete.
|
of time it took to complete.
|
||||||
"""
|
"""
|
||||||
sid = Column(CIText(), nullable=True)
|
sid = Column(CIText(), nullable=True)
|
||||||
|
is_server_erase = Column(Boolean(), nullable=True)
|
||||||
|
|
||||||
def get_last_lifetimes(self):
|
def get_last_lifetimes(self):
|
||||||
"""We get the lifetime and serial_number of the first disk"""
|
"""We get the lifetime and serial_number of the first disk"""
|
||||||
|
|
|
@ -296,6 +296,14 @@ class TestDataStorage(Test):
|
||||||
offline_uncorrectable = Integer(data_key='offlineUncorrectable')
|
offline_uncorrectable = Integer(data_key='offlineUncorrectable')
|
||||||
remaining_lifetime_percentage = Integer(data_key='remainingLifetimePercentage')
|
remaining_lifetime_percentage = Integer(data_key='remainingLifetimePercentage')
|
||||||
|
|
||||||
|
@post_load
|
||||||
|
def default_remaining_lifetime_percentage(self, data):
|
||||||
|
if not data.get('remaining_lifetime_percentage'):
|
||||||
|
return
|
||||||
|
|
||||||
|
if data.get('remaining_lifetime_percentage') > 100:
|
||||||
|
data['remaining_lifetime_percentage'] = None
|
||||||
|
|
||||||
|
|
||||||
class StressTest(Test):
|
class StressTest(Test):
|
||||||
__doc__ = m.StressTest.__doc__
|
__doc__ = m.StressTest.__doc__
|
||||||
|
|
|
@ -115,8 +115,15 @@ class SnapshotMixin:
|
||||||
if snapshot.device.hid is None:
|
if snapshot.device.hid is None:
|
||||||
snapshot.severity = Severity.Warning
|
snapshot.severity = Severity.Warning
|
||||||
|
|
||||||
|
self.is_server_erase(snapshot)
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
||||||
|
def is_server_erase(self, snapshot):
|
||||||
|
if snapshot.device.binding:
|
||||||
|
if snapshot.device.binding.kangaroo:
|
||||||
|
snapshot.is_server_erase = True
|
||||||
|
|
||||||
def get_old_smbios_version(self, debug):
|
def get_old_smbios_version(self, debug):
|
||||||
capabilities = debug.get('lshw', {}).get('capabilities', {})
|
capabilities = debug.get('lshw', {}).get('capabilities', {})
|
||||||
for x in capabilities.values():
|
for x in capabilities.values():
|
||||||
|
|
|
@ -10,7 +10,6 @@ from boltons import urlutils
|
||||||
from citext import CIText
|
from citext import CIText
|
||||||
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
|
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
|
||||||
from flask import g, request
|
from flask import g, request
|
||||||
from flask_sqlalchemy import event
|
|
||||||
from more_itertools import unique_everseen
|
from more_itertools import unique_everseen
|
||||||
from sqlalchemy import BigInteger, Boolean, Column
|
from sqlalchemy import BigInteger, Boolean, Column
|
||||||
from sqlalchemy import Enum as DBEnum
|
from sqlalchemy import Enum as DBEnum
|
||||||
|
@ -75,11 +74,15 @@ def create_code(context):
|
||||||
return hashcode.encode(_id)
|
return hashcode.encode(_id)
|
||||||
|
|
||||||
|
|
||||||
def create_phid(context):
|
def create_phid(context, count=1):
|
||||||
_hid = Placeholder.query.order_by(Placeholder.id.desc()).first()
|
phid = str(Placeholder.query.filter(Placeholder.owner == g.user).count() + count)
|
||||||
if _hid:
|
if (
|
||||||
return str(_hid.id + 1)
|
Placeholder.query.filter(Placeholder.owner == g.user)
|
||||||
return '1'
|
.filter(Placeholder.phid == phid)
|
||||||
|
.count()
|
||||||
|
):
|
||||||
|
return create_phid(context, count=count + 1)
|
||||||
|
return phid
|
||||||
|
|
||||||
|
|
||||||
class Device(Thing):
|
class Device(Thing):
|
||||||
|
@ -650,6 +653,21 @@ class Device(Thing):
|
||||||
args[POLYMORPHIC_ON] = cls.type
|
args[POLYMORPHIC_ON] = cls.type
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
def get_lots_for_template(self):
|
||||||
|
lots = []
|
||||||
|
for lot in self.lots:
|
||||||
|
if lot.is_incoming:
|
||||||
|
name = "IN - " + lot.name
|
||||||
|
lots.append(name)
|
||||||
|
if lot.is_outgoing:
|
||||||
|
name = "OUT - " + lot.name
|
||||||
|
lots.append(name)
|
||||||
|
if lot.is_temporary:
|
||||||
|
name = "TEMP - " + lot.name
|
||||||
|
lots.append(name)
|
||||||
|
lots.sort()
|
||||||
|
return lots
|
||||||
|
|
||||||
def phid(self):
|
def phid(self):
|
||||||
if self.placeholder:
|
if self.placeholder:
|
||||||
return self.placeholder.phid
|
return self.placeholder.phid
|
||||||
|
@ -901,8 +919,8 @@ class DisplayMixin:
|
||||||
|
|
||||||
class Placeholder(Thing):
|
class Placeholder(Thing):
|
||||||
id = Column(BigInteger, Sequence('placeholder_seq'), primary_key=True)
|
id = Column(BigInteger, Sequence('placeholder_seq'), primary_key=True)
|
||||||
pallet = Column(Unicode(), nullable=True)
|
|
||||||
phid = Column(Unicode(), nullable=False, default=create_phid)
|
phid = Column(Unicode(), nullable=False, default=create_phid)
|
||||||
|
pallet = Column(Unicode(), nullable=True)
|
||||||
pallet.comment = "used for identification where from where is this placeholders"
|
pallet.comment = "used for identification where from where is this placeholders"
|
||||||
info = db.Column(CIText())
|
info = db.Column(CIText())
|
||||||
components = Column(CIText())
|
components = Column(CIText())
|
||||||
|
@ -912,6 +930,9 @@ class Placeholder(Thing):
|
||||||
id_device_supplier.comment = (
|
id_device_supplier.comment = (
|
||||||
"Identification used for one supplier of one placeholders"
|
"Identification used for one supplier of one placeholders"
|
||||||
)
|
)
|
||||||
|
id_device_internal = db.Column(CIText())
|
||||||
|
id_device_internal.comment = "Identification used internaly for the user"
|
||||||
|
kangaroo = db.Column(Boolean, default=False, nullable=True)
|
||||||
|
|
||||||
device_id = db.Column(
|
device_id = db.Column(
|
||||||
BigInteger,
|
BigInteger,
|
||||||
|
@ -1593,4 +1614,5 @@ def create_code_tag(mapper, connection, device):
|
||||||
db.session.add(tag)
|
db.session.add(tag)
|
||||||
|
|
||||||
|
|
||||||
|
# from flask_sqlalchemy import event
|
||||||
# event.listen(Device, 'after_insert', create_code_tag, propagate=True)
|
# event.listen(Device, 'after_insert', create_code_tag, propagate=True)
|
||||||
|
|
|
@ -137,7 +137,10 @@ class DeviceView(View):
|
||||||
return self.one_private(id)
|
return self.one_private(id)
|
||||||
|
|
||||||
def one_public(self, id: int):
|
def one_public(self, id: int):
|
||||||
device = Device.query.filter_by(devicehub_id=id, active=True).one()
|
devices = Device.query.filter_by(devicehub_id=id, active=True).all()
|
||||||
|
if not devices:
|
||||||
|
devices = [Device.query.filter_by(dhid_bk=id, active=True).one()]
|
||||||
|
device = devices[0]
|
||||||
abstract = None
|
abstract = None
|
||||||
if device.binding:
|
if device.binding:
|
||||||
return flask.redirect(device.public_link)
|
return flask.redirect(device.public_link)
|
||||||
|
|
|
@ -26,3 +26,10 @@
|
||||||
.help {
|
.help {
|
||||||
color: #993365;
|
color: #993365;
|
||||||
}
|
}
|
||||||
|
.doTransfer {
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-right: 15px;"
|
||||||
|
}
|
||||||
|
.printLabelForm {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
|
@ -29,14 +29,18 @@ function amountInputs() {
|
||||||
if ($("#amount").val() > 1) {
|
if ($("#amount").val() > 1) {
|
||||||
$("#Phid").hide();
|
$("#Phid").hide();
|
||||||
$("#Id_device_supplier").hide();
|
$("#Id_device_supplier").hide();
|
||||||
|
$("#Id_device_internal").hide();
|
||||||
$("#Serial_number").hide();
|
$("#Serial_number").hide();
|
||||||
|
$("#Part_number").hide();
|
||||||
$("#Sku").hide();
|
$("#Sku").hide();
|
||||||
$("#imei").hide();
|
$("#imei").hide();
|
||||||
$("#meid").hide();
|
$("#meid").hide();
|
||||||
} else {
|
} else {
|
||||||
$("#Phid").show();
|
$("#Phid").show();
|
||||||
$("#Id_device_supplier").show();
|
$("#Id_device_supplier").show();
|
||||||
|
$("#Id_device_internal").show();
|
||||||
$("#Serial_number").show();
|
$("#Serial_number").show();
|
||||||
|
$("#Part_number").show();
|
||||||
$("#Sku").show();
|
$("#Sku").show();
|
||||||
deviceInputs();
|
deviceInputs();
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,11 +3,7 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<!-- ======= Header ======= -->
|
<!-- ======= Header ======= -->
|
||||||
<header id="header" class="header fixed-top d-flex align-items-center">
|
<header id="header" class="header fixed-top d-flex align-items-center">
|
||||||
|
|
||||||
<div class="d-flex align-items-center justify-content-between">
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
<a href="{{ url_for('inventory.devicelist')}}" class="logo d-flex align-items-center">
|
|
||||||
<img src="{{ url_for('static', filename='img/logo_usody_clock.png') }}" alt="">
|
|
||||||
</a>
|
|
||||||
<i class="bi bi-list toggle-sidebar-btn"></i>
|
<i class="bi bi-list toggle-sidebar-btn"></i>
|
||||||
</div><!-- End Logo -->
|
</div><!-- End Logo -->
|
||||||
|
|
||||||
|
@ -43,6 +39,11 @@
|
||||||
<i class="bi bi-search"></i>
|
<i class="bi bi-search"></i>
|
||||||
</a>
|
</a>
|
||||||
</li><!-- End Search Icon-->
|
</li><!-- End Search Icon-->
|
||||||
|
<li class="nav-item dropdown pe-3">
|
||||||
|
<a class="nav-link nav-profile d-flex align-items-center pe-0" href="{{ url_for('labels.label_list') }}">
|
||||||
|
<span class="d-none d-md-block ps-2 pb-3 pt-3">Identifiers</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item dropdown pe-3">
|
<li class="nav-item dropdown pe-3">
|
||||||
|
|
||||||
|
@ -64,6 +65,11 @@
|
||||||
<span>Lots Spreadsheet</span>
|
<span>Lots Spreadsheet</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item d-flex align-items-center" href="{{ url_for('inventory.device_erasure_list') }}">
|
||||||
|
<i class="bi bi-tag"></i><span>Data Storage Erasures</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
@ -188,6 +194,11 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul id="incoming-lots-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
|
<ul id="incoming-lots-nav" class="nav-content collapse" data-bs-parent="#sidebar-nav">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('inventory.new_transfer', type_id='incoming') }}">
|
||||||
|
<i class="bi bi-plus" style="font-size: larger;"></i><span>New Incoming lot</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{% for lot in lots %}
|
{% for lot in lots %}
|
||||||
{% if lot.is_incoming %}
|
{% if lot.is_incoming %}
|
||||||
<li>
|
<li>
|
||||||
|
@ -213,6 +224,11 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul id="outgoing-lots-nav" class="nav-content collapse " data-bs-parent="#sidebar-nav">
|
<ul id="outgoing-lots-nav" class="nav-content collapse " data-bs-parent="#sidebar-nav">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('inventory.new_transfer', type_id='outgoing') }}">
|
||||||
|
<i class="bi bi-plus" style="font-size: larger;"></i><span>New Outgoing lot</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{% for lot in lots %}
|
{% for lot in lots %}
|
||||||
{% if lot.is_outgoing %}
|
{% if lot.is_outgoing %}
|
||||||
<li>
|
<li>
|
||||||
|
@ -256,22 +272,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li><!-- End Temporal Lots Nav -->
|
</li><!-- End Temporal Lots Nav -->
|
||||||
|
|
||||||
<li class="nav-heading">Others views</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="{{ url_for('inventory.device_erasure_list') }}">
|
|
||||||
<i class="bi bi-tag"></i><span>Data Storage Erasures</span>
|
|
||||||
</a>
|
|
||||||
</li><!-- End Other views -->
|
|
||||||
|
|
||||||
<li class="nav-heading">Unique Identifiers (Tags)</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="{{ url_for('labels.label_list') }}">
|
|
||||||
<i class="bi bi-tag"></i><span>UI Management</span>
|
|
||||||
</a>
|
|
||||||
</li><!-- End Unique Identifiers -->
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</aside><!-- End Sidebar-->
|
</aside><!-- End Sidebar-->
|
||||||
|
|
|
@ -90,19 +90,6 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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">
|
<div class="form-group mb-2" id="Id_device_supplier">
|
||||||
<label for="label" class="form-label">{{ form.id_device_supplier.label }}</label>
|
<label for="label" class="form-label">{{ form.id_device_supplier.label }}</label>
|
||||||
{{ form.id_device_supplier(class_="form-control") }}
|
{{ form.id_device_supplier(class_="form-control") }}
|
||||||
|
@ -116,6 +103,19 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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">
|
<div class="form-group mb-2">
|
||||||
<label for="label" class="form-label">{{ form.pallet.label }}</label>
|
<label for="label" class="form-label">{{ form.pallet.label }}</label>
|
||||||
{{ form.pallet(class_="form-control") }}
|
{{ form.pallet(class_="form-control") }}
|
||||||
|
|
|
@ -98,6 +98,11 @@
|
||||||
<div class="col-lg-9 col-md-8">{{ placeholder.phid }}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.phid }}</div>
|
||||||
</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="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||||
<div class="col-lg-9 col-md-8">{{ placeholder.device.type }}</div>
|
<div class="col-lg-9 col-md-8">{{ placeholder.device.type }}</div>
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
|
|
||||||
<div class="col-xl-12">
|
<div class="col-xl-12">
|
||||||
|
|
||||||
{% if lot %}
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
{% if lot %}
|
||||||
<div class="card-body pt-3">
|
<div class="card-body pt-3">
|
||||||
<!-- Bordered Tabs -->
|
<!-- Bordered Tabs -->
|
||||||
|
|
||||||
|
@ -41,25 +41,19 @@
|
||||||
<h3>
|
<h3>
|
||||||
<a href="{{ url_for('inventory.lot_edit', id=lot.id) }}">{{ lot.name }}</a>
|
<a href="{{ url_for('inventory.lot_edit', id=lot.id) }}">{{ lot.name }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
{% if lot.transfer.code and lot.transfer.user_to and not lot.transfer.user_to.phantom %}
|
|
||||||
<span>{{ lot.transfer.code }} <i class="bi bi-arrow-right"></i> {{ lot.transfer.user_to.email }}</span>
|
|
||||||
{% elif lot.transfer.code and lot.transfer.user_from and not lot.transfer.user_from.phantom %}
|
|
||||||
<span>{{ lot.transfer.user_from.email }} <i class="bi bi-arrow-right"></i> {{ lot.transfer.code }}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-md-7 d-md-flex justify-content-md-end"><!-- lot actions -->
|
<div class="col-sm-12 col-md-7 d-md-flex justify-content-md-end"><!-- lot actions -->
|
||||||
{% if lot.is_temporary or not lot.transfer.closed %}
|
{% if lot.is_temporary or not lot.transfer.closed %}
|
||||||
|
|
||||||
{% if 1 == 2 %}{# <!-- TODO (@slamora) Don't render Trade buttons until implementation is finished --> #}
|
{% if lot and lot.is_temporary %}
|
||||||
<a class="me-2" href="javascript:newTrade('user_from')">
|
<a type="button" href="{{ url_for('inventory.lot_new_transfer', lot_id=lot.id, type_id='outgoing') }}" class="btn btn-primary doTransfer" >
|
||||||
<i class="bi bi-arrow-down-right"></i> Add supplier
|
Create Outgoing Lot
|
||||||
</a>
|
</a>
|
||||||
<a class="me-2" href="javascript:newTrade('user_to')">
|
<a type="button" href="{{ url_for('inventory.lot_new_transfer', lot_id=lot.id, type_id='incoming') }}" class="btn btn-primary doTransfer">
|
||||||
<i class="bi bi-arrow-up-right"></i> Add receiver
|
Create Incoming Lot
|
||||||
</a>
|
</a>
|
||||||
{% endif %}{# <!-- /end TODO --> #}
|
{% endif %}
|
||||||
|
|
||||||
<a class="text-danger" href="javascript:removeLot()">
|
<a class="text-danger" href="javascript:removeLot()">
|
||||||
<i class="bi bi-trash"></i> Delete Lot
|
<i class="bi bi-trash"></i> Delete Lot
|
||||||
</a>
|
</a>
|
||||||
|
@ -68,18 +62,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card">
|
|
||||||
<div class="card-body pt-3" style="min-height: 650px;">
|
<div class="card-body pt-3" style="min-height: 650px;">
|
||||||
<!-- Bordered Tabs -->
|
<!-- Bordered Tabs -->
|
||||||
{% if lot and not lot.is_temporary %}
|
{% if lot %}
|
||||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#devices-list">Devices</button>
|
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#devices-list">Devices</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{% if lot and not lot.is_temporary %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#trade-documents-list">Documents</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#trade-documents-list">Documents</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -101,21 +94,11 @@
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="tab-content pt-1">
|
<div class="tab-content pt-1">
|
||||||
{% if lot and lot.is_temporary %}
|
|
||||||
<div class="tab-pane active show mb-5">
|
|
||||||
<a type="button" href="{{ url_for('inventory.new_transfer', lot_id=lot.id, type_id='outgoing') }}" class="btn btn-primary" style="float: right;">
|
|
||||||
Outgoing Transfer
|
|
||||||
</a>
|
|
||||||
<a type="button" href="{{ url_for('inventory.new_transfer', lot_id=lot.id, type_id='incoming') }}" class="btn btn-primary" style="float: right; margin-right: 15px;">
|
|
||||||
Incoming Transfer
|
|
||||||
</a>
|
|
||||||
<div style="display: block;"></div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div id="devices-list" class="tab-pane fade devices-list active show">
|
<div id="devices-list" class="tab-pane fade devices-list active show">
|
||||||
<label class="btn btn-primary " for="SelectAllBTN"><input type="checkbox" id="SelectAllBTN" autocomplete="off"></label>
|
<label class="btn btn-primary " for="SelectAllBTN"><input type="checkbox" id="SelectAllBTN" autocomplete="off"></label>
|
||||||
<div class="btn-group dropdown ml-1">
|
<div class="btn-group dropdown ml-1">
|
||||||
|
@ -336,24 +319,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if lot and not lot.is_temporary %}
|
|
||||||
<div class="btn-group dropdown ml-1" uib-dropdown="">
|
|
||||||
<button id="btnSnapshot" type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
|
||||||
<i class="bi bi-book"></i>
|
|
||||||
Documents
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu" aria-labelledby="btnSnapshot">
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('inventory.trade_document_add', lot_id=lot.id)}}" class="dropdown-item">
|
|
||||||
<i class="bi bi-plus"></i>
|
|
||||||
Add new document
|
|
||||||
<span class="caret"></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div id="select-devices-info" class="alert alert-info mb-0 mt-3 d-none" role="alert">
|
<div id="select-devices-info" class="alert alert-info mb-0 mt-3 d-none" role="alert">
|
||||||
If this text is showing is because there are an error
|
If this text is showing is because there are an error
|
||||||
</div>
|
</div>
|
||||||
|
@ -392,6 +357,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for dev in devices %}
|
{% for dev in devices %}
|
||||||
|
{% if dev.placeholder and (not dev.parent_id or dev.parent.placeholder.kangaroo) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" class="deviceSelect" data="{{ dev.id }}"
|
<input type="checkbox" class="deviceSelect" data="{{ dev.id }}"
|
||||||
|
@ -411,8 +377,8 @@
|
||||||
</a>
|
</a>
|
||||||
{% if dev.lots | length > 0 %}
|
{% if dev.lots | length > 0 %}
|
||||||
<h6 class="d-inline">
|
<h6 class="d-inline">
|
||||||
{% for lot in dev.lots %}
|
{% for lot in dev.get_lots_for_template() %}
|
||||||
<span class="badge rounded-pill bg-light text-dark">{{ lot.name }}</span>
|
<span class="badge rounded-pill bg-light text-dark">{{ lot }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</h6>
|
</h6>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -445,6 +411,7 @@
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -453,12 +420,20 @@
|
||||||
</div>
|
</div>
|
||||||
{% if lot and not lot.is_temporary %}
|
{% if lot and not lot.is_temporary %}
|
||||||
<div id="trade-documents-list" class="tab-pane fade trade-documents-list">
|
<div id="trade-documents-list" class="tab-pane fade trade-documents-list">
|
||||||
|
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||||
|
<a href="{{ url_for('inventory.trade_document_add', lot_id=lot.id)}}" class="btn btn-primary">
|
||||||
|
<i class="bi bi-plus"></i>
|
||||||
|
Add new document
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h5 class="card-title">Documents</h5>
|
<h5 class="card-title">Documents</h5>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">File</th>
|
<th scope="col">File</th>
|
||||||
<th scope="col" data-type="date" data-format="DD-MM-YYYY">Uploaded on</th>
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Uploaded on</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -472,7 +447,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ doc.created.strftime('%H:%M %d-%m-%Y')}}
|
{{ doc.created.strftime('%Y-%m-%d %H:%M')}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -486,7 +461,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ doc.created.strftime('%H:%M %d-%m-%Y')}}
|
{{ doc.created.strftime('%Y-%m-%d %H:%M')}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{% if field != form.type %}
|
{% if field != form.type %}
|
||||||
{{ field.label(class_="form-label") }}
|
{{ field.label(class_="form-label") }}
|
||||||
{% if field == form.code %}
|
{% if field in [form.code, form.lot_name] %}
|
||||||
<span class="text-danger">*</span>
|
<span class="text-danger">*</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ field }}
|
{{ field }}
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ url_for('inventory.lotdevicelist', lot_id=form._tmp_lot.id) }}" class="btn btn-danger">Cancel</a>
|
<a href="{{ referrer }}" class="btn btn-danger">Cancel</a>
|
||||||
<button class="btn btn-primary" type="submit">Save</button>
|
<button class="btn btn-primary" type="submit">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">PHID</th>
|
<th scope="col">PHID</th>
|
||||||
<th scope="col">Placeholder source</th>
|
<th scope="col">Placeholder source</th>
|
||||||
<th scope="col">Type</th>
|
<th scope="col">Type Upload</th>
|
||||||
<th scope="col">DHID</th>
|
<th scope="col">DHID</th>
|
||||||
<th scope="col">Status</th>
|
<th scope="col">Status</th>
|
||||||
<th scope="col" data-type="date" data-format="DD-MM-YYYY">Time</th>
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Time</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<td>
|
<td>
|
||||||
{{ log.get_status() }}
|
{{ log.get_status() }}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ log.created.strftime('%H:%M %d-%m-%Y') }}</td>
|
<td>{{ log.created.strftime('%Y-%m-%d %H:%M') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">SID</th>
|
<th scope="col">SID</th>
|
||||||
<th scope="col">Snapshot id</th>
|
<th scope="col">Snapshot UUID</th>
|
||||||
<th scope="col">Version</th>
|
<th scope="col">Version</th>
|
||||||
<th scope="col">DHID</th>
|
<th scope="col">DHID</th>
|
||||||
<th scope="col">System UUID</th>
|
<th scope="col">System UUID</th>
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<th scope="col">Type Upload</th>
|
<th scope="col">Type Upload</th>
|
||||||
<th scope="col">Type Device</th>
|
<th scope="col">Type Device</th>
|
||||||
<th scope="col">Original DHID</th>
|
<th scope="col">Original DHID</th>
|
||||||
<th scope="col" data-type="date" data-format="DD-MM-YYYY">Time</th>
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Time</th>
|
||||||
<th scope="col"></th>
|
<th scope="col"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
<td>
|
<td>
|
||||||
{{ snap.original_dhid }}
|
{{ snap.original_dhid }}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ snap.created.strftime('%H:%M %d-%m-%Y') }}</td>
|
<td>{{ snap.created.strftime('%Y-%m-%d %H:%M') }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if snap.snapshot_uuid %}
|
{% if snap.snapshot_uuid %}
|
||||||
<a href="{{ url_for('inventory.export', export_id='snapshot') }}?id={{ snap.snapshot_uuid }}" target="_blank">
|
<a href="{{ url_for('inventory.export', export_id='snapshot') }}?id={{ snap.snapshot_uuid }}" target="_blank">
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<th scope="col">Type</th>
|
<th scope="col">Type</th>
|
||||||
<th scope="col">Provider</th>
|
<th scope="col">Provider</th>
|
||||||
<th scope="col">Device</th>
|
<th scope="col">Device</th>
|
||||||
<th scope="col">Created</th>
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ tag.created.strftime('%H:%M %d-%m-%Y') }}</td>
|
<td>{{ tag.created.strftime('%Y-%m-%d %H:%M') }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<section class="section profile">
|
<section class="section profile">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-8">
|
<div class="col-xxl-9">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -91,8 +91,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-1">
|
<div class="col-1 d-none d-md-block printLabelForm"></div>
|
||||||
</div>
|
|
||||||
<div class="col label">
|
<div class="col label">
|
||||||
<label class="col-form-label col-sm-2">Logo</label>
|
<label class="col-form-label col-sm-2">Logo</label>
|
||||||
|
|
||||||
|
@ -153,7 +152,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-switch">
|
<div class="form-switch">
|
||||||
<input class="form-check-input" name="tags" type="checkbox" id="tagsCheck">
|
<input class="form-check-input" name="tags" type="checkbox" id="tagsCheck">
|
||||||
<label class="form-check-label" for="tagsCheck">Tags</label>
|
<label class="form-check-label" for="tagsCheck">Unique Identifiers</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-switch">
|
<div class="form-switch">
|
||||||
<input class="form-check-input" name="serial_number" type="checkbox" id="serialNumberCheck">
|
<input class="form-check-input" name="serial_number" type="checkbox" id="serialNumberCheck">
|
||||||
|
|
|
@ -14,6 +14,62 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-6">
|
<div class="col-xl-6">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="pt-6 pb-2">
|
||||||
|
<div class="row pt-3">
|
||||||
|
<div class="col">
|
||||||
|
<form method="post">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">PHID</th>
|
||||||
|
<th scope="col" class="text-center">Erasure Host</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for host in form.kangaroos %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ host.phid }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{{ url_for('workbench.erasure_host', id=host.id) }}"><i class="bi bi-x-lg"></i></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{% for f in form %}
|
||||||
|
{{ f }}
|
||||||
|
{% if f == form.phid and f.errors %}
|
||||||
|
<p class="text-danger">
|
||||||
|
{% for error in f.errors %}
|
||||||
|
{{ error }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<input type="submit" class="btn btn-primary" value="Add new host" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
|
@ -26,120 +82,150 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-8">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if demo %}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-6">
|
<div class="col">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
<div class="pt-6 pb-2">
|
<div class="pt-6 pb-2">
|
||||||
<h5 class="card-title text-center pb-0 fs-4">Workbench 2022</h5>
|
<h5 class="card-title pb-0 fs-4">Usody Hardware Metadata 2022</h5>
|
||||||
<div class="row pt-3">
|
<p class="mb-5">
|
||||||
<div class="col-5">
|
A certified collection of hardware details and testing reports<br />
|
||||||
<a href="{{ iso.demo.url }}{{ iso.demo.iso }}" class="btn btn-primary">{{ iso.demo.iso }}</a>
|
<small>Desktops, Servers and Laptops</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-2">
|
||||||
|
<a href="{{ iso_register.url }}{{ iso_register.iso }}" class="btn btn-primary" style="max-width: 200px;">
|
||||||
|
Download ISO
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col-3">
|
||||||
<p class="small">
|
<p class="small">
|
||||||
Download Checksum: <a class="help" href="{{ iso.demo.url }}SHA512SUM">SHA512SUM</a> |
|
Download Checksum: <a class="help" href="{{ iso_register.url }}SHA512SUM">SHA512SUM</a> |
|
||||||
<a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a></p>
|
<a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="border mr-2 p-2">
|
||||||
|
<h5>Basic Metadata</h5>
|
||||||
|
<p>Settings for basic hardware metadata collection and hard drive smart Test reports.</p>
|
||||||
|
<a href="{{ url_for('workbench.settings') }}?opt=register" class="btn btn-primary" style="width: 100%">Download settings file</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-8">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{% if not demo %}
|
||||||
{% else %}
|
|
||||||
{% for d, v in iso.items() %}
|
|
||||||
{% if d != 'demo' %}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-6">
|
<div class="col">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
<div class="pt-6 pb-2">
|
<div class="pt-8 pb-2">
|
||||||
<h5 class="card-title text-center pb-0 fs-4">Workbench {{ d }}</h5>
|
<h5 class="card-title pb-0 fs-4">Usody Data Erasure v14</h5>
|
||||||
{% if d == 'v14' %}
|
<p class="mb-5">
|
||||||
|
A certified data erasure software to irreversibly removing data sored on hard drives.<br />
|
||||||
|
<small>Desktops, Servers and Laptops</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-5">
|
<div class="col-2">
|
||||||
<a href="{{ url_for('workbench.settings') }}?opt=erease_basic" class="btn btn-primary" style="width: 200px;">Get settings file!</a>
|
<a href="{{ iso_erease.url }}{{ iso_erease.iso }}" class="btn btn-primary" style="max-width: 200px;">
|
||||||
|
Download ISO
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col-3">
|
||||||
<p class="small">
|
<p class="small">
|
||||||
Settings for basic data erasure. | <a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a>
|
Download Checksum: <a class="help" href="{{ iso_erease.url }}SHA512SUM">SHA512SUM</a> |
|
||||||
|
<a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="border mr-2 p-2">
|
||||||
|
<h5>Basic Erasure</h5>
|
||||||
|
<p>
|
||||||
|
Settings for basic data erasure using shred Linux command.
|
||||||
|
A software-based fast non-100%-secured way of erasing data storage.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performs <strong>1</strong> pass overwriting one round using all zeros.
|
||||||
|
Compliant with <strong>NIST SP-800-88</strong>
|
||||||
|
</p>
|
||||||
|
<a href="{{ url_for('workbench.settings') }}?opt=erease_basic"
|
||||||
|
class="btn btn-primary"
|
||||||
|
style="width: 100%;">
|
||||||
|
Download settings file
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="border mr-2 p-2">
|
||||||
|
<h5>Baseline Secure Erasure</h5>
|
||||||
|
<p>
|
||||||
|
Settings for advanced data erasure using badblocks Linux software.
|
||||||
|
A secured-way of erasing data storages, erase hidden areas, checking the erase sector by sector.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performs <strong>1</strong> pass overwriting each sector with zeros and a final verification.
|
||||||
|
Compliant with <strong>HMG Infosec Standard 5 Baseline</strong>.
|
||||||
|
</p>
|
||||||
|
<a href="{{ url_for('workbench.settings') }}?opt=erease_sectors"
|
||||||
|
class="btn btn-primary"
|
||||||
|
style="width: 100%;">
|
||||||
|
Download settings file
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-3">
|
||||||
|
<div class="border mr-2 p-2">
|
||||||
|
<h5>Enhanced Secure Erasure</h5>
|
||||||
|
<p>
|
||||||
|
Settings for advanced data erasure using badblocks Linux software.
|
||||||
|
A secured-way of erasing data storages, erase hidden areas, checking the erase sector by sector.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Performs <strong>3</strong> passes overwriting every sector with zeros and ones, and final verification.
|
||||||
|
Compliant with <strong>HMG Infosec Standard 5 Enhanced</strong>.
|
||||||
|
</p>
|
||||||
|
<span
|
||||||
|
class="btn btn-secondary"
|
||||||
|
style="width: 100%;">
|
||||||
|
Download settings file
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row pt-2">
|
|
||||||
<div class="col-5">
|
|
||||||
<a href="{{ url_for('workbench.settings') }}?opt=erease_sectors" class="btn btn-primary" style="width: 200px;">Get settings file!</a>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<p class="small">
|
|
||||||
Settings for advanced data erasure through sectors and hidden areas. Guarantee of data removal. | <a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-5">
|
|
||||||
<a href="{{ url_for('workbench.settings') }}?opt=register" class="btn btn-primary" style="width: 200px;">Get settings file!</a>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<p class="small">
|
|
||||||
Settings for register devices.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if iso %}
|
|
||||||
<br />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-5">
|
|
||||||
<a href="{{ v.url }}{{ v.iso }}" class="btn btn-primary" style="width: 200px;">Get ISO file</a>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<p class="small">
|
|
||||||
{{ v.iso }}
|
|
||||||
</p>
|
|
||||||
<p class="small">
|
|
||||||
Download Checksum: <a class="help" href="{{ v.url }}SHA512SUM">SHA512SUM</a> |
|
|
||||||
<a href="https://help.usody.com/es/setup/setup-pendrive/" target="_blank" class="help">Help</a></p>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-xl-8">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
{% endblock main %}
|
{% endblock main %}
|
||||||
|
|
|
@ -3,11 +3,11 @@ isos = {
|
||||||
'iso': "USODY_2022.8.0-Demo.iso",
|
'iso': "USODY_2022.8.0-Demo.iso",
|
||||||
'url': 'http://releases.usody.com/demo/',
|
'url': 'http://releases.usody.com/demo/',
|
||||||
},
|
},
|
||||||
"2022": {
|
"register": {
|
||||||
'iso': "USODY_2022.8.0-beta.iso",
|
'iso': "USODY_2022.8.0-beta.iso",
|
||||||
'url': 'http://releases.usody.com/2022/',
|
'url': 'http://releases.usody.com/2022/',
|
||||||
},
|
},
|
||||||
"v14": {
|
"erease": {
|
||||||
'iso': "USODY_14.0.0.iso",
|
'iso': "USODY_14.0.0.iso",
|
||||||
'url': 'http://releases.usody.com/v14/',
|
'url': 'http://releases.usody.com/v14/',
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
from flask import g
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, validators
|
||||||
|
|
||||||
|
from ereuse_devicehub.db import db
|
||||||
|
from ereuse_devicehub.resources.device.models import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class KangarooForm(FlaskForm):
|
||||||
|
phid = StringField('Phid', [validators.length(min=1)])
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.placeholder = None
|
||||||
|
self.kangaroos = Placeholder.query.filter(
|
||||||
|
Placeholder.kangaroo.is_(True)
|
||||||
|
).filter(Placeholder.owner_id == g.user.id)
|
||||||
|
|
||||||
|
def validate(self, extra_validators=None):
|
||||||
|
is_valid = super().validate(extra_validators)
|
||||||
|
if not is_valid:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.placeholder:
|
||||||
|
self.placeholder = (
|
||||||
|
Placeholder.query.filter(Placeholder.phid == self.phid.data)
|
||||||
|
.filter(Placeholder.owner_id == g.user.id)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if self.placeholder:
|
||||||
|
if self.placeholder.status not in ['Snapshot', 'Twin']:
|
||||||
|
self.placeholder = None
|
||||||
|
|
||||||
|
if not self.placeholder:
|
||||||
|
self.phid.errors = ["Device not exist"]
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
if not self.placeholder or self.placeholder.kangaroo:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.placeholder.kangaroo = True
|
||||||
|
db.session.commit()
|
||||||
|
return self.placeholder
|
|
@ -3,34 +3,45 @@ import time
|
||||||
import flask
|
import flask
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from flask import current_app as app
|
from flask import current_app as app
|
||||||
from flask import g, make_response, request
|
from flask import g, make_response, request, url_for
|
||||||
|
from flask.views import View
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from ereuse_devicehub import auth
|
from ereuse_devicehub import auth
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
|
from ereuse_devicehub.resources.device.models import Placeholder
|
||||||
from ereuse_devicehub.resources.enums import SessionType
|
from ereuse_devicehub.resources.enums import SessionType
|
||||||
from ereuse_devicehub.resources.user.models import Session
|
from ereuse_devicehub.resources.user.models import Session
|
||||||
from ereuse_devicehub.views import GenericMixin
|
from ereuse_devicehub.views import GenericMixin
|
||||||
from ereuse_devicehub.workbench import isos
|
from ereuse_devicehub.workbench import isos
|
||||||
|
from ereuse_devicehub.workbench.forms import KangarooForm
|
||||||
|
|
||||||
workbench = Blueprint('workbench', __name__, url_prefix='/workbench')
|
workbench = Blueprint('workbench', __name__, url_prefix='/workbench')
|
||||||
|
|
||||||
|
|
||||||
class SettingsView(GenericMixin):
|
class SettingsView(GenericMixin):
|
||||||
decorators = [login_required]
|
decorators = [login_required]
|
||||||
|
methods = ['GET', 'POST']
|
||||||
template_name = 'workbench/settings.html'
|
template_name = 'workbench/settings.html'
|
||||||
page_title = "Workbench"
|
page_title = "Snapshots"
|
||||||
|
|
||||||
def dispatch_request(self):
|
def dispatch_request(self):
|
||||||
self.get_context()
|
self.get_context()
|
||||||
|
form_kangaroo = KangarooForm()
|
||||||
self.context.update(
|
self.context.update(
|
||||||
{
|
{
|
||||||
'page_title': self.page_title,
|
'page_title': self.page_title,
|
||||||
'demo': g.user.email == app.config['EMAIL_DEMO'],
|
'demo': g.user.email == app.config['EMAIL_DEMO'],
|
||||||
'iso': isos,
|
'iso_demo': isos['demo'],
|
||||||
|
'iso_register': isos['register'],
|
||||||
|
'iso_erease': isos['erease'],
|
||||||
|
'form': form_kangaroo,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if form_kangaroo.validate_on_submit():
|
||||||
|
form_kangaroo.save()
|
||||||
|
|
||||||
self.opt = request.values.get('opt')
|
self.opt = request.values.get('opt')
|
||||||
if self.opt in ['register', 'erease_basic', 'erease_sectors']:
|
if self.opt in ['register', 'erease_basic', 'erease_sectors']:
|
||||||
return self.download()
|
return self.download()
|
||||||
|
@ -86,4 +97,24 @@ class SettingsView(GenericMixin):
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
|
class ErasureHostView(View):
|
||||||
|
decorators = [login_required]
|
||||||
|
methods = ['GET']
|
||||||
|
|
||||||
|
def dispatch_request(self, id):
|
||||||
|
self.placeholder = (
|
||||||
|
Placeholder.query.filter(Placeholder.id == id)
|
||||||
|
.filter(Placeholder.kangaroo.is_(True))
|
||||||
|
.filter(Placeholder.owner_id == g.user.id)
|
||||||
|
.one()
|
||||||
|
)
|
||||||
|
self.placeholder.kangaroo = False
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return flask.redirect(url_for('workbench.settings'))
|
||||||
|
|
||||||
|
|
||||||
workbench.add_url_rule('/', view_func=SettingsView.as_view('settings'))
|
workbench.add_url_rule('/', view_func=SettingsView.as_view('settings'))
|
||||||
|
workbench.add_url_rule(
|
||||||
|
'/erasure_host/<int:id>/', view_func=ErasureHostView.as_view('erasure_host')
|
||||||
|
)
|
||||||
|
|
|
@ -17,7 +17,7 @@ from ereuse_devicehub.workbench.views import workbench
|
||||||
# from flask_wtf.csrf import CSRFProtect
|
# from flask_wtf.csrf import CSRFProtect
|
||||||
|
|
||||||
|
|
||||||
# from werkzeug.contrib.profiler import ProfilerMiddleware
|
# from werkzeug.middleware.profiler import ProfilerMiddleware
|
||||||
|
|
||||||
|
|
||||||
SENTRY_DSN = config('SENTRY_DSN', None)
|
SENTRY_DSN = config('SENTRY_DSN', None)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from ereuse_devicehub.devicehub import Devicehub
|
from werkzeug.middleware.profiler import ProfilerMiddleware
|
||||||
from werkzeug.contrib.profiler import ProfilerMiddleware
|
|
||||||
|
|
||||||
|
from ereuse_devicehub.devicehub import Devicehub
|
||||||
|
|
||||||
app = Devicehub(inventory='dbtest')
|
app = Devicehub(inventory='dbtest')
|
||||||
app.config["SQLALCHEMY_RECORD_QUERIES"] = True
|
app.config["SQLALCHEMY_RECORD_QUERIES"] = True
|
||||||
app.config['PROFILE'] = True
|
app.config['PROFILE'] = True
|
||||||
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30])
|
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30])
|
||||||
app.run(debug = True)
|
app.run(debug=True)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint:report": "eslint ereuse_devicehub --ext .js --output-file eslint_report.json --format json",
|
"lint:report": "eslint ereuse_devicehub --ext .js --output-file eslint_report.json --format json",
|
||||||
"lint:fix": "eslint ereuse_devicehub --ext .js --fix",
|
"lint:fix": "eslint ereuse_devicehub --ext .js --fix",
|
||||||
"babel": "babel ereuse_devicehub/static/js/main_inventory.js --out-file ereuse_devicehub/static/js/main_inventory.build.js"
|
"babel": "babel ereuse_devicehub/static/js/main_inventory.js --out-file ereuse_devicehub/static/js/main_inventory.build.js && echo 'Ignoring parameters: '"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
alembic==1.4.2
|
||||||
|
atomicwrites==1.4.0
|
||||||
|
click-spinner==0.1.8
|
||||||
|
colorama==0.3.9
|
||||||
|
colour==0.1.5
|
||||||
|
ereuse-utils[naming,test,session,cli]==0.4.0b50
|
||||||
|
Flask-Cors==3.0.10
|
||||||
|
Flask-Login==0.5.0
|
||||||
|
Flask-WTF==1.0.0
|
||||||
|
flask-weasyprint==0.4
|
||||||
|
hashids==1.2.0
|
||||||
|
more-itertools==8.12.0
|
||||||
|
passlib==1.7.1
|
||||||
|
phonenumbers==8.9.11
|
||||||
|
psycopg2-binary==2.8.3
|
||||||
|
pyjwt==2.4.0
|
||||||
|
python-decouple==3.3
|
||||||
|
python-dotenv==0.14.0
|
||||||
|
python-stdnum==1.9
|
||||||
|
pyyaml==5.4
|
||||||
|
requests==2.27.1
|
||||||
|
requests-mock==1.5.2
|
||||||
|
requests-toolbelt==0.9.1
|
||||||
|
sortedcontainers==2.1.0
|
||||||
|
sqlalchemy-citext==1.3.post0
|
||||||
|
sqlalchemy-utils==0.33.11
|
||||||
|
teal==0.2.0a38
|
||||||
|
tqdm==4.32.2
|
||||||
|
|
||||||
|
# workbench json parsing dependencies
|
||||||
|
pint==0.9
|
||||||
|
py-dmidecode==0.1.0
|
||||||
|
pandas==1.3.5
|
||||||
|
numpy==1.22.0 # pandas dependency
|
||||||
|
odfpy==1.4.1 # pandas dependency
|
||||||
|
xlrd==2.0.1 # pandas dependency
|
||||||
|
openpyxl==3.0.10 # pandas dependency
|
||||||
|
et_xmlfile==1.1.0 # pandas dependency
|
||||||
|
|
||||||
|
# manual dependency
|
||||||
|
marshmallow-enum==1.4.1
|
251
requirements.txt
251
requirements.txt
|
@ -1,53 +1,226 @@
|
||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile with python 3.8
|
||||||
|
# To update, run:
|
||||||
|
#
|
||||||
|
# pip-compile --output-file=requirements.txt requirements.in
|
||||||
|
#
|
||||||
alembic==1.4.2
|
alembic==1.4.2
|
||||||
|
# via -r requirements.in
|
||||||
anytree==2.4.3
|
anytree==2.4.3
|
||||||
|
# via teal
|
||||||
apispec==0.39.0
|
apispec==0.39.0
|
||||||
|
# via teal
|
||||||
|
atomicwrites==1.4.0
|
||||||
|
# via -r requirements.in
|
||||||
boltons==18.0.1
|
boltons==18.0.1
|
||||||
|
# via
|
||||||
|
# ereuse-utils
|
||||||
|
# teal
|
||||||
|
cairocffi==1.4.0
|
||||||
|
# via
|
||||||
|
# cairosvg
|
||||||
|
# weasyprint
|
||||||
|
cairosvg==2.5.2
|
||||||
|
# via weasyprint
|
||||||
|
certifi==2022.9.24
|
||||||
|
# via requests
|
||||||
|
cffi==1.15.1
|
||||||
|
# via
|
||||||
|
# cairocffi
|
||||||
|
# weasyprint
|
||||||
|
charset-normalizer==2.0.12
|
||||||
|
# via requests
|
||||||
click==6.7
|
click==6.7
|
||||||
|
# via
|
||||||
|
# ereuse-utils
|
||||||
|
# flask
|
||||||
click-spinner==0.1.8
|
click-spinner==0.1.8
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# teal
|
||||||
colorama==0.3.9
|
colorama==0.3.9
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# ereuse-utils
|
||||||
colour==0.1.5
|
colour==0.1.5
|
||||||
ereuse-utils[naming,test,session,cli]==0.4.0b50
|
# via
|
||||||
Flask==1.0.2
|
# -r requirements.in
|
||||||
Flask-Cors==3.0.10
|
# sqlalchemy-utils
|
||||||
Flask-Login==0.5.0
|
cssselect2==0.7.0
|
||||||
Flask-SQLAlchemy==2.3.2
|
# via
|
||||||
Flask-WTF==1.0.0
|
# cairosvg
|
||||||
|
# weasyprint
|
||||||
|
defusedxml==0.7.1
|
||||||
|
# via
|
||||||
|
# cairosvg
|
||||||
|
# odfpy
|
||||||
|
ereuse-utils[cli,naming,session,test]==0.4.0b50
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# teal
|
||||||
|
et-xmlfile==1.1.0
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# openpyxl
|
||||||
|
flask==1.0.2
|
||||||
|
# via
|
||||||
|
# ereuse-utils
|
||||||
|
# flask-cors
|
||||||
|
# flask-login
|
||||||
|
# flask-sqlalchemy
|
||||||
|
# flask-weasyprint
|
||||||
|
# flask-wtf
|
||||||
|
# teal
|
||||||
|
flask-cors==3.0.10
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# teal
|
||||||
|
flask-login==0.5.0
|
||||||
|
# via -r requirements.in
|
||||||
|
flask-sqlalchemy==2.5.1
|
||||||
|
# via teal
|
||||||
|
flask-weasyprint==0.4
|
||||||
|
# via -r requirements.in
|
||||||
|
flask-wtf==1.0.0
|
||||||
|
# via -r requirements.in
|
||||||
hashids==1.2.0
|
hashids==1.2.0
|
||||||
|
# via -r requirements.in
|
||||||
|
html5lib==1.1
|
||||||
|
# via weasyprint
|
||||||
|
idna==3.4
|
||||||
|
# via requests
|
||||||
inflection==0.3.1
|
inflection==0.3.1
|
||||||
|
# via ereuse-utils
|
||||||
itsdangerous==2.0.1
|
itsdangerous==2.0.1
|
||||||
# lock Jinja2 version because it's the latest compatible with Flask 1.0.X
|
# via
|
||||||
# see related info on https://github.com/pallets/jinja/issues/1628
|
# flask
|
||||||
Jinja2==3.0.3
|
# flask-wtf
|
||||||
|
jinja2==3.0.3
|
||||||
|
# via flask
|
||||||
|
mako==1.2.3
|
||||||
|
# via alembic
|
||||||
|
markupsafe==2.1.1
|
||||||
|
# via
|
||||||
|
# jinja2
|
||||||
|
# mako
|
||||||
|
# wtforms
|
||||||
marshmallow==3.0.0b11
|
marshmallow==3.0.0b11
|
||||||
|
# via
|
||||||
|
# marshmallow-enum
|
||||||
|
# teal
|
||||||
|
# webargs
|
||||||
marshmallow-enum==1.4.1
|
marshmallow-enum==1.4.1
|
||||||
passlib==1.7.1
|
# via -r requirements.in
|
||||||
phonenumbers==8.9.11
|
more-itertools==8.12.0
|
||||||
pytest==3.7.2
|
# via -r requirements.in
|
||||||
pytest-runner==4.2
|
numpy==1.22.0
|
||||||
python-dateutil==2.7.3
|
# via
|
||||||
python-stdnum==1.9
|
# -r requirements.in
|
||||||
PyYAML==5.4
|
# pandas
|
||||||
requests[security]==2.27.1
|
odfpy==1.4.1
|
||||||
requests-mock==1.5.2
|
# via -r requirements.in
|
||||||
SQLAlchemy==1.3.24
|
openpyxl==3.0.10
|
||||||
SQLAlchemy-Utils==0.33.11
|
# via -r requirements.in
|
||||||
teal==0.2.0a38
|
|
||||||
webargs==5.5.3
|
|
||||||
Werkzeug==0.15.5
|
|
||||||
sqlalchemy-citext==1.3.post0
|
|
||||||
flask-weasyprint==0.5
|
|
||||||
weasyprint==44
|
|
||||||
psycopg2-binary==2.8.3
|
|
||||||
sortedcontainers==2.1.0
|
|
||||||
tqdm==4.32.2
|
|
||||||
python-decouple==3.3
|
|
||||||
python-dotenv==0.14.0
|
|
||||||
pyjwt==2.4.0
|
|
||||||
pint==0.9
|
|
||||||
py-dmidecode==0.1.0
|
|
||||||
pandas==1.3.5
|
pandas==1.3.5
|
||||||
numpy==1.22.0 # pandas dependency
|
# via -r requirements.in
|
||||||
odfpy==1.4.1 # pandas dependency
|
passlib==1.7.1
|
||||||
xlrd==2.0.1 # pandas dependency
|
# via
|
||||||
openpyxl==3.0.10 # pandas dependency
|
# -r requirements.in
|
||||||
et_xmlfile==1.1.0 # pandas dependency
|
# sqlalchemy-utils
|
||||||
|
phonenumbers==8.9.11
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# sqlalchemy-utils
|
||||||
|
pillow==9.2.0
|
||||||
|
# via cairosvg
|
||||||
|
pint==0.9
|
||||||
|
# via -r requirements.in
|
||||||
|
psycopg2-binary==2.8.3
|
||||||
|
# via -r requirements.in
|
||||||
|
py-dmidecode==0.1.0
|
||||||
|
# via -r requirements.in
|
||||||
|
pycparser==2.21
|
||||||
|
# via cffi
|
||||||
|
pyjwt==2.4.0
|
||||||
|
# via -r requirements.in
|
||||||
|
pyphen==0.13.0
|
||||||
|
# via weasyprint
|
||||||
|
python-dateutil==2.7.3
|
||||||
|
# via
|
||||||
|
# alembic
|
||||||
|
# pandas
|
||||||
|
python-decouple==3.3
|
||||||
|
# via -r requirements.in
|
||||||
|
python-dotenv==0.14.0
|
||||||
|
# via -r requirements.in
|
||||||
|
python-editor==1.0.4
|
||||||
|
# via alembic
|
||||||
|
python-stdnum==1.9
|
||||||
|
# via -r requirements.in
|
||||||
|
pytz==2022.2.1
|
||||||
|
# via pandas
|
||||||
|
pyyaml==5.4
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# apispec
|
||||||
|
requests==2.27.1
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# requests-mock
|
||||||
|
# requests-toolbelt
|
||||||
|
requests-mock==1.5.2
|
||||||
|
# via -r requirements.in
|
||||||
|
requests-toolbelt==0.9.1
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# ereuse-utils
|
||||||
|
six==1.16.0
|
||||||
|
# via
|
||||||
|
# anytree
|
||||||
|
# flask-cors
|
||||||
|
# html5lib
|
||||||
|
# python-dateutil
|
||||||
|
# requests-mock
|
||||||
|
# sqlalchemy-utils
|
||||||
|
sortedcontainers==2.1.0
|
||||||
|
# via -r requirements.in
|
||||||
|
sqlalchemy==1.3.24
|
||||||
|
# via
|
||||||
|
# alembic
|
||||||
|
# flask-sqlalchemy
|
||||||
|
# sqlalchemy-citext
|
||||||
|
# sqlalchemy-utils
|
||||||
|
sqlalchemy-citext==1.3.post0
|
||||||
|
# via -r requirements.in
|
||||||
|
sqlalchemy-utils[color,password,phone]==0.33.11
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# teal
|
||||||
|
teal==0.2.0a38
|
||||||
|
# via -r requirements.in
|
||||||
|
tinycss2==1.1.1
|
||||||
|
# via
|
||||||
|
# cairosvg
|
||||||
|
# cssselect2
|
||||||
|
# weasyprint
|
||||||
|
tqdm==4.32.2
|
||||||
|
# via
|
||||||
|
# -r requirements.in
|
||||||
|
# ereuse-utils
|
||||||
|
urllib3==1.26.12
|
||||||
|
# via requests
|
||||||
|
weasyprint==44
|
||||||
|
# via flask-weasyprint
|
||||||
|
webargs==5.5.3
|
||||||
|
# via teal
|
||||||
|
webencodings==0.5.1
|
||||||
|
# via
|
||||||
|
# cssselect2
|
||||||
|
# html5lib
|
||||||
|
# tinycss2
|
||||||
|
werkzeug==2.0.3
|
||||||
|
# via flask
|
||||||
|
wtforms==3.0.1
|
||||||
|
# via flask-wtf
|
||||||
|
xlrd==2.0.1
|
||||||
|
# via -r requirements.in
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Phid;Model;Manufacturer;Serial Number;Part Number;Id device Supplier;Pallet;Info
|
Model;Manufacturer;Serial Number;Part Number;Id device Supplier;Id device Internal;Pallet;Info
|
||||||
a123;Vaio;Sony;12345678;;TTT;24A;Good conditions
|
Vaio;Sony;12345678;;TTT;AA;24A;Good conditions
|
||||||
a124;Vaio;Sony;12345679;;TTT;24A;Good conditions
|
Vaio;Sony;12345679;;TTT;BB;24A;Good conditions
|
||||||
a125;Vaio;Sony;12345680;;TTT;24A;Good conditions
|
Vaio;Sony;12345680;;TTT;CC;24A;Good conditions
|
||||||
|
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,4 @@
|
||||||
import copy
|
import copy
|
||||||
import ipaddress
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -7,7 +6,7 @@ from datetime import datetime, timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
from typing import Tuple, Type
|
from typing import Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from dateutil.tz import tzutc
|
from dateutil.tz import tzutc
|
||||||
|
@ -15,7 +14,7 @@ from flask import current_app as app
|
||||||
from flask import g
|
from flask import g
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from sqlalchemy.util import OrderedSet
|
from sqlalchemy.util import OrderedSet
|
||||||
from teal.enums import Currency, Subdivision
|
from teal.enums import Currency
|
||||||
|
|
||||||
from ereuse_devicehub.client import Client, UserClient
|
from ereuse_devicehub.client import Client, UserClient
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
|
@ -82,11 +81,7 @@ def test_erase_basic():
|
||||||
def test_validate_device_data_storage():
|
def test_validate_device_data_storage():
|
||||||
"""Checks the validation for data-storage-only actions works."""
|
"""Checks the validation for data-storage-only actions works."""
|
||||||
# We can't set a GraphicCard
|
# We can't set a GraphicCard
|
||||||
with pytest.raises(
|
with pytest.raises(TypeError):
|
||||||
TypeError,
|
|
||||||
message='EraseBasic.device must be a DataStorage '
|
|
||||||
'but you passed <GraphicCard None model=\'foo-bar\' S/N=\'foo\'>',
|
|
||||||
):
|
|
||||||
models.EraseBasic(
|
models.EraseBasic(
|
||||||
device=GraphicCard(
|
device=GraphicCard(
|
||||||
serial_number='foo', manufacturer='bar', model='foo-bar'
|
serial_number='foo', manufacturer='bar', model='foo-bar'
|
||||||
|
@ -94,6 +89,10 @@ def test_validate_device_data_storage():
|
||||||
clean_with_zeros=True,
|
clean_with_zeros=True,
|
||||||
**conftest.T,
|
**conftest.T,
|
||||||
)
|
)
|
||||||
|
pytest.fail(
|
||||||
|
'EraseBasic.device must be a DataStorage '
|
||||||
|
'but you passed <GraphicCard None model=\'foo-bar\' S/N=\'foo\'>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -292,9 +291,7 @@ def test_generic_action(
|
||||||
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_simple_status_actions(
|
def test_simple_status_actions(action_model: models.Action, user2: UserClient):
|
||||||
action_model: models.Action, user2: UserClient
|
|
||||||
):
|
|
||||||
"""Simple test of status action."""
|
"""Simple test of status action."""
|
||||||
user = user2
|
user = user2
|
||||||
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
|
@ -554,7 +551,9 @@ def test_status_without_lot(action_model: models.Action, user: UserClient):
|
||||||
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
for ams in [models.Recycling, models.Use, models.Refurbish, models.Management]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_status_in_temporary_lot(action_model: models.Action, user: UserClient, app: Devicehub):
|
def test_status_in_temporary_lot(
|
||||||
|
action_model: models.Action, user: UserClient, app: Devicehub
|
||||||
|
):
|
||||||
"""Test of status actions for devices in a temporary lot."""
|
"""Test of status actions for devices in a temporary lot."""
|
||||||
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
snap, _ = user.post(file('basic.snapshot'), res=models.Snapshot)
|
||||||
abstract = Device.query.filter_by(id=snap['device']['id']).first()
|
abstract = Device.query.filter_by(id=snap['device']['id']).first()
|
||||||
|
@ -727,7 +726,7 @@ def test_live_without_TestDataStorage(user: UserClient, client: Client, app: Dev
|
||||||
acer = file('acer.happy.battery.snapshot')
|
acer = file('acer.happy.battery.snapshot')
|
||||||
snapshot, _ = user.post(acer, res=models.Snapshot)
|
snapshot, _ = user.post(acer, res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
device_id = snapshot['device']['id']
|
||||||
db_device = Device.query.filter_by(id=device_id).one()
|
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
@ -767,7 +766,7 @@ def test_live_without_hdd_1(user: UserClient, client: Client, app: Devicehub):
|
||||||
acer = file('acer.happy.battery.snapshot')
|
acer = file('acer.happy.battery.snapshot')
|
||||||
snapshot, _ = user.post(acer, res=models.Snapshot)
|
snapshot, _ = user.post(acer, res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
device_id = snapshot['device']['id']
|
||||||
db_device = Device.query.filter_by(id=device_id).one()
|
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
@ -803,7 +802,7 @@ def test_live_without_hdd_2(user: UserClient, client: Client, app: Devicehub):
|
||||||
acer['components'] = components
|
acer['components'] = components
|
||||||
snapshot, _ = user.post(json_encode(acer), res=models.Snapshot)
|
snapshot, _ = user.post(json_encode(acer), res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
device_id = snapshot['device']['id']
|
||||||
db_device = Device.query.filter_by(id=device_id).one()
|
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
@ -838,7 +837,7 @@ def test_live_without_hdd_3(user: UserClient, client: Client, app: Devicehub):
|
||||||
acer['components'] = components
|
acer['components'] = components
|
||||||
snapshot, _ = user.post(json_encode(acer), res=models.Snapshot)
|
snapshot, _ = user.post(json_encode(acer), res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
device_id = snapshot['device']['id']
|
||||||
db_device = Device.query.filter_by(id=device_id).one()
|
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
@ -875,7 +874,7 @@ def test_live_with_hdd_with_old_time(user: UserClient, client: Client, app: Devi
|
||||||
acer = file('acer.happy.battery.snapshot')
|
acer = file('acer.happy.battery.snapshot')
|
||||||
snapshot, _ = user.post(acer, res=models.Snapshot)
|
snapshot, _ = user.post(acer, res=models.Snapshot)
|
||||||
device_id = snapshot['device']['id']
|
device_id = snapshot['device']['id']
|
||||||
db_device = Device.query.filter_by(id=device_id).one()
|
|
||||||
post_request = {
|
post_request = {
|
||||||
"transaction": "ccc",
|
"transaction": "ccc",
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
@ -1022,7 +1021,7 @@ def test_allocate(user: UserClient):
|
||||||
allocate, _ = user.post(res=models.Allocate, data=post_request)
|
allocate, _ = user.post(res=models.Allocate, data=post_request)
|
||||||
# Normal allocate
|
# Normal allocate
|
||||||
device, _ = user.get(res=Device, item=devicehub_id)
|
device, _ = user.get(res=Device, item=devicehub_id)
|
||||||
assert device['allocated'] == True
|
assert device['allocated'] is True
|
||||||
action = [a for a in device['actions'] if a['type'] == 'Allocate'][0]
|
action = [a for a in device['actions'] if a['type'] == 'Allocate'][0]
|
||||||
assert action['transaction'] == allocate['transaction']
|
assert action['transaction'] == allocate['transaction']
|
||||||
assert action['finalUserCode'] == allocate['finalUserCode']
|
assert action['finalUserCode'] == allocate['finalUserCode']
|
||||||
|
@ -1097,11 +1096,11 @@ def test_deallocate(user: UserClient):
|
||||||
|
|
||||||
user.post(res=models.Allocate, data=post_allocate)
|
user.post(res=models.Allocate, data=post_allocate)
|
||||||
device, _ = user.get(res=Device, item=devicehub_id)
|
device, _ = user.get(res=Device, item=devicehub_id)
|
||||||
assert device['allocated'] == True
|
assert device['allocated'] is True
|
||||||
deallocate, _ = user.post(res=models.Deallocate, data=post_deallocate)
|
deallocate, _ = user.post(res=models.Deallocate, data=post_deallocate)
|
||||||
assert deallocate['startTime'] == post_deallocate['startTime']
|
assert deallocate['startTime'] == post_deallocate['startTime']
|
||||||
assert deallocate['devices'][0]['id'] == device_id
|
assert deallocate['devices'][0]['id'] == device_id
|
||||||
assert deallocate['devices'][0]['allocated'] == False
|
assert deallocate['devices'][0]['allocated'] is False
|
||||||
res, _ = user.post(res=models.Deallocate, data=post_deallocate, status=422)
|
res, _ = user.post(res=models.Deallocate, data=post_deallocate, status=422)
|
||||||
assert res['code'] == 422
|
assert res['code'] == 422
|
||||||
assert res['type'] == 'ValidationError'
|
assert res['type'] == 'ValidationError'
|
||||||
|
@ -1204,8 +1203,8 @@ def test_offer_without_to(user: UserClient):
|
||||||
users = [ac.user for ac in trade.acceptances]
|
users = [ac.user for ac in trade.acceptances]
|
||||||
assert trade.user_to == device.owner
|
assert trade.user_to == device.owner
|
||||||
assert request_post['code'].lower() in device.owner.email
|
assert request_post['code'].lower() in device.owner.email
|
||||||
assert device.owner.active == False
|
assert device.owner.active is False
|
||||||
assert device.owner.phantom == True
|
assert device.owner.phantom is True
|
||||||
assert trade.user_to in users
|
assert trade.user_to in users
|
||||||
assert trade.user_from in users
|
assert trade.user_from in users
|
||||||
assert device.owner.email != user.email
|
assert device.owner.email != user.email
|
||||||
|
@ -1283,8 +1282,8 @@ def test_offer_without_from(user: UserClient, user2: UserClient):
|
||||||
|
|
||||||
phantom_user = trade.user_from
|
phantom_user = trade.user_from
|
||||||
assert request_post['code'].lower() in phantom_user.email
|
assert request_post['code'].lower() in phantom_user.email
|
||||||
assert phantom_user.active == False
|
assert phantom_user.active is False
|
||||||
assert phantom_user.phantom == True
|
assert phantom_user.phantom is True
|
||||||
# assert trade.confirm_transfer
|
# assert trade.confirm_transfer
|
||||||
|
|
||||||
users = [ac.user for ac in trade.acceptances]
|
users = [ac.user for ac in trade.acceptances]
|
||||||
|
@ -1778,12 +1777,12 @@ def test_confirmRevoke(user: UserClient, user2: UserClient):
|
||||||
assert device_10 in trade.devices
|
assert device_10 in trade.devices
|
||||||
assert len(trade.devices) == 10
|
assert len(trade.devices) == 10
|
||||||
|
|
||||||
# the SCRAP confirms the revoke action
|
# TODO??? the SCRAP confirms the revoke action
|
||||||
request_confirm_revoke = {
|
# request_confirm_revoke = {
|
||||||
'type': 'ConfirmRevoke',
|
# 'type': 'ConfirmRevoke',
|
||||||
'action': device_10.actions[-2].id,
|
# 'action': device_10.actions[-2].id,
|
||||||
'devices': [snap10['device']['id']],
|
# 'devices': [snap10['device']['id']],
|
||||||
}
|
# }
|
||||||
|
|
||||||
# check validation error
|
# check validation error
|
||||||
# user2.post(res=models.Action, data=request_confirm_revoke, status=422)
|
# user2.post(res=models.Action, data=request_confirm_revoke, status=422)
|
||||||
|
@ -2796,7 +2795,7 @@ def test_action_web_erase(user: UserClient, client: Client):
|
||||||
)
|
)
|
||||||
assert "alert alert-info" in response
|
assert "alert alert-info" in response
|
||||||
assert "100% coincidence." in response
|
assert "100% coincidence." in response
|
||||||
assert not "alert alert-danger" in response
|
assert "alert alert-danger" not in response
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -2805,7 +2804,7 @@ def test_moveOnDocument(user: UserClient, user2: UserClient):
|
||||||
lotIn, _ = user.post({'name': 'MyLotIn'}, res=Lot)
|
lotIn, _ = user.post({'name': 'MyLotIn'}, res=Lot)
|
||||||
lotOut, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
lotOut, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
||||||
url = (
|
url = (
|
||||||
'http://www.ereuse.org/apapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapaaaa',
|
'http://www.ereuse.org/apapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaap',
|
||||||
)
|
)
|
||||||
request_post1 = {
|
request_post1 = {
|
||||||
'filename': 'test.pdf',
|
'filename': 'test.pdf',
|
||||||
|
@ -2887,7 +2886,7 @@ def test_delete_devices(user: UserClient):
|
||||||
|
|
||||||
assert action_delete.t == 'Delete'
|
assert action_delete.t == 'Delete'
|
||||||
assert str(action_delete.id) == action['id']
|
assert str(action_delete.id) == action['id']
|
||||||
assert db_device.active == False
|
assert db_device.active is False
|
||||||
|
|
||||||
# Check use of filter from frontend
|
# Check use of filter from frontend
|
||||||
url = '/devices/?filter={"type":["Computer"]}'
|
url = '/devices/?filter={"type":["Computer"]}'
|
||||||
|
@ -2953,7 +2952,6 @@ def test_delete_devices_permitions(user: UserClient, user2: UserClient):
|
||||||
|
|
||||||
file_snap = file('1-device-with-components.snapshot')
|
file_snap = file('1-device-with-components.snapshot')
|
||||||
snap, _ = user.post(file_snap, res=models.Snapshot)
|
snap, _ = user.post(file_snap, res=models.Snapshot)
|
||||||
device = Device.query.filter_by(id=snap['device']['id']).one()
|
|
||||||
|
|
||||||
request = {
|
request = {
|
||||||
'type': 'Delete',
|
'type': 'Delete',
|
||||||
|
@ -2973,7 +2971,7 @@ def test_moveOnDocument_bug168(user: UserClient, user2: UserClient):
|
||||||
lotIn, _ = user.post({'name': 'MyLotIn'}, res=Lot)
|
lotIn, _ = user.post({'name': 'MyLotIn'}, res=Lot)
|
||||||
lotOut, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
lotOut, _ = user.post({'name': 'MyLotOut'}, res=Lot)
|
||||||
url = (
|
url = (
|
||||||
'http://www.ereuse.org/apapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapaaaa',
|
'http://www.ereuse.org/apapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaapaapapaapaapaapaapaapaapaapaap',
|
||||||
)
|
)
|
||||||
request_post1 = {
|
request_post1 = {
|
||||||
'filename': 'test.pdf',
|
'filename': 'test.pdf',
|
||||||
|
@ -3014,13 +3012,12 @@ def test_moveOnDocument_bug168(user: UserClient, user2: UserClient):
|
||||||
'container_to': id_hash,
|
'container_to': id_hash,
|
||||||
'description': description,
|
'description': description,
|
||||||
}
|
}
|
||||||
doc, _ = user.post(res=models.Action, data=request_moveOn)
|
user.post(res=models.Action, data=request_moveOn)
|
||||||
trade = models.Trade.query.one()
|
|
||||||
trade_document1 = TradeDocument.query.filter_by(id=tradedocument_from['id']).one()
|
trade_document1 = TradeDocument.query.filter_by(id=tradedocument_from['id']).one()
|
||||||
trade_document2 = TradeDocument.query.filter_by(id=tradedocument_to['id']).one()
|
trade_document2 = TradeDocument.query.filter_by(id=tradedocument_to['id']).one()
|
||||||
assert trade_document1.total_weight == 150.0
|
assert trade_document1.total_weight == 150.0
|
||||||
assert trade_document2.total_weight == 4.0
|
assert trade_document2.total_weight == 4.0
|
||||||
assert trade_document1.trading == 'Confirm'
|
assert trade_document1.trading == 'Confirm'
|
||||||
assert trade_document2.trading == None
|
assert trade_document2.trading is None
|
||||||
|
|
||||||
tradedocument, _ = user.delete(res=TradeDocument, item=tradedocument_to['id'])
|
tradedocument, _ = user.delete(res=TradeDocument, item=tradedocument_to['id'])
|
||||||
|
|
|
@ -21,14 +21,22 @@ def test_authenticate_success(app: Devicehub):
|
||||||
def test_authenticate_error(app: Devicehub):
|
def test_authenticate_error(app: Devicehub):
|
||||||
"""Tests the authenticate method with wrong token values."""
|
"""Tests the authenticate method with wrong token values."""
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
MESSAGE = 'Provide a suitable token.'
|
|
||||||
create_user()
|
create_user()
|
||||||
# Token doesn't exist
|
# Token doesn't exist
|
||||||
with pytest.raises(Unauthorized, message=MESSAGE):
|
with pytest.raises(Unauthorized):
|
||||||
app.auth.authenticate(token=str(uuid4()))
|
app.auth.authenticate(token=str(uuid4()))
|
||||||
|
pytest.fail('Provide a suitable token.')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
def test_authenticate_error_malformed_token(app: Devicehub):
|
||||||
|
"""Tests the authenticate method with malformed token."""
|
||||||
|
with app.app_context():
|
||||||
|
create_user()
|
||||||
# Wrong token format
|
# Wrong token format
|
||||||
with pytest.raises(Unauthorized, message=MESSAGE):
|
with pytest.raises(Unauthorized):
|
||||||
app.auth.authenticate(token='this is a wrong uuid')
|
app.auth.authenticate(token='this is a wrong uuid')
|
||||||
|
pytest.fail('Provide a suitable token.')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -36,4 +44,6 @@ def test_auth_view(user: UserClient, client: Client):
|
||||||
"""Tests authentication at endpoint / view."""
|
"""Tests authentication at endpoint / view."""
|
||||||
user.get(res='User', item=user.user['id'], status=200)
|
user.get(res='User', item=user.user['id'], status=200)
|
||||||
client.get(res='User', item=user.user['id'], status=Unauthorized)
|
client.get(res='User', item=user.user['id'], status=Unauthorized)
|
||||||
client.get(res='User', item=user.user['id'], token='wrong token', status=Unauthorized)
|
client.get(
|
||||||
|
res='User', item=user.user['id'], token='wrong token', status=Unauthorized
|
||||||
|
)
|
||||||
|
|
|
@ -68,6 +68,7 @@ def test_api_docs(client: Client):
|
||||||
'/inventory/lot/{lot_id}/trade-document/add/',
|
'/inventory/lot/{lot_id}/trade-document/add/',
|
||||||
'/inventory/lot/{lot_id}/transfer/{type_id}/',
|
'/inventory/lot/{lot_id}/transfer/{type_id}/',
|
||||||
'/inventory/lot/{lot_id}/transfer/',
|
'/inventory/lot/{lot_id}/transfer/',
|
||||||
|
'/inventory/lot/transfer/{type_id}/',
|
||||||
'/inventory/lot/{lot_id}/upload-snapshot/',
|
'/inventory/lot/{lot_id}/upload-snapshot/',
|
||||||
'/inventory/snapshots/{snapshot_uuid}/',
|
'/inventory/snapshots/{snapshot_uuid}/',
|
||||||
'/inventory/snapshots/',
|
'/inventory/snapshots/',
|
||||||
|
@ -104,6 +105,7 @@ def test_api_docs(client: Client):
|
||||||
'/users/logout/',
|
'/users/logout/',
|
||||||
'/versions/',
|
'/versions/',
|
||||||
'/workbench/',
|
'/workbench/',
|
||||||
|
'/workbench/erasure_host/{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'] == {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import pytest
|
|
||||||
|
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
from flask import g
|
|
||||||
|
|
||||||
|
import pytest
|
||||||
from colour import Color
|
from colour import Color
|
||||||
from ereuse_utils.naming import Naming
|
from ereuse_utils.naming import Naming
|
||||||
from ereuse_utils.test import ANY
|
from ereuse_utils.test import ANY
|
||||||
|
from flask import g
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from sqlalchemy.util import OrderedSet
|
from sqlalchemy.util import OrderedSet
|
||||||
from teal.db import ResourceNotFound
|
from teal.db import ResourceNotFound
|
||||||
|
@ -20,26 +19,35 @@ from ereuse_devicehub.resources.action import models as m
|
||||||
from ereuse_devicehub.resources.action.models import Remove, TestConnectivity
|
from ereuse_devicehub.resources.action.models import Remove, TestConnectivity
|
||||||
from ereuse_devicehub.resources.agent.models import Person
|
from ereuse_devicehub.resources.agent.models import Person
|
||||||
from ereuse_devicehub.resources.device import models as d
|
from ereuse_devicehub.resources.device import models as d
|
||||||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
|
||||||
from ereuse_devicehub.resources.device.schemas import Device as DeviceS
|
from ereuse_devicehub.resources.device.schemas import Device as DeviceS
|
||||||
from ereuse_devicehub.resources.device.sync import MismatchBetweenTags, MismatchBetweenTagsAndHid, \
|
from ereuse_devicehub.resources.device.sync import (
|
||||||
Sync
|
MismatchBetweenTags,
|
||||||
from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech, Severity, \
|
MismatchBetweenTagsAndHid,
|
||||||
SnapshotSoftware, TransferState
|
Sync,
|
||||||
|
)
|
||||||
|
from ereuse_devicehub.resources.enums import (
|
||||||
|
ComputerChassis,
|
||||||
|
DisplayTech,
|
||||||
|
Severity,
|
||||||
|
SnapshotSoftware,
|
||||||
|
TransferState,
|
||||||
|
)
|
||||||
from ereuse_devicehub.resources.tag.model import Tag
|
from ereuse_devicehub.resources.tag.model import Tag
|
||||||
from ereuse_devicehub.resources.user import User
|
from ereuse_devicehub.resources.user import User
|
||||||
from tests import conftest
|
from tests import conftest
|
||||||
from tests.conftest import file, yaml2json, json_encode
|
from tests.conftest import file, json_encode, yaml2json
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
def test_device_model():
|
def test_device_model():
|
||||||
"""Tests that the correctness of the device model and its relationships."""
|
"""Tests that the correctness of the device model and its relationships."""
|
||||||
pc = d.Desktop(model='p1mo',
|
pc = d.Desktop(
|
||||||
manufacturer='p1ma',
|
model='p1mo',
|
||||||
serial_number='p1s',
|
manufacturer='p1ma',
|
||||||
chassis=ComputerChassis.Tower)
|
serial_number='p1s',
|
||||||
|
chassis=ComputerChassis.Tower,
|
||||||
|
)
|
||||||
net = d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
net = d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s')
|
||||||
graphic = d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
graphic = d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500)
|
||||||
pc.components.add(net)
|
pc.components.add(net)
|
||||||
|
@ -55,7 +63,9 @@ def test_device_model():
|
||||||
# Removing a component from pc doesn't delete the component
|
# Removing a component from pc doesn't delete the component
|
||||||
pc.components.remove(net)
|
pc.components.remove(net)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
pc = d.Device.query.filter_by(id=pc.id).first() # this is the same as querying for d.Desktop directly
|
pc = d.Device.query.filter_by(
|
||||||
|
id=pc.id
|
||||||
|
).first() # this is the same as querying for d.Desktop directly
|
||||||
assert pc.components == {graphic}
|
assert pc.components == {graphic}
|
||||||
network_adapter = d.NetworkAdapter.query.one()
|
network_adapter = d.NetworkAdapter.query.one()
|
||||||
assert network_adapter not in pc.components
|
assert network_adapter not in pc.components
|
||||||
|
@ -72,7 +82,9 @@ def test_device_model():
|
||||||
assert network_adapter.id == 4
|
assert network_adapter.id == 4
|
||||||
assert d.NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
assert d.NetworkAdapter.query.first() is not None, 'We removed the network adaptor'
|
||||||
assert gcard.id == 5, 'We should still hold a reference to a zombie graphic card'
|
assert gcard.id == 5, 'We should still hold a reference to a zombie graphic card'
|
||||||
assert d.GraphicCard.query.first() is None, 'We should have deleted it –it was inside the pc'
|
assert (
|
||||||
|
d.GraphicCard.query.first() is None
|
||||||
|
), 'We should have deleted it –it was inside the pc'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason='Test not developed')
|
@pytest.mark.xfail(reason='Test not developed')
|
||||||
|
@ -92,21 +104,25 @@ def test_device_schema():
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
def test_physical_properties():
|
def test_physical_properties():
|
||||||
c = d.Motherboard(slots=2,
|
c = d.Motherboard(
|
||||||
usb=3,
|
slots=2,
|
||||||
serial_number='sn',
|
usb=3,
|
||||||
model='ml',
|
serial_number='sn',
|
||||||
manufacturer='mr',
|
model='ml',
|
||||||
width=2.0,
|
manufacturer='mr',
|
||||||
color=Color())
|
width=2.0,
|
||||||
pc = d.Desktop(chassis=ComputerChassis.Tower,
|
color=Color(),
|
||||||
model='foo',
|
)
|
||||||
manufacturer='bar',
|
pc = d.Desktop(
|
||||||
serial_number='foo-bar',
|
chassis=ComputerChassis.Tower,
|
||||||
weight=2.8,
|
model='foo',
|
||||||
width=1.4,
|
manufacturer='bar',
|
||||||
height=2.1,
|
serial_number='foo-bar',
|
||||||
color=Color('LightSeaGreen'))
|
weight=2.8,
|
||||||
|
width=1.4,
|
||||||
|
height=2.1,
|
||||||
|
color=Color('LightSeaGreen'),
|
||||||
|
)
|
||||||
pc.components.add(c)
|
pc.components.add(c)
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -122,7 +138,7 @@ def test_physical_properties():
|
||||||
'manufacturer': 'mr',
|
'manufacturer': 'mr',
|
||||||
'bios_date': None,
|
'bios_date': None,
|
||||||
'ram_max_size': None,
|
'ram_max_size': None,
|
||||||
'ram_slots': None
|
'ram_slots': None,
|
||||||
}
|
}
|
||||||
assert pc.physical_properties == {
|
assert pc.physical_properties == {
|
||||||
'chassis': ComputerChassis.Tower,
|
'chassis': ComputerChassis.Tower,
|
||||||
|
@ -132,7 +148,7 @@ def test_physical_properties():
|
||||||
'receiver_id': None,
|
'receiver_id': None,
|
||||||
'serial_number': 'foo-bar',
|
'serial_number': 'foo-bar',
|
||||||
'part_number': None,
|
'part_number': None,
|
||||||
'transfer_state': TransferState.Initial
|
'transfer_state': TransferState.Initial,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,14 +158,19 @@ def test_component_similar_one():
|
||||||
user = User.query.filter().first()
|
user = User.query.filter().first()
|
||||||
snapshot = yaml2json('pc-components.db')
|
snapshot = yaml2json('pc-components.db')
|
||||||
pc = snapshot['device']
|
pc = snapshot['device']
|
||||||
snapshot['components'][0]['serial_number'] = snapshot['components'][1]['serial_number'] = None
|
snapshot['components'][0]['serial_number'] = snapshot['components'][1][
|
||||||
pc = d.Desktop(**pc, components=OrderedSet(d.Component(**c) for c in snapshot['components']))
|
'serial_number'
|
||||||
|
] = None
|
||||||
|
pc = d.Desktop(
|
||||||
|
**pc, components=OrderedSet(d.Component(**c) for c in snapshot['components'])
|
||||||
|
)
|
||||||
component1, component2 = pc.components # type: d.Component
|
component1, component2 = pc.components # type: d.Component
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
# Let's create a new component named 'A' similar to 1
|
# Let's create a new component named 'A' similar to 1
|
||||||
componentA = d.Component(model=component1.model, manufacturer=component1.manufacturer,
|
componentA = d.Component(
|
||||||
owner_id=user.id)
|
model=component1.model, manufacturer=component1.manufacturer, owner_id=user.id
|
||||||
|
)
|
||||||
similar_to_a = componentA.similar_one(pc, set())
|
similar_to_a = componentA.similar_one(pc, set())
|
||||||
assert similar_to_a == component1
|
assert similar_to_a == component1
|
||||||
# d.Component B does not have the same model
|
# d.Component B does not have the same model
|
||||||
|
@ -175,9 +196,11 @@ def test_add_remove():
|
||||||
pc = d.Desktop(**pc, components=OrderedSet([c1, c2]))
|
pc = d.Desktop(**pc, components=OrderedSet([c1, c2]))
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
c3 = d.Component(serial_number='nc1', owner_id=user.id)
|
c3 = d.Component(serial_number='nc1', owner_id=user.id)
|
||||||
pc2 = d.Desktop(serial_number='s2',
|
pc2 = d.Desktop(
|
||||||
components=OrderedSet([c3]),
|
serial_number='s2',
|
||||||
chassis=ComputerChassis.Microtower)
|
components=OrderedSet([c3]),
|
||||||
|
chassis=ComputerChassis.Microtower,
|
||||||
|
)
|
||||||
c4 = d.Component(serial_number='c4s', owner_id=user.id)
|
c4 = d.Component(serial_number='c4s', owner_id=user.id)
|
||||||
db.session.add(pc2)
|
db.session.add(pc2)
|
||||||
db.session.add(c4)
|
db.session.add(c4)
|
||||||
|
@ -201,7 +224,9 @@ def test_sync_run_components_empty():
|
||||||
remove all the components from the device.
|
remove all the components from the device.
|
||||||
"""
|
"""
|
||||||
s = yaml2json('pc-components.db')
|
s = yaml2json('pc-components.db')
|
||||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
pc = d.Desktop(
|
||||||
|
**s['device'], components=OrderedSet(d.Component(**c) for c in s['components'])
|
||||||
|
)
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
@ -219,7 +244,9 @@ def test_sync_run_components_none():
|
||||||
keep all the components from the device.
|
keep all the components from the device.
|
||||||
"""
|
"""
|
||||||
s = yaml2json('pc-components.db')
|
s = yaml2json('pc-components.db')
|
||||||
pc = d.Desktop(**s['device'], components=OrderedSet(d.Component(**c) for c in s['components']))
|
pc = d.Desktop(
|
||||||
|
**s['device'], components=OrderedSet(d.Component(**c) for c in s['components'])
|
||||||
|
)
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
@ -249,7 +276,8 @@ def test_sync_execute_register_desktop_existing_no_tag():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
pc = d.Desktop(
|
pc = d.Desktop(
|
||||||
**yaml2json('pc-components.db')['device']) # Create a new transient non-db object
|
**yaml2json('pc-components.db')['device']
|
||||||
|
) # Create a new transient non-db object
|
||||||
# 1: device exists on DB
|
# 1: device exists on DB
|
||||||
db_pc = Sync().execute_register(pc)
|
db_pc = Sync().execute_register(pc)
|
||||||
pc.amount = 0
|
pc.amount = 0
|
||||||
|
@ -285,7 +313,9 @@ def test_sync_execute_register_desktop_tag_not_linked():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
# Create a new transient non-db object
|
# Create a new transient non-db object
|
||||||
pc = d.Desktop(**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')]))
|
pc = d.Desktop(
|
||||||
|
**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')])
|
||||||
|
)
|
||||||
returned_pc = Sync().execute_register(pc)
|
returned_pc = Sync().execute_register(pc)
|
||||||
assert returned_pc == pc
|
assert returned_pc == pc
|
||||||
assert tag.device == pc, 'Tag has to be linked'
|
assert tag.device == pc, 'Tag has to be linked'
|
||||||
|
@ -326,7 +356,9 @@ def test_sync_execute_register_tag_does_not_exist():
|
||||||
Tags have to be created before trying to link them through a Snapshot.
|
Tags have to be created before trying to link them through a Snapshot.
|
||||||
"""
|
"""
|
||||||
user = User.query.filter().first()
|
user = User.query.filter().first()
|
||||||
pc = d.Desktop(**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag('foo')]))
|
pc = d.Desktop(
|
||||||
|
**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag('foo')])
|
||||||
|
)
|
||||||
pc.owner_id = user.id
|
pc.owner_id = user.id
|
||||||
with raises(ResourceNotFound):
|
with raises(ResourceNotFound):
|
||||||
Sync().execute_register(pc)
|
Sync().execute_register(pc)
|
||||||
|
@ -345,7 +377,8 @@ def test_sync_execute_register_tag_linked_same_device():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
pc = d.Desktop(
|
pc = d.Desktop(
|
||||||
**yaml2json('pc-components.db')['device']) # Create a new transient non-db object
|
**yaml2json('pc-components.db')['device']
|
||||||
|
) # Create a new transient non-db object
|
||||||
pc.tags.add(Tag(id='foo'))
|
pc.tags.add(Tag(id='foo'))
|
||||||
db_pc = Sync().execute_register(pc)
|
db_pc = Sync().execute_register(pc)
|
||||||
assert db_pc.id == orig_pc.id
|
assert db_pc.id == orig_pc.id
|
||||||
|
@ -369,7 +402,8 @@ def test_sync_execute_register_tag_linked_other_device_mismatch_between_tags():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
pc1 = d.Desktop(
|
pc1 = d.Desktop(
|
||||||
**yaml2json('pc-components.db')['device']) # Create a new transient non-db object
|
**yaml2json('pc-components.db')['device']
|
||||||
|
) # Create a new transient non-db object
|
||||||
pc1.tags.add(Tag(id='foo-1'))
|
pc1.tags.add(Tag(id='foo-1'))
|
||||||
pc1.tags.add(Tag(id='foo-2'))
|
pc1.tags.add(Tag(id='foo-2'))
|
||||||
with raises(MismatchBetweenTags):
|
with raises(MismatchBetweenTags):
|
||||||
|
@ -393,7 +427,8 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
pc1 = d.Desktop(
|
pc1 = d.Desktop(
|
||||||
**yaml2json('pc-components.db')['device']) # Create a new transient non-db object
|
**yaml2json('pc-components.db')['device']
|
||||||
|
) # Create a new transient non-db object
|
||||||
pc1.tags.add(Tag(id='foo-2'))
|
pc1.tags.add(Tag(id='foo-2'))
|
||||||
with raises(MismatchBetweenTagsAndHid):
|
with raises(MismatchBetweenTagsAndHid):
|
||||||
Sync().execute_register(pc1)
|
Sync().execute_register(pc1)
|
||||||
|
@ -404,22 +439,36 @@ def test_sync_execute_register_mismatch_between_tags_and_hid():
|
||||||
def test_get_device(user: UserClient):
|
def test_get_device(user: UserClient):
|
||||||
"""Checks GETting a d.Desktop with its components."""
|
"""Checks GETting a d.Desktop with its components."""
|
||||||
g.user = User.query.one()
|
g.user = User.query.one()
|
||||||
pc = d.Desktop(model='p1mo',
|
pc = d.Desktop(
|
||||||
manufacturer='p1ma',
|
model='p1mo',
|
||||||
serial_number='p1s',
|
manufacturer='p1ma',
|
||||||
chassis=ComputerChassis.Tower,
|
serial_number='p1s',
|
||||||
owner_id=user.user['id'])
|
chassis=ComputerChassis.Tower,
|
||||||
pc.components = OrderedSet([
|
owner_id=user.user['id'],
|
||||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s',
|
)
|
||||||
owner_id=user.user['id']),
|
pc.components = OrderedSet(
|
||||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500, owner_id=user.user['id'])
|
[
|
||||||
])
|
d.NetworkAdapter(
|
||||||
|
model='c1mo',
|
||||||
|
manufacturer='c1ma',
|
||||||
|
serial_number='c1s',
|
||||||
|
owner_id=user.user['id'],
|
||||||
|
),
|
||||||
|
d.GraphicCard(
|
||||||
|
model='c2mo', manufacturer='c2ma', memory=1500, owner_id=user.user['id']
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
db.session.add(pc)
|
db.session.add(pc)
|
||||||
# todo test is an abstract class. replace with another one
|
# todo test is an abstract class. replace with another one
|
||||||
db.session.add(TestConnectivity(device=pc,
|
db.session.add(
|
||||||
severity=Severity.Info,
|
TestConnectivity(
|
||||||
agent=Person(name='Timmy'),
|
device=pc,
|
||||||
author=User(email='bar@bar.com')))
|
severity=Severity.Info,
|
||||||
|
agent=Person(name='Timmy'),
|
||||||
|
author=User(email='bar@bar.com'),
|
||||||
|
)
|
||||||
|
)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
pc_api, _ = user.get(res=d.Device, item=pc.devicehub_id)
|
pc_api, _ = user.get(res=d.Device, item=pc.devicehub_id)
|
||||||
assert len(pc_api['actions']) == 1
|
assert len(pc_api['actions']) == 1
|
||||||
|
@ -427,10 +476,14 @@ def test_get_device(user: UserClient):
|
||||||
assert pc_api['actions'][0]['device'] == pc.id
|
assert pc_api['actions'][0]['device'] == pc.id
|
||||||
assert pc_api['actions'][0]['severity'] == 'Info'
|
assert pc_api['actions'][0]['severity'] == 'Info'
|
||||||
assert UUID(pc_api['actions'][0]['author'])
|
assert UUID(pc_api['actions'][0]['author'])
|
||||||
assert 'actions_components' not in pc_api, 'actions_components are internal use only'
|
assert (
|
||||||
|
'actions_components' not in pc_api
|
||||||
|
), 'actions_components are internal use only'
|
||||||
assert 'actions_one' not in pc_api, 'they are internal use only'
|
assert 'actions_one' not in pc_api, 'they are internal use only'
|
||||||
assert 'author' not in pc_api
|
assert 'author' not in pc_api
|
||||||
assert tuple(c['id'] for c in pc_api['components']) == tuple(c.id for c in pc.components)
|
assert tuple(c['id'] for c in pc_api['components']) == tuple(
|
||||||
|
c.id for c in pc.components
|
||||||
|
)
|
||||||
assert pc_api['hid'] == 'desktop-p1ma-p1mo-p1s'
|
assert pc_api['hid'] == 'desktop-p1ma-p1mo-p1s'
|
||||||
assert pc_api['model'] == 'p1mo'
|
assert pc_api['model'] == 'p1mo'
|
||||||
assert pc_api['manufacturer'] == 'p1ma'
|
assert pc_api['manufacturer'] == 'p1ma'
|
||||||
|
@ -443,41 +496,59 @@ def test_get_device(user: UserClient):
|
||||||
def test_get_devices(app: Devicehub, user: UserClient):
|
def test_get_devices(app: Devicehub, user: UserClient):
|
||||||
"""Checks GETting multiple devices."""
|
"""Checks GETting multiple devices."""
|
||||||
g.user = User.query.one()
|
g.user = User.query.one()
|
||||||
pc = d.Desktop(model='p1mo',
|
pc = d.Desktop(
|
||||||
manufacturer='p1ma',
|
model='p1mo',
|
||||||
serial_number='p1s',
|
manufacturer='p1ma',
|
||||||
chassis=ComputerChassis.Tower,
|
serial_number='p1s',
|
||||||
owner_id=user.user['id'])
|
chassis=ComputerChassis.Tower,
|
||||||
pc.components = OrderedSet([
|
owner_id=user.user['id'],
|
||||||
d.NetworkAdapter(model='c1mo', manufacturer='c1ma', serial_number='c1s',
|
)
|
||||||
owner_id=user.user['id']),
|
pc.components = OrderedSet(
|
||||||
d.GraphicCard(model='c2mo', manufacturer='c2ma', memory=1500,
|
[
|
||||||
owner_id=user.user['id'])
|
d.NetworkAdapter(
|
||||||
])
|
model='c1mo',
|
||||||
pc1 = d.Desktop(model='p2mo',
|
manufacturer='c1ma',
|
||||||
manufacturer='p2ma',
|
serial_number='c1s',
|
||||||
serial_number='p2s',
|
owner_id=user.user['id'],
|
||||||
chassis=ComputerChassis.Tower,
|
),
|
||||||
owner_id=user.user['id'])
|
d.GraphicCard(
|
||||||
pc2 = d.Laptop(model='p3mo',
|
model='c2mo', manufacturer='c2ma', memory=1500, owner_id=user.user['id']
|
||||||
manufacturer='p3ma',
|
),
|
||||||
serial_number='p3s',
|
]
|
||||||
chassis=ComputerChassis.Netbook,
|
)
|
||||||
owner_id=user.user['id'])
|
pc1 = d.Desktop(
|
||||||
|
model='p2mo',
|
||||||
|
manufacturer='p2ma',
|
||||||
|
serial_number='p2s',
|
||||||
|
chassis=ComputerChassis.Tower,
|
||||||
|
owner_id=user.user['id'],
|
||||||
|
)
|
||||||
|
pc2 = d.Laptop(
|
||||||
|
model='p3mo',
|
||||||
|
manufacturer='p3ma',
|
||||||
|
serial_number='p3s',
|
||||||
|
chassis=ComputerChassis.Netbook,
|
||||||
|
owner_id=user.user['id'],
|
||||||
|
)
|
||||||
db.session.add_all((pc, pc1, pc2))
|
db.session.add_all((pc, pc1, pc2))
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
devices, _ = user.get(res=d.Device)
|
devices, _ = user.get(res=d.Device)
|
||||||
ids = (pc.id, pc1.id, pc2.id, pc.components[0].id, pc.components[1].id)
|
ids = (pc.id, pc1.id, pc2.id, pc.components[0].id, pc.components[1].id)
|
||||||
assert tuple(dev['id'] for dev in devices['items']) == ids
|
assert tuple(dev['id'] for dev in devices['items']) == ids
|
||||||
assert tuple(dev['type'] for dev in devices['items']) == (
|
assert tuple(dev['type'] for dev in devices['items']) == (
|
||||||
d.Desktop.t, d.Desktop.t, d.Laptop.t, d.NetworkAdapter.t, d.GraphicCard.t
|
d.Desktop.t,
|
||||||
|
d.Desktop.t,
|
||||||
|
d.Laptop.t,
|
||||||
|
d.NetworkAdapter.t,
|
||||||
|
d.GraphicCard.t,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_get_device_permissions(app: Devicehub, user: UserClient, user2: UserClient,
|
def test_get_device_permissions(
|
||||||
client: Client):
|
app: Devicehub, user: UserClient, user2: UserClient, client: Client
|
||||||
|
):
|
||||||
"""Checks GETting a d.Desktop with its components."""
|
"""Checks GETting a d.Desktop with its components."""
|
||||||
|
|
||||||
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
s, _ = user.post(file('asus-eee-1000h.snapshot.11'), res=m.Snapshot)
|
||||||
|
@ -529,12 +600,12 @@ def test_get_devices_unassigned(user: UserClient):
|
||||||
assert len(devices['items']) == 2
|
assert len(devices['items']) == 2
|
||||||
|
|
||||||
from ereuse_devicehub.resources.lot.models import Lot
|
from ereuse_devicehub.resources.lot.models import Lot
|
||||||
|
|
||||||
device_id = devices['items'][0]['id']
|
device_id = devices['items'][0]['id']
|
||||||
my_lot, _ = user.post(({'name': 'My_lot'}), res=Lot)
|
my_lot, _ = user.post(({'name': 'My_lot'}), res=Lot)
|
||||||
lot, _ = user.post({},
|
lot, _ = user.post(
|
||||||
res=Lot,
|
{}, res=Lot, item='{}/devices'.format(my_lot['id']), query=[('id', device_id)]
|
||||||
item='{}/devices'.format(my_lot['id']),
|
)
|
||||||
query=[('id', device_id)])
|
|
||||||
lot = Lot.query.filter_by(id=lot['id']).one()
|
lot = Lot.query.filter_by(id=lot['id']).one()
|
||||||
assert next(iter(lot.devices)).id == device_id
|
assert next(iter(lot.devices)).id == device_id
|
||||||
|
|
||||||
|
@ -554,13 +625,15 @@ def test_get_devices_unassigned(user: UserClient):
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||||
def test_computer_monitor():
|
def test_computer_monitor():
|
||||||
m = d.ComputerMonitor(technology=DisplayTech.LCD,
|
m = d.ComputerMonitor(
|
||||||
manufacturer='foo',
|
technology=DisplayTech.LCD,
|
||||||
model='bar',
|
manufacturer='foo',
|
||||||
serial_number='foo-bar',
|
model='bar',
|
||||||
resolution_width=1920,
|
serial_number='foo-bar',
|
||||||
resolution_height=1080,
|
resolution_width=1920,
|
||||||
size=14.5)
|
resolution_height=1080,
|
||||||
|
size=14.5,
|
||||||
|
)
|
||||||
db.session.add(m)
|
db.session.add(m)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
@ -568,9 +641,11 @@ def test_computer_monitor():
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_manufacturer(user: UserClient):
|
def test_manufacturer(user: UserClient):
|
||||||
m, r = user.get(res='Manufacturer', query=[('search', 'asus')])
|
m, r = user.get(res='Manufacturer', query=[('search', 'asus')])
|
||||||
assert m == {'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]}
|
assert m == {
|
||||||
|
'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]
|
||||||
|
}
|
||||||
assert r.cache_control.public
|
assert r.cache_control.public
|
||||||
assert r.expires > datetime.datetime.now()
|
assert r.expires.timestamp() > datetime.datetime.now().timestamp()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -591,12 +666,20 @@ def test_device_properties_format(app: Devicehub, user: UserClient):
|
||||||
assert format(pc, 's') == '(asustek computer inc.) S/N 94OAAQ021116'
|
assert format(pc, 's') == '(asustek computer inc.) S/N 94OAAQ021116'
|
||||||
assert pc.ram_size == 1024
|
assert pc.ram_size == 1024
|
||||||
assert pc.data_storage_size == 152627
|
assert pc.data_storage_size == 152627
|
||||||
assert pc.graphic_card_model == 'mobile 945gse express integrated graphics controller'
|
assert (
|
||||||
|
pc.graphic_card_model
|
||||||
|
== 'mobile 945gse express integrated graphics controller'
|
||||||
|
)
|
||||||
assert pc.processor_model == 'intel atom cpu n270 @ 1.60ghz'
|
assert pc.processor_model == 'intel atom cpu n270 @ 1.60ghz'
|
||||||
net = next(c for c in pc.components if isinstance(c, d.NetworkAdapter))
|
net = next(c for c in pc.components if isinstance(c, d.NetworkAdapter))
|
||||||
assert format(net) == 'NetworkAdapter 5: model ar8121/ar8113/ar8114 ' \
|
assert (
|
||||||
'gigabit or fast ethernet, S/N 00:24:8c:7f:cf:2d'
|
format(net) == 'NetworkAdapter 5: model ar8121/ar8113/ar8114 '
|
||||||
assert format(net, 't') == 'NetworkAdapter ar8121/ar8113/ar8114 gigabit or fast ethernet'
|
'gigabit or fast ethernet, S/N 00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
format(net, 't')
|
||||||
|
== 'NetworkAdapter ar8121/ar8113/ar8114 gigabit or fast ethernet'
|
||||||
|
)
|
||||||
assert format(net, 's') == 'qualcomm atheros 00:24:8C:7F:CF:2D – 100 Mbps'
|
assert format(net, 's') == 'qualcomm atheros 00:24:8C:7F:CF:2D – 100 Mbps'
|
||||||
hdd = next(c for c in pc.components if isinstance(c, d.DataStorage))
|
hdd = next(c for c in pc.components if isinstance(c, d.DataStorage))
|
||||||
assert format(hdd) == 'HardDrive 10: model st9160310as, S/N 5sv4tqa6'
|
assert format(hdd) == 'HardDrive 10: model st9160310as, S/N 5sv4tqa6'
|
||||||
|
@ -638,8 +721,12 @@ def test_networking_model(user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_cooking_mixer(user: UserClient):
|
def test_cooking_mixer(user: UserClient):
|
||||||
mixer = d.Mixer(serial_number='foo', model='bar', manufacturer='foobar',
|
mixer = d.Mixer(
|
||||||
owner_id=user.user['id'])
|
serial_number='foo',
|
||||||
|
model='bar',
|
||||||
|
manufacturer='foobar',
|
||||||
|
owner_id=user.user['id'],
|
||||||
|
)
|
||||||
db.session.add(mixer)
|
db.session.add(mixer)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
@ -652,12 +739,12 @@ def test_cooking_mixer_api(user: UserClient):
|
||||||
'serialNumber': 'foo',
|
'serialNumber': 'foo',
|
||||||
'model': 'bar',
|
'model': 'bar',
|
||||||
'manufacturer': 'foobar',
|
'manufacturer': 'foobar',
|
||||||
'type': 'Mixer'
|
'type': 'Mixer',
|
||||||
},
|
},
|
||||||
'version': '11.0',
|
'version': '11.0',
|
||||||
'software': SnapshotSoftware.Web.name
|
'software': SnapshotSoftware.Web.name,
|
||||||
},
|
},
|
||||||
res=m.Snapshot
|
res=m.Snapshot,
|
||||||
)
|
)
|
||||||
mixer, _ = user.get(res=d.Device, item=snapshot['device']['id'])
|
mixer, _ = user.get(res=d.Device, item=snapshot['device']['id'])
|
||||||
assert mixer['type'] == 'Mixer'
|
assert mixer['type'] == 'Mixer'
|
||||||
|
@ -673,14 +760,19 @@ def test_hid_with_mac(app: Devicehub, user: UserClient):
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert (
|
||||||
|
pc.placeholder.binding.hid
|
||||||
|
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_hid_without_mac(app: Devicehub, user: UserClient):
|
def test_hid_without_mac(app: Devicehub, user: UserClient):
|
||||||
"""Checks hid without mac."""
|
"""Checks hid without mac."""
|
||||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||||
snapshot['components'] = [c for c in snapshot['components'] if c['type'] != 'NetworkAdapter']
|
snapshot['components'] = [
|
||||||
|
c for c in snapshot['components'] if c['type'] != 'NetworkAdapter'
|
||||||
|
]
|
||||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
|
@ -709,7 +801,10 @@ def test_hid_with_2networkadapters(app: Devicehub, user: UserClient):
|
||||||
devices, _ = user.get(res=d.Device)
|
devices, _ = user.get(res=d.Device)
|
||||||
|
|
||||||
laptop = devices['items'][0]
|
laptop = devices['items'][0]
|
||||||
assert laptop['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert (
|
||||||
|
laptop['hid']
|
||||||
|
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@ -726,14 +821,20 @@ def test_hid_with_2network_and_drop_no_mac_in_hid(app: Devicehub, user: UserClie
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert (
|
||||||
|
pc.placeholder.binding.hid
|
||||||
|
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
|
|
||||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||||
snapshot['components'] = [c for c in snapshot['components'] if c != network]
|
snapshot['components'] = [c for c in snapshot['components'] if c != network]
|
||||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
devices, _ = user.get(res=d.Device)
|
devices, _ = user.get(res=d.Device)
|
||||||
laptop = devices['items'][0]
|
laptop = devices['items'][0]
|
||||||
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert (
|
||||||
|
pc.placeholder.binding.hid
|
||||||
|
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
||||||
assert len([c for c in laptop['components'] if c['type'] == 'NetworkAdapter']) == 1
|
assert len([c for c in laptop['components'] if c['type'] == 'NetworkAdapter']) == 1
|
||||||
|
|
||||||
|
@ -752,7 +853,10 @@ def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient)
|
||||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||||
assert pc.placeholder.binding.hid == 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
assert (
|
||||||
|
pc.placeholder.binding.hid
|
||||||
|
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||||
|
)
|
||||||
|
|
||||||
# we drop the network card then is used for to build the hid
|
# we drop the network card then is used for to build the hid
|
||||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||||
|
@ -762,19 +866,25 @@ def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient)
|
||||||
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
||||||
assert len(laptops) == 4
|
assert len(laptops) == 4
|
||||||
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
||||||
proof_hid = ['laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
proof_hid = [
|
||||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d']
|
'laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
||||||
|
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d',
|
||||||
|
]
|
||||||
assert all([h in proof_hid for h in hids])
|
assert all([h in proof_hid for h in hids])
|
||||||
|
|
||||||
# we drop all network cards
|
# we drop all network cards
|
||||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abc'
|
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abc'
|
||||||
snapshot['components'] = [c for c in snapshot['components'] if c not in [network, network2]]
|
snapshot['components'] = [
|
||||||
|
c for c in snapshot['components'] if c not in [network, network2]
|
||||||
|
]
|
||||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||||
devices, _ = user.get(res=d.Device)
|
devices, _ = user.get(res=d.Device)
|
||||||
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
||||||
assert len(laptops) == 4
|
assert len(laptops) == 4
|
||||||
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
||||||
proof_hid = ['laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
proof_hid = [
|
||||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d',
|
'laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
||||||
'laptop-asustek_computer_inc-1000h-94oaaq021116']
|
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d',
|
||||||
|
'laptop-asustek_computer_inc-1000h-94oaaq021116',
|
||||||
|
]
|
||||||
assert all([h in proof_hid for h in hids])
|
assert all([h in proof_hid for h in hids])
|
||||||
|
|
|
@ -21,10 +21,12 @@ from tests.conftest import TestConfig
|
||||||
class NoExcCliRunner(click.testing.CliRunner):
|
class NoExcCliRunner(click.testing.CliRunner):
|
||||||
"""Runner that interfaces with the Devicehub CLI."""
|
"""Runner that interfaces with the Devicehub CLI."""
|
||||||
|
|
||||||
def invoke(self, *args, input=None, env=None, catch_exceptions=False, color=False,
|
def invoke(
|
||||||
**extra):
|
self, *args, input=None, env=None, catch_exceptions=False, color=False, **extra
|
||||||
r = super().invoke(ereuse_devicehub.cli.cli,
|
):
|
||||||
args, input, env, catch_exceptions, color, **extra)
|
r = super().invoke(
|
||||||
|
ereuse_devicehub.cli.cli, args, input, env, catch_exceptions, color, **extra
|
||||||
|
)
|
||||||
assert r.exit_code == 0, 'CLI code {}: {}'.format(r.exit_code, r.output)
|
assert r.exit_code == 0, 'CLI code {}: {}'.format(r.exit_code, r.output)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
@ -69,16 +71,26 @@ def test_inventory_create_delete_user(cli, tdb1, tdb2):
|
||||||
"""
|
"""
|
||||||
# Create first DB
|
# Create first DB
|
||||||
cli.inv('tdb1')
|
cli.inv('tdb1')
|
||||||
cli.invoke('inv', 'add',
|
cli.invoke(
|
||||||
'-n', 'Test DB1',
|
'inv',
|
||||||
'-on', 'ACME DB1',
|
'add',
|
||||||
'-oi', 'acme-id',
|
'-n',
|
||||||
'-tu', 'https://example.com',
|
'Test DB1',
|
||||||
'-tt', '3c66a6ad-22de-4db6-ac46-d8982522ec40',
|
'-on',
|
||||||
'--common')
|
'ACME DB1',
|
||||||
|
'-oi',
|
||||||
|
'acme-id',
|
||||||
|
'-tu',
|
||||||
|
'https://example.com',
|
||||||
|
'-tt',
|
||||||
|
'3c66a6ad-22de-4db6-ac46-d8982522ec40',
|
||||||
|
'--common',
|
||||||
|
)
|
||||||
|
|
||||||
# Create an user for first DB
|
# Create an user for first DB
|
||||||
cli.invoke('user', 'add', 'foo@foo.com', '-a', 'Foo', '-c', 'ES', '-p', 'Such password')
|
cli.invoke(
|
||||||
|
'user', 'add', 'foo@foo.com', '-a', 'Foo', '-c', 'ES', '-p', 'Such password'
|
||||||
|
)
|
||||||
|
|
||||||
with tdb1.app_context():
|
with tdb1.app_context():
|
||||||
# There is a row for the inventory
|
# There is a row for the inventory
|
||||||
|
@ -98,12 +110,20 @@ def test_inventory_create_delete_user(cli, tdb1, tdb2):
|
||||||
cli.inv('tdb2')
|
cli.inv('tdb2')
|
||||||
# Create a second DB
|
# Create a second DB
|
||||||
# Note how we don't create common anymore
|
# Note how we don't create common anymore
|
||||||
cli.invoke('inv', 'add',
|
cli.invoke(
|
||||||
'-n', 'Test DB2',
|
'inv',
|
||||||
'-on', 'ACME DB2',
|
'add',
|
||||||
'-oi', 'acme-id-2',
|
'-n',
|
||||||
'-tu', 'https://example.com',
|
'Test DB2',
|
||||||
'-tt', 'fbad1c08-ffdc-4a61-be49-464962c186a8')
|
'-on',
|
||||||
|
'ACME DB2',
|
||||||
|
'-oi',
|
||||||
|
'acme-id-2',
|
||||||
|
'-tu',
|
||||||
|
'https://example.com',
|
||||||
|
'-tt',
|
||||||
|
'fbad1c08-ffdc-4a61-be49-464962c186a8',
|
||||||
|
)
|
||||||
# Create an user for with access for both DB
|
# Create an user for with access for both DB
|
||||||
cli.invoke('user', 'add', 'bar@bar.com', '-a', 'Bar', '-p', 'Wow password')
|
cli.invoke('user', 'add', 'bar@bar.com', '-a', 'Bar', '-p', 'Wow password')
|
||||||
|
|
||||||
|
@ -144,5 +164,6 @@ def test_create_existing_inventory(cli, tdb1):
|
||||||
cli.invoke('inv', 'add', '--common')
|
cli.invoke('inv', 'add', '--common')
|
||||||
with tdb1.app_context():
|
with tdb1.app_context():
|
||||||
assert db.has_schema('tdb1')
|
assert db.has_schema('tdb1')
|
||||||
with pytest.raises(AssertionError, message='Schema tdb1 already exists.'):
|
with pytest.raises(AssertionError):
|
||||||
cli.invoke('inv', 'add', '--common')
|
cli.invoke('inv', 'add', '--common')
|
||||||
|
pytest.fail('Schema tdb1 already exists.')
|
||||||
|
|
|
@ -356,7 +356,6 @@ def test_label_details(user3: UserClientFlask):
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
|
|
||||||
body, status = user3.get('/labels/tag1/')
|
body, status = user3.get('/labels/tag1/')
|
||||||
assert "tag1" in body
|
|
||||||
assert "Print Label" in body
|
assert "Print Label" in body
|
||||||
|
|
||||||
|
|
||||||
|
@ -562,7 +561,6 @@ def test_update_monitor(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Monitor",
|
'type': "Monitor",
|
||||||
'phid': '1',
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
'model': "LCD 43 b",
|
'model': "LCD 43 b",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
|
@ -575,8 +573,9 @@ def test_update_monitor(user3: UserClientFlask):
|
||||||
}
|
}
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'Error, exist one Placeholder device with this PHID' in body
|
# assert 'Error, exist one Placeholder device with this PHID' in body
|
||||||
dev = Device.query.one()
|
dev = Device.query.all()[0]
|
||||||
|
assert Device.query.count() == 2
|
||||||
assert dev.type == 'Monitor'
|
assert dev.type == 'Monitor'
|
||||||
assert dev.placeholder.id_device_supplier == "b2"
|
assert dev.placeholder.id_device_supplier == "b2"
|
||||||
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
|
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
|
||||||
|
@ -597,7 +596,6 @@ def test_add_2_monitor(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Monitor",
|
'type': "Monitor",
|
||||||
'phid': "AAB",
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
|
@ -619,7 +617,7 @@ def test_add_2_monitor(user3: UserClientFlask):
|
||||||
assert typ == 'Monitor'
|
assert typ == 'Monitor'
|
||||||
assert dev.placeholder.id_device_supplier == "b1"
|
assert dev.placeholder.id_device_supplier == "b1"
|
||||||
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
|
assert dev.hid == 'monitor-samsung-lc27t55-aaaab'
|
||||||
assert phid == 'AAB'
|
assert phid == '1'
|
||||||
assert dhid == 'O48N2'
|
assert dhid == 'O48N2'
|
||||||
assert dev.model == 'lc27t55'
|
assert dev.model == 'lc27t55'
|
||||||
assert dev.placeholder.pallet == "l34"
|
assert dev.placeholder.pallet == "l34"
|
||||||
|
@ -737,35 +735,6 @@ def test_add_with_ammount_laptops(user3: UserClientFlask):
|
||||||
assert Device.query.count() == num
|
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.mvp
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_filter_monitor(user3: UserClientFlask):
|
def test_filter_monitor(user3: UserClientFlask):
|
||||||
|
@ -1405,6 +1374,7 @@ def test_wb_settings_register(user3: UserClientFlask):
|
||||||
def test_create_transfer(user3: UserClientFlask):
|
def test_create_transfer(user3: UserClientFlask):
|
||||||
user3.get('/inventory/lot/add/')
|
user3.get('/inventory/lot/add/')
|
||||||
lot_name = 'lot1'
|
lot_name = 'lot1'
|
||||||
|
lot_name2 = 'lot2'
|
||||||
data = {
|
data = {
|
||||||
'name': lot_name,
|
'name': lot_name,
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
|
@ -1421,13 +1391,14 @@ def test_create_transfer(user3: UserClientFlask):
|
||||||
assert 'Description' in body
|
assert 'Description' in body
|
||||||
assert 'Save' in body
|
assert 'Save' in body
|
||||||
|
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name2}
|
||||||
|
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'Transfer created successfully!' in body
|
assert 'Transfer created successfully!' in body
|
||||||
assert 'Delete Lot' in body
|
assert 'Delete Lot' in body
|
||||||
assert 'Incoming Lot' in body
|
assert 'Incoming Lot' in body
|
||||||
|
assert lot_name2 in body
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -1436,6 +1407,8 @@ def test_edit_transfer(user3: UserClientFlask):
|
||||||
# create lot
|
# create lot
|
||||||
user3.get('/inventory/lot/add/')
|
user3.get('/inventory/lot/add/')
|
||||||
lot_name = 'lot1'
|
lot_name = 'lot1'
|
||||||
|
lot_name2 = 'lot2'
|
||||||
|
lot_name3 = 'lot3'
|
||||||
data = {
|
data = {
|
||||||
'name': lot_name,
|
'name': lot_name,
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
|
@ -1453,12 +1426,13 @@ def test_edit_transfer(user3: UserClientFlask):
|
||||||
|
|
||||||
# create new incoming lot
|
# create new incoming lot
|
||||||
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name2}
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
assert 'Transfer (<span class="text-success">Open</span>)' in body
|
assert 'Transfer (<span class="text-success">Open</span>)' in body
|
||||||
assert '<i class="bi bi-trash"></i> Delete Lot' in body
|
assert '<i class="bi bi-trash"></i> Delete Lot' in body
|
||||||
lot = Lot.query.filter()[1]
|
lot = Lot.query.filter()[1]
|
||||||
assert lot.transfer is not None
|
assert lot.transfer is not None
|
||||||
|
assert lot_name2 in body
|
||||||
|
|
||||||
# edit transfer with errors
|
# edit transfer with errors
|
||||||
lot_id = lot.id
|
lot_id = lot.id
|
||||||
|
@ -1467,6 +1441,7 @@ def test_edit_transfer(user3: UserClientFlask):
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'code': 'AAA',
|
'code': 'AAA',
|
||||||
'description': 'one one one',
|
'description': 'one one one',
|
||||||
|
'lot_name': lot_name3,
|
||||||
'date': datetime.datetime.now().date() + datetime.timedelta(15),
|
'date': datetime.datetime.now().date() + datetime.timedelta(15),
|
||||||
}
|
}
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
|
@ -1481,6 +1456,7 @@ def test_edit_transfer(user3: UserClientFlask):
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'code': 'AAA',
|
'code': 'AAA',
|
||||||
'description': 'one one one',
|
'description': 'one one one',
|
||||||
|
'lot_name': lot_name3,
|
||||||
'date': datetime.datetime.now().date() - datetime.timedelta(15),
|
'date': datetime.datetime.now().date() - datetime.timedelta(15),
|
||||||
}
|
}
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
|
@ -1489,6 +1465,7 @@ def test_edit_transfer(user3: UserClientFlask):
|
||||||
assert 'one one one' in body
|
assert 'one one one' in body
|
||||||
assert '<i class="bi bi-trash"></i> Delete Lot' not in body
|
assert '<i class="bi bi-trash"></i> Delete Lot' not in body
|
||||||
assert 'Transfer (<span class="text-danger">Closed</span>)' in body
|
assert 'Transfer (<span class="text-danger">Closed</span>)' in body
|
||||||
|
assert lot_name3 in body
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -1507,7 +1484,7 @@ def test_edit_deliverynote(user3: UserClientFlask):
|
||||||
|
|
||||||
# create new incoming lot
|
# create new incoming lot
|
||||||
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name}
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
lot = Lot.query.filter()[1]
|
lot = Lot.query.filter()[1]
|
||||||
lot_id = lot.id
|
lot_id = lot.id
|
||||||
|
@ -1548,7 +1525,7 @@ def test_edit_receivernote(user3: UserClientFlask):
|
||||||
|
|
||||||
# create new incoming lot
|
# create new incoming lot
|
||||||
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name}
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
lot = Lot.query.filter()[1]
|
lot = Lot.query.filter()[1]
|
||||||
lot_id = lot.id
|
lot_id = lot.id
|
||||||
|
@ -1589,7 +1566,7 @@ def test_edit_notes_with_closed_transfer(user3: UserClientFlask):
|
||||||
|
|
||||||
# create new incoming lot
|
# create new incoming lot
|
||||||
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name}
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
lot = Lot.query.filter()[1]
|
lot = Lot.query.filter()[1]
|
||||||
lot_id = lot.id
|
lot_id = lot.id
|
||||||
|
@ -1698,6 +1675,7 @@ def test_export_lots(user3: UserClientFlask):
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
def test_export_snapshot_json(user3: UserClientFlask):
|
def test_export_snapshot_json(user3: UserClientFlask):
|
||||||
|
# ??
|
||||||
file_name = 'real-eee-1001pxd.snapshot.13.json'
|
file_name = 'real-eee-1001pxd.snapshot.13.json'
|
||||||
snap = create_device(user3, file_name)
|
snap = create_device(user3, file_name)
|
||||||
|
|
||||||
|
@ -1729,7 +1707,7 @@ def test_add_placeholder_excel(user3: UserClientFlask):
|
||||||
assert Device.query.count() == 3
|
assert Device.query.count() == 3
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
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.info == 'Good conditions'
|
||||||
assert dev.placeholder.pallet == '24A'
|
assert dev.placeholder.pallet == '24A'
|
||||||
assert dev.placeholder.id_device_supplier == 'TTT'
|
assert dev.placeholder.id_device_supplier == 'TTT'
|
||||||
|
@ -1755,7 +1733,7 @@ def test_add_placeholder_csv(user3: UserClientFlask):
|
||||||
assert Device.query.count() == 3
|
assert Device.query.count() == 3
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
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.info == 'Good conditions'
|
||||||
assert dev.placeholder.pallet == '24A'
|
assert dev.placeholder.pallet == '24A'
|
||||||
assert dev.placeholder.id_device_supplier == 'TTT'
|
assert dev.placeholder.id_device_supplier == 'TTT'
|
||||||
|
@ -1781,7 +1759,7 @@ def test_add_placeholder_ods(user3: UserClientFlask):
|
||||||
assert Device.query.count() == 3
|
assert Device.query.count() == 3
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
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.info == 'Good conditions'
|
||||||
assert dev.placeholder.pallet == '24A'
|
assert dev.placeholder.pallet == '24A'
|
||||||
assert dev.placeholder.id_device_supplier == 'TTT'
|
assert dev.placeholder.id_device_supplier == 'TTT'
|
||||||
|
@ -1809,10 +1787,11 @@ def test_add_placeholder_office_open_xml(user3: UserClientFlask):
|
||||||
assert Device.query.count() == 3
|
assert Device.query.count() == 3
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
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.info == 'Good conditions'
|
||||||
assert dev.placeholder.pallet == '24A'
|
assert dev.placeholder.pallet == '24A'
|
||||||
assert dev.placeholder.id_device_supplier == 'TTT'
|
assert dev.placeholder.id_device_supplier == 'TTT'
|
||||||
|
assert dev.placeholder.id_device_internal == 'AA'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -1921,8 +1900,8 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Laptop",
|
'type': "Laptop",
|
||||||
'phid': 'ace',
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
|
'part_number': "AAAAB",
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
'generation': 1,
|
'generation': 1,
|
||||||
|
@ -1930,9 +1909,13 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
|
||||||
'height': 0.1,
|
'height': 0.1,
|
||||||
'depth': 0.1,
|
'depth': 0.1,
|
||||||
'id_device_supplier': "b2",
|
'id_device_supplier': "b2",
|
||||||
|
'id_device_internal': "b2i",
|
||||||
}
|
}
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
dev = Device.query.one()
|
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)
|
uri = '/inventory/device/edit/{}/'.format(dev.devicehub_id)
|
||||||
user3.get(uri)
|
user3.get(uri)
|
||||||
|
@ -1948,16 +1931,20 @@ def test_placeholder_log_manual_edit(user3: UserClientFlask):
|
||||||
'height': 0.1,
|
'height': 0.1,
|
||||||
'depth': 0.1,
|
'depth': 0.1,
|
||||||
'id_device_supplier': "a2",
|
'id_device_supplier': "a2",
|
||||||
|
'id_device_internal': "a2i",
|
||||||
}
|
}
|
||||||
user3.post(uri, data=data)
|
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/'
|
uri = '/inventory/placeholder-logs/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert "Placeholder Logs" in body
|
assert "Placeholder Logs" in body
|
||||||
assert "Web form" in body
|
|
||||||
assert "ace" in body
|
|
||||||
assert "Update" in body
|
assert "Update" in body
|
||||||
|
assert "Web form" in body
|
||||||
|
assert "1" in body
|
||||||
assert dev.devicehub_id in body
|
assert dev.devicehub_id in body
|
||||||
assert "✓" in body
|
assert "✓" in body
|
||||||
assert "CSV" not in body
|
assert "CSV" not in body
|
||||||
|
@ -1980,7 +1967,7 @@ def test_placeholder_log_excel_new(user3: UserClientFlask):
|
||||||
}
|
}
|
||||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.placeholder.phid == 'a123'
|
assert dev.placeholder.phid == '1'
|
||||||
|
|
||||||
uri = '/inventory/placeholder-logs/'
|
uri = '/inventory/placeholder-logs/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
|
@ -1989,7 +1976,6 @@ def test_placeholder_log_excel_new(user3: UserClientFlask):
|
||||||
assert dev.placeholder.phid in body
|
assert dev.placeholder.phid in body
|
||||||
assert dev.devicehub_id in body
|
assert dev.devicehub_id in body
|
||||||
assert "Web form" not in body
|
assert "Web form" not in body
|
||||||
assert "Update" not in body
|
|
||||||
assert "New device" in body
|
assert "New device" in body
|
||||||
assert "✓" in body
|
assert "✓" in body
|
||||||
assert "CSV" not in body
|
assert "CSV" not in body
|
||||||
|
@ -2023,7 +2009,7 @@ def test_placeholder_log_excel_update(user3: UserClientFlask):
|
||||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||||
|
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.placeholder.phid == 'a123'
|
assert dev.placeholder.phid == '1'
|
||||||
|
|
||||||
uri = '/inventory/placeholder-logs/'
|
uri = '/inventory/placeholder-logs/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
|
@ -2032,7 +2018,6 @@ def test_placeholder_log_excel_update(user3: UserClientFlask):
|
||||||
assert dev.placeholder.phid in body
|
assert dev.placeholder.phid in body
|
||||||
assert dev.devicehub_id in body
|
assert dev.devicehub_id in body
|
||||||
assert "Web form" not in body
|
assert "Web form" not in body
|
||||||
assert "Update" in body
|
|
||||||
assert "New device" in body
|
assert "New device" in body
|
||||||
assert "✓" in body
|
assert "✓" in body
|
||||||
assert "CSV" in body
|
assert "CSV" in body
|
||||||
|
@ -2070,7 +2055,7 @@ def test_add_placeholder_excel_from_lot(user3: UserClientFlask):
|
||||||
assert Device.query.count() == 3
|
assert Device.query.count() == 3
|
||||||
dev = Device.query.first()
|
dev = Device.query.first()
|
||||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
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.info == 'Good conditions'
|
||||||
assert dev.placeholder.pallet == '24A'
|
assert dev.placeholder.pallet == '24A'
|
||||||
assert dev.placeholder.id_device_supplier == 'TTT'
|
assert dev.placeholder.id_device_supplier == 'TTT'
|
||||||
|
@ -2097,7 +2082,6 @@ def test_add_new_placeholder_from_lot(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Laptop",
|
'type': "Laptop",
|
||||||
'phid': 'ace',
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
|
@ -2110,7 +2094,7 @@ def test_add_new_placeholder_from_lot(user3: UserClientFlask):
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
dev = Device.query.one()
|
dev = Device.query.one()
|
||||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||||
assert dev.placeholder.phid == 'ace'
|
assert dev.placeholder.phid == '1'
|
||||||
assert len(lot.devices) == 1
|
assert len(lot.devices) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -2124,7 +2108,6 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Laptop",
|
'type': "Laptop",
|
||||||
'phid': 'sid',
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
|
@ -2136,7 +2119,7 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
dev = Device.query.one()
|
dev = Device.query.one()
|
||||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||||
assert dev.placeholder.phid == 'sid'
|
assert dev.placeholder.phid == '1'
|
||||||
assert dev.placeholder.is_abstract is False
|
assert dev.placeholder.is_abstract is False
|
||||||
|
|
||||||
# add device from wb
|
# add device from wb
|
||||||
|
@ -2155,7 +2138,7 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
|
|
||||||
# page binding
|
# page binding
|
||||||
dhid = dev_wb.dhid
|
dhid = dev_wb.dhid
|
||||||
uri = f'/inventory/binding/{dhid}/sid/'
|
uri = f'/inventory/binding/{dhid}/1/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'sid' in body
|
assert 'sid' in body
|
||||||
|
@ -2174,11 +2157,18 @@ def test_manual_binding(user3: UserClientFlask):
|
||||||
assert txt in body
|
assert txt in body
|
||||||
|
|
||||||
# check new structure
|
# check new structure
|
||||||
assert dev_wb.binding.phid == 'sid'
|
assert dev_wb.binding.phid == '1'
|
||||||
assert dev_wb.binding.device == dev
|
assert dev_wb.binding.device == dev
|
||||||
|
assert dev_wb.phid() == dev.phid()
|
||||||
|
assert dev_wb.is_abstract() == dev.is_abstract() == 'Twin'
|
||||||
|
# assert dev_wb.
|
||||||
assert Placeholder.query.filter_by(id=old_placeholder.id).first() is None
|
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
|
assert Device.query.filter_by(id=old_placeholder.device.id).first() is None
|
||||||
|
|
||||||
|
body_real, status = user3.get(f'/devices/{dhid_real}')
|
||||||
|
body_abstract, status = user3.get(f'/devices/{dhid_abstract}')
|
||||||
|
assert body_real == body_abstract
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
@ -2237,7 +2227,6 @@ def test_unbinding(user3: UserClientFlask):
|
||||||
data = {
|
data = {
|
||||||
'csrf_token': generate_csrf(),
|
'csrf_token': generate_csrf(),
|
||||||
'type': "Laptop",
|
'type': "Laptop",
|
||||||
'phid': 'sid',
|
|
||||||
'serial_number': "AAAAB",
|
'serial_number': "AAAAB",
|
||||||
'model': "LC27T55",
|
'model': "LC27T55",
|
||||||
'manufacturer': "Samsung",
|
'manufacturer': "Samsung",
|
||||||
|
@ -2262,20 +2251,22 @@ def test_unbinding(user3: UserClientFlask):
|
||||||
|
|
||||||
# page binding
|
# page binding
|
||||||
dhid = dev_wb.dhid
|
dhid = dev_wb.dhid
|
||||||
uri = f'/inventory/binding/{dhid}/sid/'
|
uri = f'/inventory/binding/{dhid}/1/'
|
||||||
user3.get(uri)
|
user3.get(uri)
|
||||||
|
|
||||||
# action binding
|
# action binding
|
||||||
|
assert Placeholder.query.count() == 11
|
||||||
assert dev.placeholder.binding is None
|
assert dev.placeholder.binding is None
|
||||||
user3.post(uri, data={})
|
user3.post(uri, data={})
|
||||||
assert dev.placeholder.binding == dev_wb
|
assert dev.placeholder.binding == dev_wb
|
||||||
|
assert Placeholder.query.count() == 1
|
||||||
|
|
||||||
dhid = dev.dhid
|
dhid = dev.dhid
|
||||||
# action unbinding
|
# action unbinding
|
||||||
uri = '/inventory/unbinding/sid/'
|
uri = '/inventory/unbinding/1/'
|
||||||
body, status = user3.post(uri, data={})
|
body, status = user3.post(uri, data={})
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
txt = f'Device with PHID:"sid" and DHID: {dhid} unbind successfully!'
|
txt = f'Device with PHID:"1" and DHID: {dhid} unbind successfully!'
|
||||||
assert txt in body
|
assert txt in body
|
||||||
# assert 'Device "sid" unbind successfully!' in body
|
# assert 'Device "sid" unbind successfully!' in body
|
||||||
|
|
||||||
|
@ -2292,6 +2283,7 @@ def test_unbinding(user3: UserClientFlask):
|
||||||
assert Device.query.filter_by(id=dev_wb.binding.device.id).first()
|
assert Device.query.filter_by(id=dev_wb.binding.device.id).first()
|
||||||
assert Device.query.filter_by(id=dev.id).first()
|
assert Device.query.filter_by(id=dev.id).first()
|
||||||
assert Placeholder.query.filter_by(id=dev.placeholder.id).first()
|
assert Placeholder.query.filter_by(id=dev.placeholder.id).first()
|
||||||
|
assert Placeholder.query.count() == 11
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -2400,8 +2392,8 @@ def test_bug_3821_binding(user3: UserClientFlask):
|
||||||
user3.post(uri, data=data)
|
user3.post(uri, data=data)
|
||||||
dev = Device.query.one()
|
dev = Device.query.one()
|
||||||
dhid = dev.dhid
|
dhid = dev.dhid
|
||||||
assert dev.phid() == 'sid'
|
assert dev.phid() == '1'
|
||||||
uri = f'/inventory/binding/{dhid}/sid/'
|
uri = f'/inventory/binding/{dhid}/1/'
|
||||||
body, status = user3.get(uri)
|
body, status = user3.get(uri)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
assert 'is not a Snapshot device!' in body
|
assert 'is not a Snapshot device!' in body
|
||||||
|
@ -2430,7 +2422,7 @@ def test_bug_3831_documents(user3: UserClientFlask):
|
||||||
|
|
||||||
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
uri = f'/inventory/lot/{lot_id}/transfer/incoming/'
|
||||||
user3.get(uri)
|
user3.get(uri)
|
||||||
data = {'csrf_token': generate_csrf(), 'code': 'AAA'}
|
data = {'csrf_token': generate_csrf(), 'code': 'AAA', 'lot_name': lot_name}
|
||||||
|
|
||||||
body, status = user3.post(uri, data=data)
|
body, status = user3.post(uri, data=data)
|
||||||
assert status == '200 OK'
|
assert status == '200 OK'
|
||||||
|
@ -2457,3 +2449,132 @@ def test_bug_3831_documents(user3: UserClientFlask):
|
||||||
uri = f'/inventory/lot/{lot_id}/trade-document/add/'
|
uri = f'/inventory/lot/{lot_id}/trade-document/add/'
|
||||||
# body, status = user3.post(uri, data=data, content_type="multipart/form-data")
|
# body, status = user3.post(uri, data=data, content_type="multipart/form-data")
|
||||||
# assert status == '200 OK'
|
# assert status == '200 OK'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_hdd_filter(user3: UserClientFlask):
|
||||||
|
create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||||
|
|
||||||
|
hdds = Device.query.filter_by(type='HardDrive').all()
|
||||||
|
for hdd in hdds:
|
||||||
|
hdd.parent = None
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
csrf = generate_csrf()
|
||||||
|
uri = f'/inventory/device/?filter=All+DataStorage&csrf_token={csrf}'
|
||||||
|
body, status = user3.get(uri)
|
||||||
|
|
||||||
|
assert status == '200 OK'
|
||||||
|
for hdd in hdds:
|
||||||
|
assert hdd.dhid in body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_add_kangaroo(user3: UserClientFlask):
|
||||||
|
create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||||
|
|
||||||
|
body, status = user3.get('/workbench/')
|
||||||
|
|
||||||
|
assert status == '200 OK'
|
||||||
|
|
||||||
|
pc = Device.query.filter_by(type='Laptop').first()
|
||||||
|
data = {
|
||||||
|
'csrf_token': generate_csrf(),
|
||||||
|
'phid': pc.phid(),
|
||||||
|
}
|
||||||
|
|
||||||
|
body, status = user3.post('/workbench/', data=data)
|
||||||
|
assert status == '200 OK'
|
||||||
|
assert pc.phid() in body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_drop_kangaroo(user3: UserClientFlask):
|
||||||
|
create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||||
|
pc = Device.query.filter_by(type='Laptop').first()
|
||||||
|
phid = 'AAA'
|
||||||
|
pc.placeholder.phid = phid
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
body, status = user3.get('/workbench/')
|
||||||
|
assert phid not in body
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'csrf_token': generate_csrf(),
|
||||||
|
'phid': phid,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, status = user3.post('/workbench/', data=data)
|
||||||
|
assert status == '200 OK'
|
||||||
|
assert phid in body
|
||||||
|
|
||||||
|
placeholder_id = pc.placeholder.id
|
||||||
|
uri = f'/workbench/erasure_host/{placeholder_id}/'
|
||||||
|
body, status = user3.get(uri)
|
||||||
|
assert status == '200 OK'
|
||||||
|
assert phid not in body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_filter_hdd_in_kangaroo(user3: UserClientFlask):
|
||||||
|
create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||||
|
csrf = generate_csrf()
|
||||||
|
uri = f'/inventory/device/?filter=All+DataStorage&csrf_token={csrf}'
|
||||||
|
body, status = user3.get(uri)
|
||||||
|
|
||||||
|
assert status == '200 OK'
|
||||||
|
for hdd in Device.query.filter_by(type='HardDrive').all():
|
||||||
|
assert hdd.dhid not in body
|
||||||
|
|
||||||
|
user3.get('/workbench/')
|
||||||
|
pc = Device.query.filter_by(type='Laptop').first()
|
||||||
|
data = {
|
||||||
|
'csrf_token': generate_csrf(),
|
||||||
|
'phid': pc.phid(),
|
||||||
|
}
|
||||||
|
user3.post('/workbench/', data=data)
|
||||||
|
|
||||||
|
csrf = generate_csrf()
|
||||||
|
uri = f'/inventory/device/?filter=All+DataStorage&csrf_token={csrf}'
|
||||||
|
body, status = user3.get(uri)
|
||||||
|
|
||||||
|
assert status == '200 OK'
|
||||||
|
for hdd in Device.query.filter_by(type='HardDrive').all():
|
||||||
|
assert hdd.dhid in body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||||
|
def test_snapshot_is_server_erase(user3: UserClientFlask):
|
||||||
|
snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||||
|
|
||||||
|
user3.get('/workbench/')
|
||||||
|
data = {
|
||||||
|
'csrf_token': generate_csrf(),
|
||||||
|
'phid': snapshot.device.phid(),
|
||||||
|
}
|
||||||
|
user3.post('/workbench/', data=data)
|
||||||
|
|
||||||
|
uri = '/inventory/upload-snapshot/'
|
||||||
|
file_name = 'real-eee-1001pxd.snapshot.12'
|
||||||
|
snapshot_json = conftest.yaml2json(file_name)
|
||||||
|
snapshot_json['uuid'] = 'c058e8d2-fb92-47cb-a4b7-522b75561136'
|
||||||
|
b_snapshot = bytes(json.dumps(snapshot_json), 'utf-8')
|
||||||
|
file_snap = (BytesIO(b_snapshot), file_name)
|
||||||
|
user3.get(uri)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'snapshot': file_snap,
|
||||||
|
'csrf_token': generate_csrf(),
|
||||||
|
}
|
||||||
|
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||||
|
snapshot2 = Snapshot.query.filter_by(uuid=snapshot_json['uuid']).one()
|
||||||
|
|
||||||
|
assert not snapshot.is_server_erase
|
||||||
|
assert snapshot2.is_server_erase
|
||||||
|
assert snapshot in snapshot.device.actions
|
||||||
|
assert snapshot2 in snapshot.device.actions
|
||||||
|
|
Reference in New Issue