feat: add dynamic signpanel type column to asset export and optimize query performance
This commit is contained in:
parent
33ef94902b
commit
96492a9726
2 changed files with 102 additions and 28 deletions
|
|
@ -4077,6 +4077,8 @@ class ExportAssetsTest(TestCase):
|
|||
content = response.content.decode('utf-8')
|
||||
self.assertIn("EXP01A-000001", content)
|
||||
self.assertIn("Asset Pour Export", content)
|
||||
from django.utils.translation import gettext as _
|
||||
self.assertNotIn(_("Type de panneau"), content)
|
||||
|
||||
def test_export_assets_with_duplicate_content_types(self):
|
||||
from django.urls import reverse
|
||||
|
|
@ -4098,6 +4100,41 @@ class ExportAssetsTest(TestCase):
|
|||
content = response.content.decode('utf-8')
|
||||
self.assertIn("EXP01A-000001", content)
|
||||
|
||||
def test_export_signpanel_with_type(self):
|
||||
from django.urls import reverse
|
||||
from assets.models import SignPanel, SignPanelType, SignPole, SignStreet
|
||||
|
||||
thematic_sign = Thematic.objects.get_or_create(code="sign", defaults={"name_fr": "Signalisation"})[0]
|
||||
UserThematics.objects.create(
|
||||
user_config=self.user_config,
|
||||
thematic=thematic_sign,
|
||||
can_view_assets=True,
|
||||
can_edit_assets=True,
|
||||
)
|
||||
|
||||
street = SignStreet.objects.create(name_fr="Rue du Test", code="STR01")
|
||||
pole = SignPole.objects.create(code="POL01", street=street)
|
||||
panel_type = SignPanelType.objects.create(code="C15", name_fr="Accès interdit", name_nl="Verboden toegang")
|
||||
panel = SignPanel.objects.create(
|
||||
code="PAN01",
|
||||
pole=pole,
|
||||
street=street,
|
||||
signpanel_type=panel_type,
|
||||
status="active",
|
||||
)
|
||||
|
||||
self.client.force_login(self.user)
|
||||
url = reverse('assets:export_assets')
|
||||
ids_json = json.dumps([f"signpanel:{panel.id}"])
|
||||
|
||||
response = self.client.post(url, {'ids': ids_json, 'format': 'csv'})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
content = response.content.decode('utf-8')
|
||||
from django.utils.translation import gettext as _
|
||||
self.assertIn(_("Type de panneau"), content)
|
||||
self.assertIn("C15 - Accès interdit", content)
|
||||
self.assertIn("PAN01", content)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,21 @@ def _get_asset_model_display(asset):
|
|||
return ''
|
||||
|
||||
|
||||
def _get_asset_signpanel_type_display(asset):
|
||||
"""Return the signpanel type code and/or name (e.g. 'C15' or 'C15 - Accès interdit...') if applicable."""
|
||||
try:
|
||||
spt = getattr(asset, 'signpanel_type', None)
|
||||
if spt:
|
||||
code = (getattr(spt, 'code', '') or '').strip()
|
||||
name = (spt.get_name() if hasattr(spt, 'get_name') else getattr(spt, 'name_fr', '')) or ''
|
||||
if code and name:
|
||||
return f"{code} - {name}"
|
||||
return code or name or ''
|
||||
except Exception:
|
||||
pass
|
||||
return ''
|
||||
|
||||
|
||||
def _fmt_date(dt):
|
||||
if dt is None:
|
||||
return ''
|
||||
|
|
@ -56,7 +71,7 @@ def _fmt_date(dt):
|
|||
return str(dt)
|
||||
|
||||
|
||||
def _get_row(model_name, asset):
|
||||
def _get_row(model_name, asset, include_signpanel_type=False):
|
||||
location = _get_asset_location(asset)
|
||||
loc_code = location.code if location else ''
|
||||
loc_name = location.get_name() if location else ''
|
||||
|
|
@ -71,13 +86,17 @@ def _get_row(model_name, asset):
|
|||
else (getattr(asset, 'obsolescence', '') or '')
|
||||
)
|
||||
warranty = getattr(asset, 'warranty_duration', None)
|
||||
return [
|
||||
row = [
|
||||
model_name,
|
||||
asset.id,
|
||||
asset.code or '',
|
||||
asset.get_name() if hasattr(asset, 'get_name') else '',
|
||||
asset.category.get_name() if getattr(asset, 'category', None) else '',
|
||||
_get_asset_model_display(asset),
|
||||
]
|
||||
if include_signpanel_type:
|
||||
row.append(_get_asset_signpanel_type_display(asset))
|
||||
row.extend([
|
||||
status_display,
|
||||
obsolescence_display,
|
||||
loc_code,
|
||||
|
|
@ -90,29 +109,36 @@ def _get_row(model_name, asset):
|
|||
getattr(asset, 'note', '') or '',
|
||||
getattr(asset, 'lon', '') if getattr(asset, 'lon', None) is not None else '',
|
||||
getattr(asset, 'lat', '') if getattr(asset, 'lat', None) is not None else '',
|
||||
])
|
||||
return row
|
||||
|
||||
|
||||
def _get_export_headers(include_signpanel_type=False):
|
||||
headers = [
|
||||
_("Type"),
|
||||
_("ID"),
|
||||
_("Code"),
|
||||
_("Nom"),
|
||||
_("Catégorie"),
|
||||
_("Modèle"),
|
||||
]
|
||||
|
||||
|
||||
EXPORT_HEADERS = [
|
||||
_("Type"),
|
||||
_("ID"),
|
||||
_("Code"),
|
||||
_("Nom"),
|
||||
_("Catégorie"),
|
||||
_("Modèle"),
|
||||
_("Statut"),
|
||||
_("Obsolescence"),
|
||||
_("Code localisation"),
|
||||
_("Nom localisation"),
|
||||
_("Date d'installation"),
|
||||
_("Date de déinstallation"),
|
||||
_("Numéro de série"),
|
||||
_("Garantie (mois)"),
|
||||
_("Marque"),
|
||||
_("Note"),
|
||||
_("Longitude"),
|
||||
_("Latitude"),
|
||||
]
|
||||
if include_signpanel_type:
|
||||
headers.append(_("Type de panneau"))
|
||||
headers.extend([
|
||||
_("Statut"),
|
||||
_("Obsolescence"),
|
||||
_("Code localisation"),
|
||||
_("Nom localisation"),
|
||||
_("Date d'installation"),
|
||||
_("Date de déinstallation"),
|
||||
_("Numéro de série"),
|
||||
_("Garantie (mois)"),
|
||||
_("Marque"),
|
||||
_("Note"),
|
||||
_("Longitude"),
|
||||
_("Latitude"),
|
||||
])
|
||||
return [str(h) for h in headers]
|
||||
|
||||
|
||||
@login_required
|
||||
|
|
@ -164,14 +190,25 @@ def export_assets(request):
|
|||
break
|
||||
if model_class is None:
|
||||
continue
|
||||
for asset in model_class.objects.filter(pk__in=asset_ids):
|
||||
qs = model_class.objects.filter(pk__in=asset_ids)
|
||||
for fk in ('category', 'model', 'signpanel_type'):
|
||||
if any(f.name == fk for f in model_class._meta.fields):
|
||||
try:
|
||||
qs = qs.select_related(fk)
|
||||
except Exception:
|
||||
pass
|
||||
for asset in qs:
|
||||
if can_view_asset(request.user, asset):
|
||||
items.append((model_name, asset))
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
has_signpanels = any(
|
||||
model_name == 'signpanel' or hasattr(asset, 'signpanel_type')
|
||||
for model_name, asset in items
|
||||
)
|
||||
timestamp = localtime(now()).strftime('%Y%m%d_%H%M%S')
|
||||
headers = [str(h) for h in EXPORT_HEADERS]
|
||||
headers = _get_export_headers(include_signpanel_type=has_signpanels)
|
||||
|
||||
if fmt == 'xlsx':
|
||||
try:
|
||||
|
|
@ -189,7 +226,7 @@ def export_assets(request):
|
|||
ws.title = 'Assets'
|
||||
ws.append(headers)
|
||||
for model_name, asset in items:
|
||||
ws.append([_sanitize(v) for v in _get_row(model_name, asset)])
|
||||
ws.append([_sanitize(v) for v in _get_row(model_name, asset, include_signpanel_type=has_signpanels)])
|
||||
|
||||
output = BytesIO()
|
||||
wb.save(output)
|
||||
|
|
@ -211,6 +248,6 @@ def export_assets(request):
|
|||
writer = csv.writer(resp, delimiter=';')
|
||||
writer.writerow(headers)
|
||||
for model_name, asset in items:
|
||||
writer.writerow(_get_row(model_name, asset))
|
||||
writer.writerow(_get_row(model_name, asset, include_signpanel_type=has_signpanels))
|
||||
|
||||
return resp
|
||||
|
|
|
|||
Loading…
Reference in a new issue