feat: add ZIP archive support and expand structure directory matching to include location codes

This commit is contained in:
kdeterme 2026-08-21 15:14:15 +02:00
parent 0ab5fee09b
commit 04eb087cf1

View file

@ -1,5 +1,7 @@
import os import os
import subprocess import subprocess
import tempfile
import zipfile
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -16,7 +18,7 @@ User = get_user_model()
class Command(BaseCommand): class Command(BaseCommand):
help = ( help = (
"Imports As-Built documents from a local directory or via rclone from OneDrive " "Imports As-Built documents from a local directory, a ZIP archive, or via rclone "
"into the 'Electromechanics / As-Built' subfolder of specified structures." "into the 'Electromechanics / As-Built' subfolder of specified structures."
) )
@ -26,6 +28,11 @@ class Command(BaseCommand):
default="/tmp/as_built_sync", default="/tmp/as_built_sync",
help="Path to local directory containing files/folders to import (default: /tmp/as_built_sync).", help="Path to local directory containing files/folders to import (default: /tmp/as_built_sync).",
) )
parser.add_argument(
"--source-zip",
default=None,
help="Path to a ZIP file downloaded from OneDrive to extract and import.",
)
parser.add_argument( parser.add_argument(
"--rclone-remote", "--rclone-remote",
default=None, default=None,
@ -55,6 +62,7 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
source_dir = options["source_dir"] source_dir = options["source_dir"]
source_zip = options["source_zip"]
rclone_remote = options["rclone_remote"] rclone_remote = options["rclone_remote"]
target_codes = options["structures"] target_codes = options["structures"]
dry_run = options["dry_run"] dry_run = options["dry_run"]
@ -64,8 +72,18 @@ class Command(BaseCommand):
if dry_run: if dry_run:
self.stdout.write(self.style.WARNING("DRY RUN — no changes will be committed.")) self.stdout.write(self.style.WARNING("DRY RUN — no changes will be committed."))
# Optionnel: Synchronisation via rclone si un remote est spécifié # Traitement d'une archive ZIP si spécifiée
if rclone_remote: if source_zip:
if not os.path.isfile(source_zip):
raise CommandError(f"ZIP file '{source_zip}' does not exist.")
self.stdout.write(self.style.NOTICE(f"Extracting ZIP archive '{source_zip}' into '{source_dir}'..."))
os.makedirs(source_dir, exist_ok=True)
with zipfile.ZipFile(source_zip, 'r') as zip_ref:
zip_ref.extractall(source_dir)
self.stdout.write(self.style.SUCCESS("ZIP extraction completed."))
# Synchronisation via rclone si un remote est spécifié
elif rclone_remote:
self.stdout.write(self.style.NOTICE(f"Syncing from rclone remote '{rclone_remote}' to '{source_dir}'...")) self.stdout.write(self.style.NOTICE(f"Syncing from rclone remote '{rclone_remote}' to '{source_dir}'..."))
os.makedirs(source_dir, exist_ok=True) os.makedirs(source_dir, exist_ok=True)
rclone_cmd = ["rclone", "copy", rclone_remote, source_dir] rclone_cmd = ["rclone", "copy", rclone_remote, source_dir]
@ -158,13 +176,23 @@ class Command(BaseCommand):
total_skipped = 0 total_skipped = 0
for structure in structures: for structure in structures:
# Check if there is a dedicated subfolder for this structure code or name in source_dir # Check if there is a dedicated subfolder for this structure code, location codes or name in source_dir
struct_dir = None struct_dir = None
possible_dirs = [ possible_dirs = [
os.path.join(source_dir, structure.code), os.path.join(source_dir, structure.code),
os.path.join(source_dir, f"{structure.code}_{structure.name_fr}"), os.path.join(source_dir, f"{structure.code}_{structure.name_fr}"),
os.path.join(source_dir, structure.name_fr or ""), os.path.join(source_dir, structure.name_fr or ""),
] ]
# Also check all associated location codes (e.g. WTB03)
loc_codes = list(structure.all_locations.values_list("code", flat=True))
for loc_code in loc_codes:
possible_dirs.append(os.path.join(source_dir, loc_code))
if os.path.isdir(source_dir):
for folder_item in os.listdir(source_dir):
if folder_item.upper().startswith(loc_code.upper()):
possible_dirs.append(os.path.join(source_dir, folder_item))
for p in possible_dirs: for p in possible_dirs:
if os.path.isdir(p): if os.path.isdir(p):
struct_dir = p struct_dir = p