diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index cc1fd447..47b07f91 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -1392,7 +1392,7 @@ class DeviceDocumentForm(FlaskForm): def validate(self, extra_validators=None): is_valid = super().validate(extra_validators) - if g.user == self._device.owner: + if g.user != self._device.owner: is_valid = False return is_valid @@ -1415,7 +1415,7 @@ class DeviceDocumentForm(FlaskForm): if not self._obj.id: db.session.add(self._obj) - self._device.documents.add(self._obj) + # self._device.documents.add(self._obj) if commit: db.session.commit() diff --git a/ereuse_devicehub/inventory/models.py b/ereuse_devicehub/inventory/models.py index 7073078e..1e51113e 100644 --- a/ereuse_devicehub/inventory/models.py +++ b/ereuse_devicehub/inventory/models.py @@ -1,6 +1,7 @@ from uuid import uuid4 from citext import CIText +from dateutil.tz import tzutc from flask import g from sortedcontainers import SortedSet from sqlalchemy import BigInteger, Column, Integer @@ -148,3 +149,13 @@ class DeviceDocument(Thing): # db.Index('document_id', id, postgresql_using='hash'), # db.Index('type_doc', type, postgresql_using='hash') # ) + + def get_url(self) -> str: + if self.url: + return self.url.to_text() + return '' + + def __lt__(self, other): + return self.created.replace(tzinfo=tzutc()) < other.created.replace( + tzinfo=tzutc() + ) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index e6906564..bb1ac9a9 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -569,27 +569,6 @@ class DocumentDeleteView(View): return flask.redirect(next_url) -class DeviceDocumentDeleteView(View): - methods = ['GET'] - decorators = [login_required] - template_name = 'inventory/device_list.html' - form_class = TradeDocumentForm - - def dispatch_request(self, lot_id, doc_id): - next_url = url_for('inventory.lotdevicelist', lot_id=lot_id) - form = self.form_class(lot=lot_id, document=doc_id) - try: - form.remove() - except Exception as err: - msg = "{}".format(err) - messages.error(msg) - return flask.redirect(next_url) - - msg = "Document removed successfully." - messages.success(msg) - return flask.redirect(next_url) - - class UploadSnapshotView(GenericMixin): methods = ['GET', 'POST'] decorators = [login_required] @@ -853,6 +832,48 @@ class NewDeviceDocumentView(GenericMixin): return flask.render_template(self.template_name, **self.context) +class EditDeviceDocumentView(GenericMixin): + decorators = [login_required] + methods = ['POST', 'GET'] + template_name = 'inventory/device_document.html' + form_class = DeviceDocumentForm + title = "Edit document" + + def dispatch_request(self, dhid, doc_id): + self.form = self.form_class(dhid=dhid, document=doc_id) + self.get_context() + + if self.form.validate_on_submit(): + self.form.save() + messages.success('Edit document successfully!') + next_url = url_for('inventory.device_details', id=dhid) + return flask.redirect(next_url) + + self.context.update({'form': self.form, 'title': self.title}) + return flask.render_template(self.template_name, **self.context) + + +class DeviceDocumentDeleteView(View): + methods = ['GET'] + decorators = [login_required] + template_name = 'inventory/device_detail.html' + form_class = DeviceDocumentForm + + def dispatch_request(self, dhid, doc_id): + self.form = self.form_class(dhid=dhid, document=doc_id) + next_url = url_for('inventory.device_details', id=dhid) + try: + self.form.remove() + except Exception as err: + msg = "{}".format(err) + messages.error(msg) + return flask.redirect(next_url) + + msg = "Document removed successfully." + messages.success(msg) + return flask.redirect(next_url) + + class NewTradeDocumentView(GenericMixin): methods = ['POST', 'GET'] decorators = [login_required] @@ -875,7 +896,6 @@ class NewTradeDocumentView(GenericMixin): class EditTransferDocumentView(GenericMixin): - decorators = [login_required] methods = ['POST', 'GET'] template_name = 'inventory/trade_document.html' @@ -1601,6 +1621,14 @@ devices.add_url_rule( '/device//document/add/', view_func=NewDeviceDocumentView.as_view('device_document_add'), ) +devices.add_url_rule( + '/device//document/edit/', + view_func=EditDeviceDocumentView.as_view('device_document_edit'), +) +devices.add_url_rule( + '/device//document/del/', + view_func=DeviceDocumentDeleteView.as_view('device_document_del'), +) devices.add_url_rule( '/lot//transfer-document/add/', view_func=NewTradeDocumentView.as_view('transfer_document_add'), diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index a7025549..c5e65e37 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -216,6 +216,7 @@ File Uploaded on + @@ -232,7 +233,7 @@ {{ doc.created.strftime('%Y-%m-%d %H:%M')}} - + @@ -259,7 +260,7 @@ diff --git a/tests/test_basic.py b/tests/test_basic.py index e834cba2..bf78792d 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -55,6 +55,9 @@ def test_api_docs(client: Client): '/inventory/device/add/', '/inventory/device/{id}/', '/inventory/device/{dhid}/binding/', + '/inventory/device/{dhid}/document/del/{doc_id}', + '/inventory/device/{dhid}/document/edit/{doc_id}', + '/inventory/device/{dhid}/document/add/', '/inventory/device/erasure/', '/inventory/device/erasure/{orphans}/', '/inventory/all/device/', diff --git a/tests/test_render_2_0.py b/tests/test_render_2_0.py index bf127c14..d2842429 100644 --- a/tests/test_render_2_0.py +++ b/tests/test_render_2_0.py @@ -2774,3 +2774,82 @@ def test_reliable_device(user3: UserClientFlask): assert Snapshot.query.first() == snapshot assert len(snapshot.device.components) == 8 assert len(snapshot.device.actions) == 7 + + +@pytest.mark.mvp +@pytest.mark.usefixtures(conftest.app_context.__name__) +def test_add_device_document(user3: UserClientFlask): + snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json') + device = Device.query.filter_by(devicehub_id=snapshot.device.dhid).one() + uri = '/inventory/device/{}/document/add/'.format(device.dhid) + user3.get(uri) + + name = "doc1.pdf" + url = "https://www.usody.com/" + file_name = (BytesIO(b'1234567890'), name) + data = { + 'url': url, + 'file_name': file_name, + 'csrf_token': generate_csrf(), + } + + user3.post(uri, data=data, content_type="multipart/form-data") + assert device.documents[0].file_name == name + assert device.documents[0].url.to_text() == url + + +@pytest.mark.mvp +@pytest.mark.usefixtures(conftest.app_context.__name__) +def test_edit_device_document(user3: UserClientFlask): + snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json') + device = Device.query.filter_by(devicehub_id=snapshot.device.dhid).one() + uri = '/inventory/device/{}/document/add/'.format(device.dhid) + user3.get(uri) + + name = "doc1.pdf" + url = "https://www.usody.com/" + file_name = (BytesIO(b'1234567890'), name) + data = { + 'url': url, + 'file_name': file_name, + 'csrf_token': generate_csrf(), + } + + user3.post(uri, data=data, content_type="multipart/form-data") + + doc_id = str(device.documents[0].id) + uri = '/inventory/device/{}/document/edit/{}'.format(device.dhid, doc_id) + user3.get(uri) + + data['url'] = "https://www.ereuse.org/" + data['csrf_token'] = generate_csrf() + data['file_name'] = (BytesIO(b'1234567890'), name) + + user3.post(uri, data=data, content_type="multipart/form-data") + assert device.documents[0].file_name == name + assert device.documents[0].url.to_text() == data['url'] + + +@pytest.mark.mvp +@pytest.mark.usefixtures(conftest.app_context.__name__) +def test_delete_device_document(user3: UserClientFlask): + snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json') + device = Device.query.filter_by(devicehub_id=snapshot.device.dhid).one() + uri = '/inventory/device/{}/document/add/'.format(device.dhid) + user3.get(uri) + + name = "doc1.pdf" + url = "https://www.usody.com/" + file_name = (BytesIO(b'1234567890'), name) + data = { + 'url': url, + 'file_name': file_name, + 'csrf_token': generate_csrf(), + } + + user3.post(uri, data=data, content_type="multipart/form-data") + + doc_id = str(device.documents[0].id) + uri = '/inventory/device/{}/document/del/{}'.format(device.dhid, doc_id) + user3.get(uri) + assert len(device.documents) == 0