feat: add ZIP archive support and expand structure directory matching to include location codes
This commit is contained in:
parent
0ab5fee09b
commit
04eb087cf1
1 changed files with 32 additions and 4 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue