From f55abc4a7b7f018f4935620f5df8f5efc979c4af Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 10 Aug 2022 18:05:18 +0200 Subject: [PATCH 01/29] put the old dhid in the new placeholder device --- .../migrations/versions/d7ea9a3b2da1_create_placeholders.py | 5 +++++ ereuse_devicehub/resources/documents/device_row.py | 2 +- ereuse_devicehub/templates/inventory/device_detail.html | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/migrations/versions/d7ea9a3b2da1_create_placeholders.py b/ereuse_devicehub/migrations/versions/d7ea9a3b2da1_create_placeholders.py index 6abff7a8..87a7154b 100644 --- a/ereuse_devicehub/migrations/versions/d7ea9a3b2da1_create_placeholders.py +++ b/ereuse_devicehub/migrations/versions/d7ea9a3b2da1_create_placeholders.py @@ -63,6 +63,9 @@ def clone_device(device): if device.type == "Battery": device.size + + old_devicehub_id = device.devicehub_id + dict_device = copy.copy(device.__dict__) dict_device.pop('_sa_instance_state') dict_device.pop('id', None) @@ -73,6 +76,8 @@ def clone_device(device): dict_device.pop('tags', None) dict_device.pop('system_uuid', None) new_device = device.__class__(**dict_device) + new_device.devicehub_id = old_devicehub_id + device.devicehub_id = None db.session.add(new_device) if hasattr(device, 'components'): diff --git a/ereuse_devicehub/resources/documents/device_row.py b/ereuse_devicehub/resources/documents/device_row.py index edca2752..b239ee92 100644 --- a/ereuse_devicehub/resources/documents/device_row.py +++ b/ereuse_devicehub/resources/documents/device_row.py @@ -276,7 +276,7 @@ class DeviceRow(BaseDeviceRow): software=snapshot.software.name, version=snapshot.version ) # General information about device - self['DHID'] = device.devicehub_id + self['DHID'] = self.placeholder.device.devicehub_id self['DocumentID'] = self.document_id self['Public Link'] = '{url}{id}'.format( url=url_for('Device.main', _external=True), id=device.devicehub_id diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index 9f46e787..ccc90020 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -34,7 +34,7 @@ {% if placeholder.binding %} {% endif %} From 7ed2368f02e8820d98d74b40b2b3bd31ea6e7b1b Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 11 Aug 2022 09:51:17 +0200 Subject: [PATCH 02/29] unic template for device details --- .../templates/inventory/device_detail.html | 105 +++++++----------- 1 file changed, 43 insertions(+), 62 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index ccc90020..3a8ccdb0 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -18,25 +18,13 @@
-

{{ device.devicehub_id }}

+

{{ placeholder.device.devicehub_id }}

-
-
Details
- {% if device.placeholder %} +
+
Details Real parth
-
{{ device.is_abstract() }}
+
{{ placeholder.device.is_abstract() }}
- {% endif %} - {% if device.placeholder %}
Phid
-
{{ device.placeholder.phid }}
+
{{ placeholder.phid }}
- {% endif %}
Type
-
{{ device.type }}
+
{{ placeholder.device.type }}
Manufacturer
-
{{ device.manufacturer or ''}}
+
{{ placeholder.device.manufacturer or ''}}
Model
-
{{ device.model or ''}}
+
{{ placeholder.device.model or ''}}
Serial Number
-
{{ device.serial_number or ''}}
+
{{ placeholder.device.serial_number or ''}}
+
+ +
Details Abstract parth
+
+
Type
+
{{ placeholder.binding.type }}
+
+ +
+
Manufacturer
+
{{ placeholder.binding.manufacturer or ''}}
+
+ +
+
Model
+
{{ placeholder.binding.model or ''}}
+
+ +
+
Serial Number
+
{{ placeholder.binding.serial_number or ''}}
@@ -120,7 +121,7 @@
Incoming Lots
- {% for lot in device.lots %} + {% for lot in placeholder.device.lots %} {% if lot.is_incoming %}
@@ -134,7 +135,7 @@
Outgoing Lots
- {% for lot in device.lots %} + {% for lot in placeholder.device.lots %} {% if lot.is_outgoing %}
@@ -148,7 +149,7 @@
Temporary Lots
- {% for lot in device.lots %} + {% for lot in placeholder.device.lots %} {% if lot.is_temporary %} -
-
Rate Details
-
-
Rating
-
{{ device.rate or '' }}
-
-
-
Processor
-
{{ device.rate.processor or '' }}
-
-
-
RAM
-
{{ device.rate.ram or '' }}
-
-
-
Data storage
-
{{ device.rate.data_storage or '' }}
-
-
-
Traceability log Details
- {% for action in device.reverse_actions %} + {% for action in placeholder.actions %}
{{ action.type }} {{ action.severity }} {{ action.created.strftime('%H:%M %d-%m-%Y') }} @@ -258,7 +239,7 @@

