feat(assets): allow editing general note field on asset details
This commit is contained in:
parent
15403b8604
commit
e51f698030
5 changed files with 39 additions and 8 deletions
|
|
@ -16,32 +16,32 @@ ASSET_EDITABLE_FIELDS_BY_ROLE = {
|
||||||
'admin': [
|
'admin': [
|
||||||
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
||||||
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
||||||
'last_inspection_date', 'funding_program', 'geom', 'lon', 'lat',
|
'last_inspection_date', 'funding_program', 'note', 'geom', 'lon', 'lat',
|
||||||
'location_id', 'intersection_id',
|
'location_id', 'intersection_id',
|
||||||
],
|
],
|
||||||
'manager': [
|
'manager': [
|
||||||
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
||||||
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
||||||
'last_inspection_date', 'funding_program', 'geom', 'lon', 'lat',
|
'last_inspection_date', 'funding_program', 'note', 'geom', 'lon', 'lat',
|
||||||
'location_id', 'intersection_id',
|
'location_id', 'intersection_id',
|
||||||
],
|
],
|
||||||
'controller': [
|
'controller': [
|
||||||
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
||||||
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
||||||
'last_inspection_date', 'funding_program', 'geom', 'lon', 'lat',
|
'last_inspection_date', 'funding_program', 'note', 'geom', 'lon', 'lat',
|
||||||
'location_id', 'intersection_id',
|
'location_id', 'intersection_id',
|
||||||
],
|
],
|
||||||
'external_manager': [
|
'external_manager': [
|
||||||
'name_fr', 'name_nl', 'external_reference', 'category', 'brand', 'serial_number', 'funding_program'
|
'name_fr', 'name_nl', 'external_reference', 'category', 'brand', 'serial_number', 'funding_program', 'note',
|
||||||
],
|
],
|
||||||
'technician': ['name_fr', 'name_nl', 'external_reference', 'category', 'brand', 'serial_number', 'funding_program'],
|
'technician': ['name_fr', 'name_nl', 'external_reference', 'category', 'brand', 'serial_number', 'funding_program', 'note'],
|
||||||
'operator': [],
|
'operator': [],
|
||||||
'observer': [],
|
'observer': [],
|
||||||
'viewer': [],
|
'viewer': [],
|
||||||
'editor': [
|
'editor': [
|
||||||
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
'code', 'external_reference', 'name_fr', 'name_nl', 'status', 'model', 'category',
|
||||||
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
'serial_number', 'installation_date', 'brand', 'warranty_duration',
|
||||||
'last_inspection_date', 'funding_program', 'geom', 'lon', 'lat',
|
'last_inspection_date', 'funding_program', 'note', 'geom', 'lon', 'lat',
|
||||||
'location_id', 'intersection_id',
|
'location_id', 'intersection_id',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
@ -588,6 +588,10 @@ def get_allowed_update_fields_for_asset(user, asset):
|
||||||
role_fields = ASSET_EDITABLE_FIELDS_BY_ROLE.get(role.name, [])
|
role_fields = ASSET_EDITABLE_FIELDS_BY_ROLE.get(role.name, [])
|
||||||
allowed_fields.update(role_fields)
|
allowed_fields.update(role_fields)
|
||||||
|
|
||||||
|
# Superuser fallback if no explicit roles configured
|
||||||
|
if getattr(user, 'is_superuser', False) and not allowed_fields:
|
||||||
|
allowed_fields.update(ASSET_EDITABLE_FIELDS_BY_ROLE.get('admin', []))
|
||||||
|
|
||||||
# Check validation permission
|
# Check validation permission
|
||||||
if can_validate_asset(user, asset):
|
if can_validate_asset(user, asset):
|
||||||
allowed_fields.add('validation_status')
|
allowed_fields.add('validation_status')
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,19 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<!-- Note générale -->
|
||||||
|
<tr class="asset-editable-field" data-field="note" data-can-edit="{% if 'note' in allowed_update_fields %}true{% else %}false{% endif %}">
|
||||||
|
<th>{% translate "Note générale" %}</th>
|
||||||
|
<td>
|
||||||
|
<div class="field-display">
|
||||||
|
<span class="field-value text-muted">{{ asset.note|default:"-"|linebreaksbr }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="field-edit d-none">
|
||||||
|
<textarea class="form-control form-control-sm" rows="3">{{ asset.note|default:'' }}</textarea>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<!-- Champs spécifiques au type d'asset -->
|
<!-- Champs spécifiques au type d'asset -->
|
||||||
{% get_asset_specific_fields asset as asset_specific_fields %}
|
{% get_asset_specific_fields asset as asset_specific_fields %}
|
||||||
{% if asset_specific_fields %}
|
{% if asset_specific_fields %}
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,7 @@
|
||||||
<span class="field-value text-muted">{{ asset.note|default:"-"|linebreaksbr }}</span>
|
<span class="field-value text-muted">{{ asset.note|default:"-"|linebreaksbr }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-edit d-none">
|
<div class="field-edit d-none">
|
||||||
<textarea class="form-control form-control-sm" rows="2">{{ asset.note|default:'' }}</textarea>
|
<textarea class="form-control form-control-sm" rows="3">{{ asset.note|default:'' }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -3516,6 +3516,16 @@ class AssetValidationPermissionTest(TestCase):
|
||||||
fields = get_allowed_update_fields_for_asset(self.user, self.asset)
|
fields = get_allowed_update_fields_for_asset(self.user, self.asset)
|
||||||
self.assertIn("validation_status", fields)
|
self.assertIn("validation_status", fields)
|
||||||
|
|
||||||
|
def test_note_in_allowed_update_fields(self):
|
||||||
|
from assets.permissions import get_allowed_update_fields_for_asset
|
||||||
|
from common.models import Role
|
||||||
|
|
||||||
|
editor_role, _ = Role.objects.get_or_create(name="editor")
|
||||||
|
self.user_config.roles.add(editor_role)
|
||||||
|
|
||||||
|
fields = get_allowed_update_fields_for_asset(self.user, self.asset)
|
||||||
|
self.assertIn("note", fields)
|
||||||
|
|
||||||
def test_bulk_edit_assets(self):
|
def test_bulk_edit_assets(self):
|
||||||
import json
|
import json
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,8 @@ class MobileAssetDetailTests(TestCase):
|
||||||
self.assertContains(response, 'id="asset-cms-edit-btn"')
|
self.assertContains(response, 'id="asset-cms-edit-btn"')
|
||||||
self.assertContains(response, 'id="asset-cms-save-btn"')
|
self.assertContains(response, 'id="asset-cms-save-btn"')
|
||||||
self.assertContains(response, 'id="asset-cms-cancel-btn"')
|
self.assertContains(response, 'id="asset-cms-cancel-btn"')
|
||||||
|
self.assertIn('note', response.context['allowed_update_fields'])
|
||||||
|
self.assertContains(response, 'data-field="note" data-can-edit="true"')
|
||||||
|
|
||||||
def test_tree_mobile_specific_elements(self):
|
def test_tree_mobile_specific_elements(self):
|
||||||
"""NatureTree specific mobile design: dendrometric widgets, icons and input attributes."""
|
"""NatureTree specific mobile design: dendrometric widgets, icons and input attributes."""
|
||||||
|
|
@ -224,7 +226,8 @@ class MobileAssetDetailTests(TestCase):
|
||||||
"height": 18.2,
|
"height": 18.2,
|
||||||
"circumference": 175.0,
|
"circumference": 175.0,
|
||||||
"vitality": "strong",
|
"vitality": "strong",
|
||||||
"tag_number": "TAG-99999"
|
"tag_number": "TAG-99999",
|
||||||
|
"note": "Arbre sain, élagage prévu à l'automne."
|
||||||
}
|
}
|
||||||
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
|
|
@ -243,6 +246,7 @@ class MobileAssetDetailTests(TestCase):
|
||||||
self.assertEqual(self.tree.circumference, 175.0)
|
self.assertEqual(self.tree.circumference, 175.0)
|
||||||
self.assertEqual(self.tree.vitality, "strong")
|
self.assertEqual(self.tree.vitality, "strong")
|
||||||
self.assertEqual(self.tree.tag_number, "TAG-99999")
|
self.assertEqual(self.tree.tag_number, "TAG-99999")
|
||||||
|
self.assertEqual(self.tree.note, "Arbre sain, élagage prévu à l'automne.")
|
||||||
|
|
||||||
def test_mobile_index_shows_assets_card_when_authorized(self):
|
def test_mobile_index_shows_assets_card_when_authorized(self):
|
||||||
"""User with asset view rights sees 'Assets' card on mobile home."""
|
"""User with asset view rights sees 'Assets' card on mobile home."""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue