diff --git a/loko/assets/management/commands/import_as_built_documents.py b/loko/assets/management/commands/import_as_built_documents.py index 43bab33..2830187 100644 --- a/loko/assets/management/commands/import_as_built_documents.py +++ b/loko/assets/management/commands/import_as_built_documents.py @@ -1,5 +1,7 @@ import os import subprocess +import tempfile +import zipfile from django.core.management.base import BaseCommand, CommandError from django.contrib.contenttypes.models import ContentType from django.contrib.auth import get_user_model @@ -16,7 +18,7 @@ User = get_user_model() class Command(BaseCommand): 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." ) @@ -26,6 +28,11 @@ class Command(BaseCommand): 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( "--rclone-remote", default=None, @@ -55,6 +62,7 @@ class Command(BaseCommand): def handle(self, *args, **options): source_dir = options["source_dir"] + source_zip = options["source_zip"] rclone_remote = options["rclone_remote"] target_codes = options["structures"] dry_run = options["dry_run"] @@ -64,8 +72,18 @@ class Command(BaseCommand): if dry_run: self.stdout.write(self.style.WARNING("DRY RUN — no changes will be committed.")) - # Optionnel: Synchronisation via rclone si un remote est spécifié - if rclone_remote: + # Traitement d'une archive ZIP si spécifiée + 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}'...")) os.makedirs(source_dir, exist_ok=True) rclone_cmd = ["rclone", "copy", rclone_remote, source_dir] @@ -158,13 +176,23 @@ class Command(BaseCommand): total_skipped = 0 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 possible_dirs = [ os.path.join(source_dir, structure.code), os.path.join(source_dir, f"{structure.code}_{structure.name_fr}"), 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: if os.path.isdir(p): struct_dir = p