-
+ {{ form_binding.csrf_token }} {% for field in form_binding %} {% if field != form_binding.csrf_token %} From 57ba86eb39adfed262f9574d6db676c857b9c955 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 11 Aug 2022 10:21:45 +0200 Subject: [PATCH 03/29] add actions in placeholder model --- ereuse_devicehub/resources/device/models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index a50d1593..1a95c3b3 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -924,6 +924,17 @@ class Placeholder(Thing): ) owner = db.relationship(User, primaryjoin=owner_id == User.id) + @property + def actions(self): + actions = list(self.device.actions) or [] + + if self.binding: + actions.extend(list(self.binding.actions)) + + actions = sorted(actions, key=lambda x: x.created) + actions.reverse() + return actions + class Computer(Device): """A chassis with components inside that can be processed From 138dc66b9aa58bb440a100823bb62fb9b2a88131 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 11 Aug 2022 14:50:47 +0200 Subject: [PATCH 04/29] modify details page and binding/unbinding page --- ereuse_devicehub/inventory/views.py | 89 +++++++++---------- ereuse_devicehub/resources/device/models.py | 8 ++ .../templates/inventory/binding.html | 85 +++++++++--------- .../templates/inventory/device_detail.html | 25 +++--- .../templates/inventory/unbinding.html | 81 ++++++++++------- 5 files changed, 153 insertions(+), 135 deletions(-) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index a797a705..1da71c58 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -180,65 +180,66 @@ class BindingView(GenericMixin): def dispatch_request(self, dhid, phid): self.get_context() - device = ( + old_device = ( Device.query.filter(Device.owner_id == g.user.id) .filter(Device.devicehub_id == dhid) - .one() + .first() ) - placeholder = ( + new_placeholder = ( Placeholder.query.filter(Placeholder.owner_id == g.user.id) .filter(Placeholder.phid == phid) - .one() + .first() ) - if device.is_abstract() != 'Abstract': + if not old_device or old_device.placeholder.status != 'Abstract': next_url = url_for('inventory.device_details', id=dhid) - messages.error('Device "{}" not is a Abstract device!'.format(dhid)) + messages.error('Device Dhid: "{}" not is a Abstract device!'.format(dhid)) return flask.redirect(next_url) - if device.placeholder: - device = device.placeholder.binding - dhid = device.devicehub_id + if not new_placeholder or new_placeholder.status != 'Real': + next_url = url_for('inventory.device_details', id=dhid) + messages.error('Device Phid: "{}" not is a Abstract device!'.format(phid)) + return flask.redirect(next_url) + + old_placeholder = old_device.placeholder + new_device = new_placeholder.device + abstract_device = old_placeholder.binding + new_dhid = new_device.devicehub_id if request.method == 'POST': - old_placeholder = device.binding - old_device_placeholder = old_placeholder.device - if old_placeholder.is_abstract: - for plog in PlaceholdersLog.query.filter_by( - placeholder_id=old_placeholder.id - ): - db.session.delete(plog) + for plog in PlaceholdersLog.query.filter_by( + placeholder_id=old_placeholder.id + ): + db.session.delete(plog) - for ac in old_device_placeholder.actions: - ac.devices.add(placeholder.device) - ac.devices.remove(old_device_placeholder) - for act in ac.actions_device: - if act.device == old_device_placeholder: - db.session.delete(act) + for ac in old_device.actions: + ac.devices.add(new_device) + ac.devices.remove(old_device) + for act in ac.actions_device: + if act.device == old_device: + db.session.delete(act) - for tag in list(old_device_placeholder.tags): - tag.device = placeholder.device + for tag in list(old_device.tags): + tag.device = new_device - db.session.delete(old_device_placeholder) - - device.binding = placeholder + db.session.delete(old_device) + abstract_device.binding = new_placeholder db.session.commit() - next_url = url_for('inventory.device_details', id=dhid) + + next_url = url_for('inventory.device_details', id=new_dhid) messages.success( - 'Device "{}" bind successfully with {}!'.format(dhid, phid) + 'Device Dhid: "{}" bind successfully with Phid: {}!'.format(dhid, phid) ) return flask.redirect(next_url) self.context.update( { - 'device': device.binding.device, - 'placeholder': placeholder, + 'new_placeholder': new_placeholder, + 'old_placeholder': old_placeholder, 'page_title': 'Binding confirm', - 'actions': list(device.binding.device.actions) - + list(placeholder.device.actions), - 'tags': list(device.binding.device.tags) - + list(placeholder.device.tags), + 'actions': list(old_device.actions) + list(new_device.actions), + 'tags': list(old_device.tags) + list(new_device.tags), } ) @@ -256,31 +257,29 @@ class UnBindingView(GenericMixin): .filter(Placeholder.phid == phid) .one() ) - if not placeholder.binding: + if not placeholder.binding or placeholder.status != 'Twin': next_url = url_for( 'inventory.device_details', id=placeholder.device.devicehub_id ) return flask.redirect(next_url) - device = placeholder.binding - - if device.is_abstract() != 'Twin': - dhid = device.devicehub_id + if placeholder.status != 'Twin': + dhid = placeholder.device.devicehub_id next_url = url_for('inventory.device_details', id=dhid) - messages.error('Device "{}" not is a Twin device!'.format(dhid)) + messages.error('Device Dhid: "{}" not is a Twin device!'.format(dhid)) return flask.redirect(next_url) self.get_context() if request.method == 'POST': - new_device = self.clone_device(device) - next_url = url_for('inventory.device_details', id=new_device.devicehub_id) - messages.success('Device "{}" unbind successfully!'.format(phid)) + new_device = self.clone_device(placeholder.binding) + new_dhid = new_device.devicehub_id + next_url = url_for('inventory.device_details', id=new_dhid) + messages.success('Device Phid: "{}" unbind successfully!'.format(phid)) return flask.redirect(next_url) self.context.update( { - 'device': device, 'placeholder': placeholder, 'page_title': 'Unbinding confirm', } diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 1a95c3b3..5bc25477 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -935,6 +935,14 @@ class Placeholder(Thing): actions.reverse() return actions + @property + def status(self): + if self.is_abstract: + return 'Abstract' + if self.binding: + return 'Twin' + return 'Real' + class Computer(Device): """A chassis with components inside that can be processed diff --git a/ereuse_devicehub/templates/inventory/binding.html b/ereuse_devicehub/templates/inventory/binding.html index 087b4e85..d453d154 100644 --- a/ereuse_devicehub/templates/inventory/binding.html +++ b/ereuse_devicehub/templates/inventory/binding.html @@ -26,109 +26,104 @@ Basic Data - Info to be Entered - Info to be Decoupled + Info Twin device + Info Abstract device - - PHID: - {{ placeholder.phid or '' }} - {{ device.placeholder.phid or '' }} - Manufacturer: - {{ placeholder.device.manufacturer or '' }} - {{ device.manufacturer or '' }} + {{ new_placeholder.device.manufacturer or '' }} + {{ old_placeholder.device.manufacturer or '' }} Model: - {{ placeholder.device.model or '' }} - {{ device.model or '' }} + {{ new_placeholder.device.model or '' }} + {{ old_placeholder.device.model or '' }} Serial Number: - {{ placeholder.device.serial_number or '' }} - {{ device.serial_number or '' }} + {{ new_placeholder.device.serial_number or '' }} + {{ old_placeholder.device.serial_number or '' }} Brand: - {{ placeholder.device.brand or '' }} - {{ device.brand or '' }} + {{ new_placeholder.device.brand or '' }} + {{ old_placeholder.device.brand or '' }} Sku: - {{ placeholder.device.sku or '' }} - {{ device.sku or '' }} + {{ new_placeholder.device.sku or '' }} + {{ old_placeholder.device.sku or '' }} Generation: - {{ placeholder.device.generation or '' }} - {{ device.generation or '' }} + {{ new_placeholder.device.generation or '' }} + {{ old_placeholder.device.generation or '' }} Version: - {{ placeholder.device.version or '' }} - {{ device.version or '' }} + {{ new_placeholder.device.version or '' }} + {{ old_placeholder.device.version or '' }} Weight: - {{ placeholder.device.weight or '' }} - {{ device.weight or '' }} + {{ new_placeholder.device.weight or '' }} + {{ old_placeholder.device.weight or '' }} Width: - {{ placeholder.device.width or '' }} - {{ device.width or '' }} + {{ new_placeholder.device.width or '' }} + {{ old_placeholder.device.width or '' }} Height: - {{ placeholder.device.height or '' }} - {{ device.height or '' }} + {{ new_placeholder.device.height or '' }} + {{ old_placeholder.device.height or '' }} Depth: - {{ placeholder.device.depth or '' }} - {{ device.depth or '' }} + {{ new_placeholder.device.depth or '' }} + {{ old_placeholder.device.depth or '' }} Color: - {{ placeholder.device.color or '' }} - {{ device.color or '' }} + {{ new_placeholder.device.color or '' }} + {{ old_placeholder.device.color or '' }} Production date: - {{ placeholder.device.production_date or '' }} - {{ device.production_date or '' }} + {{ new_placeholder.device.production_date or '' }} + {{ old_placeholder.device.production_date or '' }} Variant: - {{ placeholder.device.variant or '' }} - {{ device.variant or '' }} + {{ new_placeholder.device.variant or '' }} + {{ old_placeholder.device.variant or '' }}
- {% if placeholder.device.components or device.components %} + {% if new_placeholder.device.components or old_placeholder.device.components %}

Components

- - + + @@ -144,8 +139,8 @@
Info to be EnteredInfo to be DecoupledInfo Twin deviceInfo Abstract device
- {% for c in placeholder.device.components %} + {% for c in new_placeholder.device.components %} * {{ c.verbose_name }}
{% endfor %}
- {% for c in device.components %} + {% for c in old_placeholder.device.components %} * {{ c.verbose_name }}
{% endfor %}
- - + + @@ -169,8 +164,8 @@
Info to be EnteredInfo to be DecoupledInfo Twin deviceInfo Abstract device
- - + + @@ -189,7 +184,7 @@
- Cancel + Cancel
diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index 3a8ccdb0..9dcc3ead 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -46,13 +46,13 @@ - {% if device.is_abstract() == 'Abstract' %} + {% if placeholder.status == 'Abstract' %} {% endif %} - {% if device.is_abstract() == 'Twin' %} + {% if placeholder.status == 'Twin' %} @@ -67,7 +67,7 @@ -
{{ placeholder.device.is_abstract() }}
+
{{ placeholder.status }}
@@ -95,6 +95,7 @@
{{ placeholder.device.serial_number or ''}}
+ {% if placeholder.binding %}
Details Abstract parth
Type
@@ -115,6 +116,7 @@
Serial Number
{{ placeholder.binding.serial_number or ''}}
+ {% endif %}
@@ -202,10 +204,15 @@
-
Components Details
- {% if device.binding %} +
Components Real parth
- {% for component in device.components|sort(attribute='type') %} + {{ placeholder.components or '' }} +
+ + {% if placeholder.binding %} +
Components Abstract parth
+
+ {% for component in placeholder.binding.components|sort(attribute='type') %}
{{ component.type }}
@@ -223,13 +230,9 @@
{% endfor %}
- {% else %} -
- {{ device.placeholder.components or '' }} -
{% endif %}
- {% if device.is_abstract() %} + {% if placeholder.status %}
Binding
diff --git a/ereuse_devicehub/templates/inventory/unbinding.html b/ereuse_devicehub/templates/inventory/unbinding.html index 457b4a74..c041bfea 100644 --- a/ereuse_devicehub/templates/inventory/unbinding.html +++ b/ereuse_devicehub/templates/inventory/unbinding.html @@ -26,84 +26,79 @@
- - + + - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -111,26 +106,21 @@
- {% if placeholder.device.components or device.components %} + {% if placeholder.components %}

