loko/streetup/interventions/views/drafts.py
2026-07-22 14:48:40 +02:00

124 lines
No EOL
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import uuid
import time
from typing import Iterable
class InterventionDraftManager:
SESSION_KEY = 'intervention_drafts'
EXPIRATION_SECONDS = 3600 # 1h
def __init__(self, session):
self.session = session
if self.SESSION_KEY not in self.session:
self.session[self.SESSION_KEY] = {}
def _touch(self, draft):
draft['timestamp'] = time.time()
self.session.modified = True
def get_or_create(self, draft_id=None):
self.cleanup()
drafts = self.session[self.SESSION_KEY]
if not draft_id or draft_id not in drafts:
draft_id = str(uuid.uuid4())
drafts[draft_id] = {
'form_data': {},
'assets': [], # liste d'objets {"model","object_id"}
'locations': [], # si besoin, même principe {"id": ...} ou {"model","object_id"}
'timestamp': time.time()
}
self.session.modified = True
return draft_id
def get(self, draft_id):
self.cleanup()
return self.session[self.SESSION_KEY].get(draft_id, {})
def update_form_data(self, draft_id, form_data: dict):
draft = self.get(draft_id)
if draft:
draft['form_data'] = form_data or {}
self._touch(draft)
# --- Helpers de normalisation ---
@staticmethod
def _norm_assets(items: Iterable):
"""Normalise en [{'model': str, 'object_id': int}, ...] + dédup."""
norm = []
seen = set()
for i, a in enumerate(items or []):
if isinstance(a, dict) and 'model' in a and 'object_id' in a:
model = str(a['model']).lower().strip()
oid = int(a['object_id'])
key = (model, oid)
if key not in seen:
seen.add(key)
norm.append({'model': model, 'object_id': oid, 'asset_type': model})
else:
# Compat : si ancien format [id, id, ...], on ignore (impossible d’inférer le model)
# => à migrer côté appelant
continue
return norm
def update_assets(self, draft_id, assets_list):
draft = self.get(draft_id)
if draft is not None:
draft['assets'] = self._norm_assets(assets_list)
self._touch(draft)
def update_locations(self, draft_id, locations_ids):
draft = self.get(draft_id)
if draft is not None:
ids = []
for x in (locations_ids or []):
try:
v = int(str(x).strip()) # gère '', ' 12 ', etc.
except (ValueError, TypeError):
continue # ignore les invalides
if v > 0: # optionnel: n'autoriser que des ids positifs
ids.append(v)
draft['locations'] = ids
self._touch(draft)
def remove_location(self, draft_id, location_id):
"""Supprime une localisation spécifique du draft"""
draft = self.get(draft_id)
if draft is not None:
try:
location_id = int(location_id)
draft['locations'] = [loc_id for loc_id in draft.get('locations', []) if loc_id != location_id]
self._touch(draft)
return True
except (ValueError, TypeError):
return False
return False
def remove_asset(self, draft_id, asset_model, asset_id):
"""Supprime un asset spécifique du draft"""
draft = self.get(draft_id)
if draft is not None:
try:
asset_id = int(asset_id)
asset_model = str(asset_model).lower().strip()
draft['assets'] = [
a for a in draft.get('assets', [])
if not (a.get('model') == asset_model and a.get('object_id') == asset_id)
]
self._touch(draft)
return True
except (ValueError, TypeError):
return False
return False
def delete(self, draft_id):
self.session[self.SESSION_KEY].pop(draft_id, None)
self.session.modified = True
def cleanup(self):
now = time.time()
expired = [k for k, v in self.session[self.SESSION_KEY].items()
if v.get('timestamp', 0) < now - self.EXPIRATION_SECONDS]
for k in expired:
self.session[self.SESSION_KEY].pop(k, None)
if expired:
self.session.modified = True