loko/streetup/sign/management/commands/invert_vertical_order.py
2026-07-22 14:48:40 +02:00

98 lines
3.3 KiB
Python

"""
Management command to invert the vertical_order of SignPanels for a given organization.
For each pole, the vertical_order values are reversed:
if orders on a pole are [1, 2, 3], they become [3, 2, 1]
formula: new_order = max_order + min_order - old_order
Usage:
python manage.py invert_vertical_order --org_id 1 [--dry-run]
"""
from django.core.management.base import BaseCommand
from django.db import transaction
from sign.models import SignPanel, SignPole
class Command(BaseCommand):
help = "Inverse l'ordre vertical des panneaux par poteau pour une organisation donnée."
def add_arguments(self, parser):
parser.add_argument(
"--org_id",
type=int,
default=1,
help="ID de l'organisation (défaut: 1)",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Affiche les modifications sans les appliquer",
)
def handle(self, *args, **options):
org_id = options["org_id"]
dry_run = options["dry_run"]
if dry_run:
self.stdout.write(self.style.WARNING("Mode DRY-RUN: aucune modification ne sera enregistrée.\n"))
# Get all distinct pole IDs that have panels for this organisation
pole_ids = (
SignPanel.objects
.filter(organization_id=org_id, pole__isnull=False, vertical_order__isnull=False)
.values_list("pole_id", flat=True)
.distinct()
)
pole_ids = list(pole_ids)
self.stdout.write(f"Organisation {org_id}: {len(pole_ids)} poteau(x) concerné(s).\n")
total_panels_updated = 0
with transaction.atomic():
for pole_id in pole_ids:
panels = list(
SignPanel.objects
.filter(organization_id=org_id, pole_id=pole_id, vertical_order__isnull=False)
.order_by("vertical_order")
)
if not panels:
continue
orders = [p.vertical_order for p in panels]
min_order = min(orders)
max_order = max(orders)
if min_order == max_order:
# Only one distinct value, nothing to invert
continue
self.stdout.write(f" Poteau {pole_id}: orders {orders} -> ", ending="")
updates = []
for panel in panels:
new_order = max_order + min_order - panel.vertical_order
updates.append((panel, new_order))
new_orders = [o for _, o in updates]
self.stdout.write(str(new_orders))
if not dry_run:
for panel, new_order in updates:
panel.vertical_order = new_order
panel.save(update_fields=["vertical_order"])
total_panels_updated += 1
if dry_run:
# Rollback even if somehow something was written
transaction.set_rollback(True)
if dry_run:
self.stdout.write(self.style.WARNING("\nDRY-RUN terminé, aucune modification enregistrée."))
else:
self.stdout.write(
self.style.SUCCESS(f"\n{total_panels_updated} panneau(x) mis à jour avec succès.")
)