Components

Info to be EnteredInfo to be DecoupledInfo Twin deviceInfo Abstract device
Basic DataInfo to be EnteredInfo to be DecoupledInfo Abstract deviceInfo Real device
PHID:{{ placeholder.phid or '' }}
Manufacturer:{{ device.manufacturer or '' }}{{ placeholder.binding.manufacturer or '' }} {{ placeholder.device.manufacturer or '' }}
Model:{{ device.model or '' }}{{ placeholder.binding.model or '' }} {{ placeholder.device.model or '' }}
Serial Number:{{ device.serial_number or '' }}{{ placeholder.binding.serial_number or '' }} {{ placeholder.device.serial_number or '' }}
Brand:{{ device.brand or '' }}{{ placeholder.binding.brand or '' }} {{ placeholder.device.brand or '' }}
Sku:{{ device.sku or '' }}{{ placeholder.binding.sku or '' }} {{ placeholder.device.sku or '' }}
Generation:{{ device.generation or '' }}{{ placeholder.binding.generation or '' }} {{ placeholder.device.generation or '' }}
Version:{{ device.version or '' }}{{ placeholder.binding.version or '' }} {{ placeholder.device.version or '' }}
Weight:{{ device.weight or '' }}{{ placeholder.binding.weight or '' }} {{ placeholder.device.weight or '' }}
Width:{{ device.width or '' }}{{ placeholder.binding.width or '' }} {{ placeholder.device.width or '' }}
Height:{{ device.height or '' }}{{ placeholder.binding.height or '' }} {{ placeholder.device.height or '' }}
Depth:{{ device.depth or '' }}{{ placeholder.binding.depth or '' }} {{ placeholder.device.depth or '' }}
Color:{{ device.color or '' }}{{ placeholder.binding.color or '' }} {{ placeholder.device.color or '' }}
Production date:{{ device.production_date or '' }}{{ placeholder.binding.production_date or '' }} {{ placeholder.device.production_date or '' }}
Variant:{{ device.variant or '' }}{{ placeholder.binding.variant or '' }} {{ placeholder.device.variant or '' }}
- - + + @@ -139,19 +129,19 @@
- {% if placeholder.device.manual_actions or device.manual_actions %} + {% if placeholder.device.manual_actions or placeholder.binding.manual_actions %}

Actions

Info to be EnteredInfo to be DecoupledInfo Abstract deviceInfo Real device
- {% for c in device.components %} - * {{ c.verbose_name }}
- {% endfor %}
- {% for c in placeholder.device.components %} - * {{ c.verbose_name }}
- {% endfor %} + {{ placeholder.components or ''}}
- - + + @@ -165,6 +155,29 @@
Info to be EnteredInfo to be DecoupledInfo Abstract deviceInfo Real device
- {% for a in device.manual_actions %} + {% for a in placeholder.binding.manual_actions %} * {{ a.t }}
{% endfor %}
{% endif %} + {% if placeholder.device.tags %} +

Tags

+ + + + + + + + + + + + + +
Info Abstract deviceInfo Real device
+ + {% for a in placeholder.device.tags %} + * {{ a.t }}
+ {% endfor %} +
+ {% endif %} +
Cancel From 62b235a45515fbdad568c0d97594fb058988b3ee Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 11 Aug 2022 17:30:00 +0200 Subject: [PATCH 05/29] to do binding from real device --- ereuse_devicehub/inventory/forms.py | 6 +- ereuse_devicehub/inventory/views.py | 152 +++++++++++------- .../templates/inventory/binding.html | 2 +- .../templates/inventory/device_detail.html | 2 +- 4 files changed, 99 insertions(+), 63 deletions(-) diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index b1fdb645..1864bb3b 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -1667,8 +1667,8 @@ class BindingForm(FlaskForm): self.phid.errors = [txt] return False - if self.device.is_abstract() != 'Abstract': - txt = "This is not a abstract device." + if self.device.is_abstract() not in ['Abstract', 'Real']: + txt = "This is not a Abstract or Real device." self.phid.errors = [txt] return False @@ -1682,7 +1682,7 @@ class BindingForm(FlaskForm): self.phid.errors = [txt] return False - if self.placeholder.binding: + if self.placeholder.status not in ['Abstract', 'Real']: txt = "This placeholder have a binding with other device. " txt += "Before you need to do an unbinding with this other device." self.phid.errors = [txt] diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index 1da71c58..f2d72350 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -163,7 +163,7 @@ class DeviceDetailView(GenericMixin): if form_binding.validate_on_submit(): next_url = url_for( 'inventory.binding', - dhid=form_binding.device.devicehub_id, + dhid=id, phid=form_binding.placeholder.phid, ) return flask.redirect(next_url) @@ -179,72 +179,108 @@ class BindingView(GenericMixin): template_name = 'inventory/binding.html' def dispatch_request(self, dhid, phid): + self.phid = phid + self.dhid = dhid + self.next_url = url_for('inventory.device_details', id=dhid) self.get_context() - old_device = ( - Device.query.filter(Device.owner_id == g.user.id) - .filter(Device.devicehub_id == dhid) - .first() - ) - new_placeholder = ( - Placeholder.query.filter(Placeholder.owner_id == g.user.id) - .filter(Placeholder.phid == phid) - .first() - ) - - if not old_device or old_device.placeholder.status != 'Abstract': - next_url = url_for('inventory.device_details', id=dhid) - messages.error('Device Dhid: "{}" not is a Abstract device!'.format(dhid)) - return flask.redirect(next_url) - - if not new_placeholder or new_placeholder.status != 'Real': - next_url = url_for('inventory.device_details', id=dhid) - messages.error('Device Phid: "{}" not is a Abstract device!'.format(phid)) - return flask.redirect(next_url) - - old_placeholder = old_device.placeholder - new_device = new_placeholder.device - abstract_device = old_placeholder.binding - new_dhid = new_device.devicehub_id + self.get_objects() + if self.check_errors(): + return flask.redirect(self.next_url) if request.method == 'POST': - - for plog in PlaceholdersLog.query.filter_by( - placeholder_id=old_placeholder.id - ): - db.session.delete(plog) - - for ac in old_device.actions: - ac.devices.add(new_device) - ac.devices.remove(old_device) - for act in ac.actions_device: - if act.device == old_device: - db.session.delete(act) - - for tag in list(old_device.tags): - tag.device = new_device - - db.session.delete(old_device) - abstract_device.binding = new_placeholder - db.session.commit() - - next_url = url_for('inventory.device_details', id=new_dhid) - messages.success( - 'Device Dhid: "{}" bind successfully with Phid: {}!'.format(dhid, phid) - ) - return flask.redirect(next_url) + return self.post() self.context.update( { - 'new_placeholder': new_placeholder, - 'old_placeholder': old_placeholder, + 'new_placeholder': self.new_placeholder, + 'old_placeholder': self.old_placeholder, 'page_title': 'Binding confirm', - 'actions': list(old_device.actions) + list(new_device.actions), - 'tags': list(old_device.tags) + list(new_device.tags), + 'actions': list(self.old_device.actions) + + list(self.new_device.actions), + 'tags': list(self.old_device.tags) + list(self.new_device.tags), + 'dhid': self.dhid, } ) return flask.render_template(self.template_name, **self.context) + def check_errors(self): + if not self.new_placeholder: + messages.error('Device Phid: "{}" not exist!'.format(self.phid)) + return True + + if self.old_device.placeholder.status != 'Abstract': + messages.error( + 'Device Dhid: "{}" is not a Abstract device!'.format(self.dhid) + ) + return True + + if self.new_placeholder.status == 'Twin': + messages.error('Device Phid: "{}" is a Twin device!'.format(self.phid)) + return True + + if self.new_placeholder.status == self.old_placeholder.status: + txt = 'Device Phid: "{}" and device Dhid: "{}" have the same status, "{}"!'.format( + self.phid, self.dhid, self.new_placeholder.status + ) + messages.error(txt) + return True + + def get_objects(self): + self.old_device = ( + Device.query.filter(Device.owner_id == g.user.id) + .filter(Device.devicehub_id == self.dhid) + .one() + ) + self.new_placeholder = ( + Placeholder.query.filter(Placeholder.owner_id == g.user.id) + .filter(Placeholder.phid == self.phid) + .first() + ) + + if not self.new_placeholder: + return + + if self.old_device.placeholder.status == 'Abstract': + self.new_device = self.new_placeholder.device + self.old_placeholder = self.old_device.placeholder + elif self.old_device.placeholder.status == 'Real': + self.new_device = self.old_device + self.old_placeholder = self.new_placeholder + self.old_device = self.old_placeholder.device + self.new_placeholder = self.new_device.placeholder + + self.abstract_device = self.old_placeholder.binding + self.new_dhid = self.new_device.devicehub_id + + def post(self): + for plog in PlaceholdersLog.query.filter_by( + placeholder_id=self.old_placeholder.id + ): + db.session.delete(plog) + + for ac in self.old_device.actions: + ac.devices.add(self.new_device) + ac.devices.remove(self.old_device) + for act in ac.actions_device: + if act.device == self.old_device: + db.session.delete(act) + + for tag in list(self.old_device.tags): + tag.device = self.new_device + + db.session.delete(self.old_device) + self.abstract_device.binding = self.new_placeholder + db.session.commit() + + next_url = url_for('inventory.device_details', id=self.new_dhid) + messages.success( + 'Device Dhid: "{}" bind successfully with Phid: {}!'.format( + self.dhid, self.phid + ) + ) + return flask.redirect(next_url) + class UnBindingView(GenericMixin): methods = ['GET', 'POST'] @@ -272,9 +308,9 @@ class UnBindingView(GenericMixin): self.get_context() if request.method == 'POST': - new_device = self.clone_device(placeholder.binding) - new_dhid = new_device.devicehub_id - next_url = url_for('inventory.device_details', id=new_dhid) + dhid = placeholder.device.devicehub_id + self.clone_device(placeholder.binding) + next_url = url_for('inventory.device_details', id=dhid) messages.success('Device Phid: "{}" unbind successfully!'.format(phid)) return flask.redirect(next_url) diff --git a/ereuse_devicehub/templates/inventory/binding.html b/ereuse_devicehub/templates/inventory/binding.html index d453d154..5d4b0ecb 100644 --- a/ereuse_devicehub/templates/inventory/binding.html +++ b/ereuse_devicehub/templates/inventory/binding.html @@ -184,7 +184,7 @@
- Cancel + Cancel
diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index 9dcc3ead..875d3508 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -46,7 +46,7 @@ - {% if placeholder.status == 'Abstract' %} + {% if placeholder.status in ['Abstract', 'Real'] %} From 1e5254d7d39ef4679d754619ffb0d4644dabc10a Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 12 Aug 2022 12:28:48 +0200 Subject: [PATCH 06/29] buttons binding/unbinding --- .../templates/inventory/device_detail.html | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index 875d3508..b233c3ad 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -19,6 +19,18 @@

{{ placeholder.device.devicehub_id }}

+
+ {% if placeholder.status in ['Abstract', 'Real'] %} + + Binding + + {% elif placeholder.status == 'Twin' %} + + Unbinding + + {% endif %} +
+
From ae4ea03b49018871ea5fe328c39b8052c72b942b Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 12 Aug 2022 15:59:15 +0200 Subject: [PATCH 07/29] add new view for search phid --- ereuse_devicehub/inventory/views.py | 33 ++++++++++++--- .../templates/inventory/device_detail.html | 41 +------------------ 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index f2d72350..3b1bff66 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -148,15 +148,37 @@ class DeviceDetailView(GenericMixin): .one() ) - form_binding = BindingForm(device=device) - self.context.update( { 'device': device, 'placeholder': device.binding or device.placeholder, 'page_title': 'Device {}'.format(device.devicehub_id), + } + ) + + return flask.render_template(self.template_name, **self.context) + + +class BindingSearchView(GenericMixin): + methods = ['GET', 'POST'] + decorators = [login_required] + template_name = 'inventory/binding_search.html' + + def dispatch_request(self, dhid): + self.get_context() + device = ( + Device.query.filter(Device.owner_id == current_user.id) + .filter(Device.devicehub_id == dhid) + .one() + ) + + form_binding = BindingForm(device=device) + + self.context.update( + { + 'page_title': 'Search a Device for to do a binding from {}'.format(device.devicehub_id), 'form_binding': form_binding, - 'active_binding': False, + 'device': device } ) @@ -167,8 +189,6 @@ class DeviceDetailView(GenericMixin): phid=form_binding.placeholder.phid, ) return flask.redirect(next_url) - elif form_binding.phid.data: - self.context['active_binding'] = True return flask.render_template(self.template_name, **self.context) @@ -1227,3 +1247,6 @@ devices.add_url_rule( devices.add_url_rule( '/unbinding//', view_func=UnBindingView.as_view('unbinding') ) +devices.add_url_rule( + '//binding/', view_func=BindingSearchView.as_view('binding_search') +) diff --git a/ereuse_devicehub/templates/inventory/device_detail.html b/ereuse_devicehub/templates/inventory/device_detail.html index b233c3ad..98bef52d 100644 --- a/ereuse_devicehub/templates/inventory/device_detail.html +++ b/ereuse_devicehub/templates/inventory/device_detail.html @@ -21,7 +21,7 @@

{{ placeholder.device.devicehub_id }}

{% if placeholder.status in ['Abstract', 'Real'] %} - + Binding {% elif placeholder.status == 'Twin' %} @@ -61,7 +61,7 @@
-
+
Details Real parth
@@ -232,43 +232,6 @@
{% endif %}
- {% if placeholder.status %} -
-
Binding
-
-

- Be careful, binding implies changes in the data of a device that affect its - traceability. -

-
-
-
- {{ form_binding.csrf_token }} - {% for field in form_binding %} - {% if field != form_binding.csrf_token %} - -
- {{ field.label(class_="form-label") }}: - {{ field }} - {% if field.errors %} -

- {% for error in field.errors %} - {{ error }}
- {% endfor %} -

- {% endif %} -
- - {% endif %} - {% endfor %} -
- -
-
-
-
- {% endif %} -
From d5de31338463ff8d47439813118059de14e76695 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 12 Aug 2022 16:29:51 +0200 Subject: [PATCH 08/29] fix binding search --- ereuse_devicehub/inventory/views.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index 3b1bff66..86770593 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -176,16 +176,18 @@ class BindingSearchView(GenericMixin): self.context.update( { - 'page_title': 'Search a Device for to do a binding from {}'.format(device.devicehub_id), + 'page_title': 'Search a Device for to do a binding from {}'.format( + device.devicehub_id + ), 'form_binding': form_binding, - 'device': device + 'device': device, } ) if form_binding.validate_on_submit(): next_url = url_for( 'inventory.binding', - dhid=id, + dhid=dhid, phid=form_binding.placeholder.phid, ) return flask.redirect(next_url) @@ -1248,5 +1250,6 @@ devices.add_url_rule( '/unbinding//', view_func=UnBindingView.as_view('unbinding') ) devices.add_url_rule( - '//binding/', view_func=BindingSearchView.as_view('binding_search') + '/device//binding/', + view_func=BindingSearchView.as_view('binding_search'), ) From 59509bf2d46216bc7429736d6a33ba327d7f2247 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 11:37:39 +0200 Subject: [PATCH 09/29] messages succesfull --- ereuse_devicehub/inventory/views.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index 86770593..d673112c 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -273,7 +273,10 @@ class BindingView(GenericMixin): self.new_placeholder = self.new_device.placeholder self.abstract_device = self.old_placeholder.binding - self.new_dhid = self.new_device.devicehub_id + self.real_dhid = self.new_device.devicehub_id + self.real_phid = self.new_placeholder.phid + self.abstract_dhid = self.old_device.devicehub_id + self.abstract_phid = self.old_placeholder.phid def post(self): for plog in PlaceholdersLog.query.filter_by( @@ -295,10 +298,15 @@ class BindingView(GenericMixin): self.abstract_device.binding = self.new_placeholder db.session.commit() - next_url = url_for('inventory.device_details', id=self.new_dhid) + next_url = url_for('inventory.device_details', id=self.real_dhid) + txt = 'Device real with PHID: {} and DHID: {} bind successfully with ' + txt += 'device abstract PHID: {} DHID: {}.' messages.success( - 'Device Dhid: "{}" bind successfully with Phid: {}!'.format( - self.dhid, self.phid + txt.format( + self.real_phid, + self.real_dhid, + self.abstract_phid, + self.abstract_dhid ) ) return flask.redirect(next_url) @@ -333,7 +341,7 @@ class UnBindingView(GenericMixin): dhid = placeholder.device.devicehub_id self.clone_device(placeholder.binding) next_url = url_for('inventory.device_details', id=dhid) - messages.success('Device Phid: "{}" unbind successfully!'.format(phid)) + messages.success('Device with PHID:"{}" and DHID: {} unbind successfully!'.format(phid, dhid)) return flask.redirect(next_url) self.context.update( From 2f74a7526a7563eaff99f2277040f12137dfe338 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 11:38:16 +0200 Subject: [PATCH 10/29] declare real and abstract details in the head --- ereuse_devicehub/templates/inventory/binding.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ereuse_devicehub/templates/inventory/binding.html b/ereuse_devicehub/templates/inventory/binding.html index 5d4b0ecb..e7410bb6 100644 --- a/ereuse_devicehub/templates/inventory/binding.html +++ b/ereuse_devicehub/templates/inventory/binding.html @@ -20,6 +20,17 @@
{{ title }}

Please check that the information is correct.

+

This is a binding between:  +

    + {% if new_placeholder.is_abstract %} +
  • 1. Device abstract with DHID:{{ new_placeholder.device.devicehub_id }} and PHID: {{ new_placeholder.phid }}
  • +
  • 2. Device real with DHID: {{ old_placeholder.device.devicehub_id }} and PHID:{{ old_placeholder.phid }}
  • + {% else %} +
  • 1. Device abstract with DHID:{{ old_placeholder.device.devicehub_id }} and PHID: {{ old_placeholder.phid }}
  • +
  • 2. Device real with DHID: {{ new_placeholder.device.devicehub_id }} and PHID:{{ new_placeholder.phid }}
  • + {% endif %} +
+

From c8ff7a74f13e5770e35c5dbce664d7ceb39f1f02 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 12:49:15 +0200 Subject: [PATCH 11/29] messages succesfull --- ereuse_devicehub/inventory/views.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index d673112c..28f1e252 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -303,10 +303,7 @@ class BindingView(GenericMixin): txt += 'device abstract PHID: {} DHID: {}.' messages.success( txt.format( - self.real_phid, - self.real_dhid, - self.abstract_phid, - self.abstract_dhid + self.real_phid, self.real_dhid, self.abstract_phid, self.abstract_dhid ) ) return flask.redirect(next_url) @@ -341,7 +338,11 @@ class UnBindingView(GenericMixin): dhid = placeholder.device.devicehub_id self.clone_device(placeholder.binding) next_url = url_for('inventory.device_details', id=dhid) - messages.success('Device with PHID:"{}" and DHID: {} unbind successfully!'.format(phid, dhid)) + messages.success( + 'Device with PHID:"{}" and DHID: {} unbind successfully!'.format( + phid, dhid + ) + ) return flask.redirect(next_url) self.context.update( From df37c466369b3c081fdb3efe3e009514ec5b39bb Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 12:50:01 +0200 Subject: [PATCH 12/29] messages and colors in binding details --- .../templates/inventory/binding.html | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/binding.html b/ereuse_devicehub/templates/inventory/binding.html index e7410bb6..1cb97765 100644 --- a/ereuse_devicehub/templates/inventory/binding.html +++ b/ereuse_devicehub/templates/inventory/binding.html @@ -31,6 +31,11 @@ {% endif %}

+

The DHID and PHID information of the abstract will be lost.

+

The information in red colour will be losted and replaced by the information in green colour.
+ The information in orange will be replaced by the information in green and you always can recover + it by doing an unbinding action or find this information into device details web. +

@@ -45,72 +50,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - +
Manufacturer: {{ new_placeholder.device.manufacturer or '' }}{{ old_placeholder.device.manufacturer or '' }}{{ old_placeholder.device.manufacturer or '' }}
Model: {{ new_placeholder.device.model or '' }}{{ old_placeholder.device.model or '' }}{{ old_placeholder.device.model or '' }}
Serial Number: {{ new_placeholder.device.serial_number or '' }}{{ old_placeholder.device.serial_number or '' }}{{ old_placeholder.device.serial_number or '' }}
Brand: {{ new_placeholder.device.brand or '' }}{{ old_placeholder.device.brand or '' }}{{ old_placeholder.device.brand or '' }}
Sku: {{ new_placeholder.device.sku or '' }}{{ old_placeholder.device.sku or '' }}{{ old_placeholder.device.sku or '' }}
Generation: {{ new_placeholder.device.generation or '' }}{{ old_placeholder.device.generation or '' }}{{ old_placeholder.device.generation or '' }}
Version: {{ new_placeholder.device.version or '' }}{{ old_placeholder.device.version or '' }}{{ old_placeholder.device.version or '' }}
Weight: {{ new_placeholder.device.weight or '' }}{{ old_placeholder.device.weight or '' }}{{ old_placeholder.device.weight or '' }}
Width: {{ new_placeholder.device.width or '' }}{{ old_placeholder.device.width or '' }}{{ old_placeholder.device.width or '' }}
Height: {{ new_placeholder.device.height or '' }}{{ old_placeholder.device.height or '' }}{{ old_placeholder.device.height or '' }}
Depth: {{ new_placeholder.device.depth or '' }}{{ old_placeholder.device.depth or '' }}{{ old_placeholder.device.depth or '' }}
Color: {{ new_placeholder.device.color or '' }}{{ old_placeholder.device.color or '' }}{{ old_placeholder.device.color or '' }}
Production date: {{ new_placeholder.device.production_date or '' }}{{ old_placeholder.device.production_date or '' }}{{ old_placeholder.device.production_date or '' }}
Variant: {{ new_placeholder.device.variant or '' }}{{ old_placeholder.device.variant or '' }}{{ old_placeholder.device.variant or '' }}
@@ -133,7 +138,7 @@ * {{ c.verbose_name }}
{% endfor %} - + {% for c in old_placeholder.device.components %} * {{ c.verbose_name }}
{% endfor %} @@ -147,6 +152,9 @@ {% if actions %}

Actions

+

+ The actions will become real device and will no longer be in the abstract +

@@ -162,6 +170,9 @@ {% endfor %} @@ -172,6 +183,9 @@ {% if tags %}

Tags

+

+ The tags will become real device and will no longer be in the abstract +

+ {% for a in actions %} + * {{ a.t }}
+ {% endfor %}
@@ -187,6 +201,9 @@ {% endfor %} From d3f87d553b05e632357838e4dbae04ef8a7b8cb2 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 12:55:53 +0200 Subject: [PATCH 13/29] fix actions and tags colums --- ereuse_devicehub/templates/inventory/binding.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/binding.html b/ereuse_devicehub/templates/inventory/binding.html index 1cb97765..4aad3737 100644 --- a/ereuse_devicehub/templates/inventory/binding.html +++ b/ereuse_devicehub/templates/inventory/binding.html @@ -170,9 +170,6 @@ {% endfor %} @@ -201,9 +198,6 @@ {% endfor %} From 36dfba584df1bb57bbd3709b15ab264c46d397c5 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 12:56:10 +0200 Subject: [PATCH 14/29] status colors and messages --- .../templates/inventory/unbinding.html | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/unbinding.html b/ereuse_devicehub/templates/inventory/unbinding.html index c041bfea..1b397d28 100644 --- a/ereuse_devicehub/templates/inventory/unbinding.html +++ b/ereuse_devicehub/templates/inventory/unbinding.html @@ -34,72 +34,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - +
+ {% for tag in tags %} + * {{ tag.id }}
+ {% endfor %}
- {% for a in actions %} - * {{ a.t }}
- {% endfor %}
- {% for tag in tags %} - * {{ tag.id }}
- {% endfor %}
Manufacturer: {{ placeholder.binding.manufacturer or '' }}{{ placeholder.device.manufacturer or '' }}{{ placeholder.device.manufacturer or '' }}
Model: {{ placeholder.binding.model or '' }}{{ placeholder.device.model or '' }}{{ placeholder.device.model or '' }}
Serial Number: {{ placeholder.binding.serial_number or '' }}{{ placeholder.device.serial_number or '' }}{{ placeholder.device.serial_number or '' }}
Brand: {{ placeholder.binding.brand or '' }}{{ placeholder.device.brand or '' }}{{ placeholder.device.brand or '' }}
Sku: {{ placeholder.binding.sku or '' }}{{ placeholder.device.sku or '' }}{{ placeholder.device.sku or '' }}
Generation: {{ placeholder.binding.generation or '' }}{{ placeholder.device.generation or '' }}{{ placeholder.device.generation or '' }}
Version: {{ placeholder.binding.version or '' }}{{ placeholder.device.version or '' }}{{ placeholder.device.version or '' }}
Weight: {{ placeholder.binding.weight or '' }}{{ placeholder.device.weight or '' }}{{ placeholder.device.weight or '' }}
Width: {{ placeholder.binding.width or '' }}{{ placeholder.device.width or '' }}{{ placeholder.device.width or '' }}
Height: {{ placeholder.binding.height or '' }}{{ placeholder.device.height or '' }}{{ placeholder.device.height or '' }}
Depth: {{ placeholder.binding.depth or '' }}{{ placeholder.device.depth or '' }}{{ placeholder.device.depth or '' }}
Color: {{ placeholder.binding.color or '' }}{{ placeholder.device.color or '' }}{{ placeholder.device.color or '' }}
Production date: {{ placeholder.binding.production_date or '' }}{{ placeholder.device.production_date or '' }}{{ placeholder.device.production_date or '' }}
Variant: {{ placeholder.binding.variant or '' }}{{ placeholder.device.variant or '' }}{{ placeholder.device.variant or '' }}
@@ -119,7 +119,7 @@ - + {{ placeholder.components or ''}} @@ -131,6 +131,9 @@ {% if placeholder.device.manual_actions or placeholder.binding.manual_actions %}

Actions

+

+ The actions will become real device and will no longer be in the abstract +

@@ -157,6 +160,9 @@ {% if placeholder.device.tags %}

Tags

+

+ The tags will become real device and will no longer be in the abstract +

From 05d1f9698cf9ab25060897115c61c08e1b0e4d45 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 16:36:42 +0200 Subject: [PATCH 15/29] add both device in a public page when is a twin device --- .../device/templates/devices/layout.html | 192 ++++++++++++++++-- ereuse_devicehub/resources/device/views.py | 5 +- 2 files changed, 182 insertions(+), 15 deletions(-) diff --git a/ereuse_devicehub/resources/device/templates/devices/layout.html b/ereuse_devicehub/resources/device/templates/devices/layout.html index e4474426..f513d0b9 100644 --- a/ereuse_devicehub/resources/device/templates/devices/layout.html +++ b/ereuse_devicehub/resources/device/templates/devices/layout.html @@ -41,8 +41,8 @@
@@ -52,7 +52,7 @@
    {% for key, value in device.public_properties.items() %} -
  • {{ key }}: {{ value }}
  • +
  • {{ key }}: {{ value or '' }}
  • {% endfor %}
{% if isinstance(device, d.Computer) %} @@ -140,17 +140,6 @@
{% endif %} - {% if device.rate %} - - - - - {% endif %}
- Total rate - - {{ device.rate.rating_range }} - ({{ device.rate.rating }}) -
@@ -222,6 +211,181 @@ {% endif %}
+ {% if abstract %} +
+ +
+
+
+
+
+
    + {% for key, value in abstract.public_properties.items() %} +
  • {{ key }}: {{ value or '' }}
  • + {% endfor %} +
+ {% if isinstance(abstract, d.Computer) %} +
+ + + + + + + + + {% if abstract.processor_model %} + + + + + {% endif %} + {% if abstract.ram_size %} + + + + + {% endif %} + {% if abstract.data_storage_size %} + + + + + {% endif %} + {% if abstract.graphic_card_model %} + + + + + {% endif %} + {% if abstract.network_speeds %} + + + + + {% endif %} + +
Range
+ CPU – {{ abstract.processor_model }} + + Processor Rate = {% if abstract.rate %} + {{ abstract.rate.processor_range }} + ({{ abstract.rate.processor }}) + {% endif %} +
+ RAM – {{ abstract.ram_size // 1000 }} GB + {{ macros.component_type(abstract.components, 'RamModule') }} + + RAM Rate = {% if abstract.rate %} + {{ abstract.rate.ram_range }} + ({{ abstract.rate.ram }}) + {% endif %} +
+ Data Storage – {{ abstract.data_storage_size // 1000 }} GB + {{ macros.component_type(abstract.components, 'SolidStateDrive') }} + {{ macros.component_type(abstract.components, 'HardDrive') }} + + Data Storage Rate = {% if abstract.rate %} + {{ abstract.rate.data_storage_range }} + ({{ abstract.rate.data_storage }}) + {% endif %} +
+ Graphics – {{ abstract.graphic_card_model }} + {{ macros.component_type(abstract.components, 'GraphicCard') }} +
+ Network – + {% if abstract.network_speeds[0] %} + Ethernet + {% if abstract.network_speeds[0] != None %} + max. {{ abstract.network_speeds[0] }} Mbps + {% endif %} + {% endif %} + {% if abstract.network_speeds[0] and abstract.network_speeds[1] %} + + + {% endif %} + {% if abstract.network_speeds[1] %} + WiFi + {% if abstract.network_speeds[1] != None %} + max. {{ abstract.network_speeds[1] }} Mbps + {% endif %} + {% endif %} + {{ macros.component_type(abstract.components, 'NetworkAdapter') }} +
+
+

Actual Status

+
    +
  1. + + Lifecycle Status + + — + {% if abstract.status %} + {{ abstract.status.type }} + {% endif %} +
  2. +
  3. + + Allocate Status + + — + {% if abstract.allocated_status %} + {{ abstract.allocated_status.type }} + {% endif %} +
  4. +
  5. + + Physical Status + + — + {% if abstract.physical_status %} + {{ abstract.physical_status.type }} + {% endif %} +
  6. +
+ +

Public traceability log of the abstract

+
+ Latest one. +
+
    + {% for action in abstract.public_actions %} +
  1. + + {{ abstract.is_status(action) }} + {% if not abstract.is_status(action) %} + {{ action.type }} + {% endif %} + + — + {% if abstract.is_status(action) %} + {{ action }} {{ action.type }} + {% else %} + {{ action }} + {% endif %} +
    +
    + + {{ action._date_str }} + +
    + {% if action.certificate %} + See the certificate + {% endif %} +
  2. + {% endfor %} +
+
+ Oldest one. +
+ {% endif %} +
+
+ {% endif %}
diff --git a/ereuse_devicehub/resources/device/views.py b/ereuse_devicehub/resources/device/views.py index 238284e1..1fff5bcc 100644 --- a/ereuse_devicehub/resources/device/views.py +++ b/ereuse_devicehub/resources/device/views.py @@ -141,7 +141,10 @@ class DeviceView(View): device = Device.query.filter_by( devicehub_id=id, active=True ).one() - return render_template('devices/layout.html', device=device, states=states) + abstract = None + if device.is_abstract() == 'Twin': + abstract = device.placeholder.binding + return render_template('devices/layout.html', device=device, states=states, abstract=abstract) @auth.Auth.requires_auth def one_private(self, id: str): From 30f511a03afaeaf669f8592be0cfcd39304df00a Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 16:36:57 +0200 Subject: [PATCH 16/29] add both device in a public page when is a twin device --- ereuse_devicehub/resources/device/views.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ereuse_devicehub/resources/device/views.py b/ereuse_devicehub/resources/device/views.py index 1fff5bcc..2729592a 100644 --- a/ereuse_devicehub/resources/device/views.py +++ b/ereuse_devicehub/resources/device/views.py @@ -110,9 +110,7 @@ class DeviceView(View): return super().get(id) def patch(self, id): - dev = Device.query.filter_by( - id=id, owner_id=g.user.id, active=True - ).one() + dev = Device.query.filter_by(id=id, owner_id=g.user.id, active=True).one() if isinstance(dev, Computer): resource_def = app.resources['Computer'] # TODO check how to handle the 'actions_one' @@ -138,13 +136,13 @@ class DeviceView(View): return self.one_private(id) def one_public(self, id: int): - device = Device.query.filter_by( - devicehub_id=id, active=True - ).one() + device = Device.query.filter_by(devicehub_id=id, active=True).one() abstract = None if device.is_abstract() == 'Twin': abstract = device.placeholder.binding - return render_template('devices/layout.html', device=device, states=states, abstract=abstract) + return render_template( + 'devices/layout.html', device=device, states=states, abstract=abstract + ) @auth.Auth.requires_auth def one_private(self, id: str): From 43f1d4e209f6a47dc7543b07dc354eeb4b9ca0ca Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 16:38:07 +0200 Subject: [PATCH 17/29] add template binding search --- .../templates/inventory/binding_search.html | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 ereuse_devicehub/templates/inventory/binding_search.html diff --git a/ereuse_devicehub/templates/inventory/binding_search.html b/ereuse_devicehub/templates/inventory/binding_search.html new file mode 100644 index 00000000..28fbad0b --- /dev/null +++ b/ereuse_devicehub/templates/inventory/binding_search.html @@ -0,0 +1,74 @@ +{% extends "ereuse_devicehub/base_site.html" %} +{% block main %} + +
+

Inventory

+ +
+ +
+
+ +
+ +
+
+

{{ device.devicehub_id }}

+ +
+ +
+
Binding
+ {% if device.is_abstract() == 'Twin' or not device.placeholder %} +
+

+ Device with Dhid: {{ device.devicehub_id }} is a Twin device.
+ If you want to do a binding with this device, you need todo an Unbinding first.
+ You can to do this in here. +

+
+ {% else %} +
+

+ Be careful, binding implies changes in the data of a device that affect its traceability. +

+
+
+
+ {{ form_binding.csrf_token }} + {% for field in form_binding %} + {% if field != form_binding.csrf_token %} + +
+ {{ field.label(class_="form-label") }}: + {{ field }} + {% if field.errors %} +

+ {% for error in field.errors %} + {{ error }}
+ {% endfor %} +

+ {% endif %} +
+ + {% endif %} + {% endfor %} +
+ +
+
+
+ {% endif %} +
+ +
+
+
+
+
+{% endblock main %} From b5a738c44ab8d008f5107b0e7bd933e3897159c9 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Mon, 29 Aug 2022 17:22:29 +0200 Subject: [PATCH 18/29] fix test print label in test_render --- tests/test_render_2_0.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_render_2_0.py b/tests/test_render_2_0.py index 3395cda5..31965b13 100644 --- a/tests/test_render_2_0.py +++ b/tests/test_render_2_0.py @@ -419,7 +419,7 @@ def test_print_labels(user3: UserClientFlask): body, status = user3.post(uri, data=data) assert status == '200 OK' - path = "/inventory/device/{}/".format(dev.devicehub_id) + path = "/devices/{}".format(dev.devicehub_id) assert path in body assert "tag1" in body From bdf04061dc398e29998afa5fcef958bb4a1bdc51 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 30 Aug 2022 13:10:35 +0200 Subject: [PATCH 19/29] mv unique identifiers buttons to device details --- ereuse_devicehub/inventory/forms.py | 37 ++++++++---------- ereuse_devicehub/inventory/views.py | 26 ++++++++----- .../templates/ereuse_devicehub/base_site.html | 8 ++++ .../templates/inventory/addDevicestag.html | 12 ++---- .../templates/inventory/device_detail.html | 39 +++++++++++++++++++ .../templates/inventory/device_list.html | 33 ---------------- .../inventory/tag_unlink_device.html | 2 +- 7 files changed, 85 insertions(+), 72 deletions(-) diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 1864bb3b..83d18ad9 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -137,11 +137,11 @@ class FilterForm(FlaskForm): self.lot = self.lots.filter(Lot.id == self.lot_id).one() device_ids = (d.id for d in self.lot.devices) self.devices = Device.query.filter(Device.id.in_(device_ids)).filter( - Device.binding == None + Device.binding == None # noqa: E711 ) else: self.devices = Device.query.filter(Device.owner_id == g.user.id).filter( - Device.binding == None + Device.binding == None # noqa: E711 ) if self.only_unassigned: self.devices = self.devices.filter_by(lots=None) @@ -655,19 +655,30 @@ class NewDeviceForm(FlaskForm): class TagDeviceForm(FlaskForm): - tag = SelectField('Tag', choices=[]) - device = StringField('Device', [validators.Optional()]) + tag = SelectField( + 'Tag', + choices=[], + render_kw={ + 'class': 'form-control selectpicker', + 'data-live-search': 'true', + }, + ) def __init__(self, *args, **kwargs): self.delete = kwargs.pop('delete', None) - self.device_id = kwargs.pop('device', None) + self.dhid = kwargs.pop('dhid', None) + self._device = ( + Device.query.filter(Device.devicehub_id == self.dhid) + .filter(Device.owner_id == g.user.id) + .one() + ) super().__init__(*args, **kwargs) if self.delete: tags = ( Tag.query.filter(Tag.owner_id == g.user.id) - .filter_by(device_id=self.device_id) + .filter_by(device_id=self._device.id) .order_by(Tag.id) ) else: @@ -695,20 +706,6 @@ class TagDeviceForm(FlaskForm): self.tag.errors = [("This tag is actualy in use.")] return False - if self.device.data: - try: - self.device.data = int(self.device.data.split(',')[-1]) - except: # noqa: E722 - self.device.data = None - - if self.device_id or self.device.data: - self.device_id = self.device_id or self.device.data - self._device = ( - Device.query.filter(Device.id == self.device_id) - .filter(Device.owner_id == g.user.id) - .one() - ) - return True def save(self): diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index 28f1e252..8b65e37a 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -80,7 +80,6 @@ class DeviceListMixin(GenericMixin): self.context.update( { 'devices': devices, - 'form_tag_device': TagDeviceForm(), 'form_new_action': form_new_action, 'form_new_allocate': AllocateForm(lot=lot_id), 'form_new_datawipe': DataWipeForm(lot=lot_id), @@ -148,11 +147,13 @@ class DeviceDetailView(GenericMixin): .one() ) + form_tags = TagDeviceForm(dhid=id) self.context.update( { 'device': device, 'placeholder': device.binding or device.placeholder, 'page_title': 'Device {}'.format(device.devicehub_id), + 'form_tag_device': form_tags, } ) @@ -542,12 +543,15 @@ class TagLinkDeviceView(View): methods = ['POST'] decorators = [login_required] - def dispatch_request(self): - form = TagDeviceForm() + def dispatch_request(self, dhid): + form = TagDeviceForm(dhid=dhid) if form.validate_on_submit(): + tag = form.tag.data form.save() - return flask.redirect(request.referrer) + next_url = url_for('inventory.device_details', id=dhid) + messages.success('Tag {} was linked successfully!'.format(tag)) + return flask.redirect(next_url) class TagUnlinkDeviceView(GenericMixin): @@ -555,19 +559,20 @@ class TagUnlinkDeviceView(GenericMixin): decorators = [login_required] template_name = 'inventory/tag_unlink_device.html' - def dispatch_request(self, id): + def dispatch_request(self, dhid): self.get_context() - form = TagDeviceForm(delete=True, device=id) + form = TagDeviceForm(delete=True, dhid=dhid) if form.validate_on_submit(): form.remove() - next_url = url_for('inventory.devicelist') + next_url = url_for('inventory.device_details', id=dhid) + messages.success('Tag {} was unlinked successfully!'.format(form.tag.data)) return flask.redirect(next_url) self.context.update( { 'form': form, - 'referrer': request.referrer, + 'dhid': dhid, } ) @@ -1211,10 +1216,11 @@ devices.add_url_rule( '/device/edit//', view_func=DeviceEditView.as_view('device_edit') ) devices.add_url_rule( - '/tag/devices/add/', view_func=TagLinkDeviceView.as_view('tag_devices_add') + '/tag/devices//add/', + view_func=TagLinkDeviceView.as_view('tag_devices_add'), ) devices.add_url_rule( - '/tag/devices//del/', + '/tag/devices//del/', view_func=TagUnlinkDeviceView.as_view('tag_devices_del'), ) devices.add_url_rule( diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html index 87dfb226..4d793495 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html @@ -256,6 +256,14 @@ + + + + diff --git a/ereuse_devicehub/templates/inventory/addDevicestag.html b/ereuse_devicehub/templates/inventory/addDevicestag.html index bb02c221..55c11fbc 100644 --- a/ereuse_devicehub/templates/inventory/addDevicestag.html +++ b/ereuse_devicehub/templates/inventory/addDevicestag.html @@ -7,16 +7,12 @@
-
- {{ form_tag_device.csrf_token }} + + + +{% include "inventory/addDevicestag.html" %} {% endblock main %} diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index b2ed449d..8d305417 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -268,42 +268,11 @@
- -
-{% include "inventory/addDevicestag.html" %} {% include "inventory/lot_delete_modal.html" %} {% include "inventory/actions.html" %} {% include "inventory/allocate.html" %} {% include "inventory/data_wipe.html" %} {% include "inventory/trade.html" %} {% include "inventory/alert_export_error.html" %} -{% include "inventory/alert_unlink_tag_error.html" %} {% include "inventory/alert_lots_changes.html" %} diff --git a/ereuse_devicehub/templates/inventory/tag_unlink_device.html b/ereuse_devicehub/templates/inventory/tag_unlink_device.html index af6ed3a6..42d67014 100644 --- a/ereuse_devicehub/templates/inventory/tag_unlink_device.html +++ b/ereuse_devicehub/templates/inventory/tag_unlink_device.html @@ -49,7 +49,7 @@
- Cancel + Cancel
From 4dfbb4a0dcb9db7313946828308f961051f398f7 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 30 Aug 2022 13:17:58 +0200 Subject: [PATCH 20/29] js unique identifiers fix --- .../static/js/main_inventory.build.js | 31 ------------------- ereuse_devicehub/static/js/main_inventory.js | 31 ------------------- 2 files changed, 62 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.build.js b/ereuse_devicehub/static/js/main_inventory.build.js index 7737a44c..0ae433c1 100644 --- a/ereuse_devicehub/static/js/main_inventory.build.js +++ b/ereuse_devicehub/static/js/main_inventory.build.js @@ -178,8 +178,6 @@ function deviceSelect() { $("#addingLotModal .btn-primary").hide(); $("#removeLotModal .pol").show(); $("#removeLotModal .btn-primary").hide(); - $("#addingTagModal .pol").show(); - $("#addingTagModal .btn-primary").hide(); $("#actionModal .pol").show(); $("#actionModal .btn-primary").hide(); $("#allocateModal .pol").show(); @@ -197,8 +195,6 @@ function deviceSelect() { $("#allocateModal .btn-primary").show(); $("#datawipeModal .pol").hide(); $("#datawipeModal .btn-primary").show(); - $("#addingTagModal .pol").hide(); - $("#addingTagModal .btn-primary").show(); } } @@ -214,33 +210,6 @@ function removeLot() { $("#activeRemoveLotModal").click(); } -function removeTag() { - const devices = TableController.getSelectedDevices(); - const devices_id = devices.map(dev => $(dev).attr('data')); - - if (devices_id.length == 1) { - const url = "/inventory/tag/devices/".concat(devices_id[0], "/del/"); - window.location.href = url; - } else { - $("#unlinkTagAlertModal").click(); - } -} - -function addTag() { - const devices = TableController.getSelectedDevices(); - const devices_id = devices.map(dev => $(dev).attr('data')); - - if (devices_id.length == 1) { - $("#addingTagModal .pol").hide(); - $("#addingTagModal .btn-primary").show(); - } else { - $("#addingTagModal .pol").show(); - $("#addingTagModal .btn-primary").hide(); - } - - $("#addTagAlertModal").click(); -} - function select_shift() { const chkboxes = $('.deviceSelect'); var lastChecked = null; diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index d80d6c66..061c82e0 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -163,9 +163,6 @@ function deviceSelect() { $("#removeLotModal .pol").show(); $("#removeLotModal .btn-primary").hide(); - $("#addingTagModal .pol").show(); - $("#addingTagModal .btn-primary").hide(); - $("#actionModal .pol").show(); $("#actionModal .btn-primary").hide(); @@ -189,9 +186,6 @@ function deviceSelect() { $("#datawipeModal .pol").hide(); $("#datawipeModal .btn-primary").show(); - - $("#addingTagModal .pol").hide(); - $("#addingTagModal .btn-primary").show(); } } @@ -205,31 +199,6 @@ function removeLot() { $("#activeRemoveLotModal").click(); } -function removeTag() { - const devices = TableController.getSelectedDevices(); - const devices_id = devices.map(dev => $(dev).attr("data")); - if (devices_id.length == 1) { - const url = `/inventory/tag/devices/${devices_id[0]}/del/`; - window.location.href = url; - } else { - $("#unlinkTagAlertModal").click(); - } -} - -function addTag() { - const devices = TableController.getSelectedDevices(); - const devices_id = devices.map(dev => $(dev).attr("data")); - if (devices_id.length == 1) { - $("#addingTagModal .pol").hide(); - $("#addingTagModal .btn-primary").show(); - } else { - $("#addingTagModal .pol").show(); - $("#addingTagModal .btn-primary").hide(); - } - - $("#addTagAlertModal").click(); -} - function select_shift() { const chkboxes = $(".deviceSelect"); let lastChecked = null; From 4935a1bd7546f876c6f10d5a30764c2ca7a1b84d Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 30 Aug 2022 15:12:14 +0200 Subject: [PATCH 21/29] add phid in advanced search --- ereuse_devicehub/inventory/forms.py | 8 +++- .../templates/inventory/search.html | 43 ++++--------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 83d18ad9..ede98e95 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -110,7 +110,13 @@ class AdvancedSearchForm(FlaskForm): self.search(dhids) def search(self, dhids): - self.devices = Device.query.filter(Device.devicehub_id.in_(dhids)) + query = Device.query.filter(Device.owner_id == g.user.id) + self.devices = query.join(Device.placeholder).filter( + or_( + Device.devicehub_id.in_(dhids), + Placeholder.phid.in_(dhids), + ) + ) class FilterForm(FlaskForm): diff --git a/ereuse_devicehub/templates/inventory/search.html b/ereuse_devicehub/templates/inventory/search.html index d996a1f3..06a4f42e 100644 --- a/ereuse_devicehub/templates/inventory/search.html +++ b/ereuse_devicehub/templates/inventory/search.html @@ -28,7 +28,7 @@
- {% if devices %} + {% if devices.count() %}
@@ -178,42 +178,11 @@
- -
-{% include "inventory/addDevicestag.html" %} {% include "inventory/lot_delete_modal.html" %} {% include "inventory/actions.html" %} {% include "inventory/allocate.html" %} {% include "inventory/data_wipe.html" %} {% include "inventory/trade.html" %} {% include "inventory/alert_export_error.html" %} -{% include "inventory/alert_unlink_tag_error.html" %} {% include "inventory/alert_lots_changes.html" %} From c0653e51cedc10178adaf76a75a687eab45a907f Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 31 Aug 2022 10:55:49 +0200 Subject: [PATCH 22/29] redirect public link from abstract to real device --- ereuse_devicehub/resources/device/models.py | 3 +++ ereuse_devicehub/resources/device/views.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 5bc25477..7772eacc 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -324,6 +324,9 @@ class Device(Thing): @property def public_link(self) -> str: + if self.binding: + return self.binding.device.public_link + host_url = request.host_url.strip('/') return "{}{}".format(host_url, self.url.to_text()) diff --git a/ereuse_devicehub/resources/device/views.py b/ereuse_devicehub/resources/device/views.py index 2729592a..e6e158a4 100644 --- a/ereuse_devicehub/resources/device/views.py +++ b/ereuse_devicehub/resources/device/views.py @@ -2,6 +2,7 @@ import datetime import uuid from itertools import filterfalse +import flask import marshmallow from flask import Response from flask import current_app as app @@ -138,8 +139,12 @@ class DeviceView(View): def one_public(self, id: int): device = Device.query.filter_by(devicehub_id=id, active=True).one() abstract = None + if device.binding: + return flask.redirect(device.public_link) + if device.is_abstract() == 'Twin': abstract = device.placeholder.binding + return render_template( 'devices/layout.html', device=device, states=states, abstract=abstract ) From eefcaeb6a0e617fe8211a51bee039ae04a8698de Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 31 Aug 2022 11:04:59 +0200 Subject: [PATCH 23/29] split new device in a parth real and other abstract --- .../templates/inventory/device_list.html | 31 ++++++++++++------- .../templates/inventory/search.html | 29 ++++++++++++++--- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index 8d305417..4502b63e 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -291,19 +291,9 @@ + + {% if lot and not lot.is_temporary %} + +