feat: add rclone support to import command and implement duplicate document skipping during sync
This commit is contained in:
parent
dda68cabec
commit
0ab5fee09b
1 changed files with 43 additions and 9 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import subprocess
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.auth import get_user_model
|
||||
|
|
@ -15,15 +16,20 @@ User = get_user_model()
|
|||
|
||||
class Command(BaseCommand):
|
||||
help = (
|
||||
"Imports As-Built documents from a local directory into the "
|
||||
"'Electromechanics / As-Built' subfolder of specified structures."
|
||||
"Imports As-Built documents from a local directory or via rclone from OneDrive "
|
||||
"into the 'Electromechanics / As-Built' subfolder of specified structures."
|
||||
)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"--source-dir",
|
||||
required=True,
|
||||
help="Path to the 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(
|
||||
"--rclone-remote",
|
||||
default=None,
|
||||
help="Optional rclone remote path (e.g. 'onedrive:DPO_TUNNEL_EM_AS-BUILT') to sync before import.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--structures",
|
||||
|
|
@ -49,17 +55,32 @@ class Command(BaseCommand):
|
|||
|
||||
def handle(self, *args, **options):
|
||||
source_dir = options["source_dir"]
|
||||
rclone_remote = options["rclone_remote"]
|
||||
target_codes = options["structures"]
|
||||
dry_run = options["dry_run"]
|
||||
username = options["user"]
|
||||
tag_name = options["tag"]
|
||||
|
||||
if not os.path.isdir(source_dir):
|
||||
raise CommandError(f"Source directory '{source_dir}' does not exist or is not a directory.")
|
||||
|
||||
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:
|
||||
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]
|
||||
rclone_conf = os.path.join(os.getcwd(), "rclone.conf")
|
||||
if os.path.exists(rclone_conf):
|
||||
rclone_cmd.extend(["--config", rclone_conf])
|
||||
|
||||
res = subprocess.run(rclone_cmd, capture_output=True, text=True)
|
||||
if res.returncode != 0:
|
||||
raise CommandError(f"rclone sync failed:\n{res.stderr}")
|
||||
self.stdout.write(self.style.SUCCESS("rclone sync completed successfully."))
|
||||
|
||||
if not os.path.isdir(source_dir):
|
||||
raise CommandError(f"Source directory '{source_dir}' does not exist or is not a directory.")
|
||||
|
||||
# Creator user lookup
|
||||
creator_user = None
|
||||
if username:
|
||||
|
|
@ -134,6 +155,7 @@ class Command(BaseCommand):
|
|||
structures = Structure.objects.all()
|
||||
|
||||
total_imported = 0
|
||||
total_skipped = 0
|
||||
|
||||
for structure in structures:
|
||||
# Check if there is a dedicated subfolder for this structure code or name in source_dir
|
||||
|
|
@ -173,12 +195,24 @@ class Command(BaseCommand):
|
|||
continue
|
||||
|
||||
self.stdout.write(f" Target subfolder: Electromechanics / As-Built (ID: {as_built_folder.pk or 'dry-run'})")
|
||||
self.stdout.write(f" Found {len(files_to_import)} file(s) to import.")
|
||||
self.stdout.write(f" Found {len(files_to_import)} file(s) to process.")
|
||||
|
||||
for file_path in files_to_import:
|
||||
rel_name = os.path.basename(file_path)
|
||||
doc_title = os.path.splitext(rel_name)[0]
|
||||
|
||||
# Deduplication check
|
||||
if as_built_folder.pk:
|
||||
existing_doc = ManagedDocument.objects.filter(
|
||||
folders=as_built_folder,
|
||||
title=doc_title,
|
||||
is_archived=False
|
||||
).first()
|
||||
if existing_doc:
|
||||
self.stdout.write(f" Document '{rel_name}' already exists in As-Built folder (Doc ID: {existing_doc.pk}). Skipped.")
|
||||
total_skipped += 1
|
||||
continue
|
||||
|
||||
if dry_run:
|
||||
self.stdout.write(f" [Dry-run] Would import '{rel_name}' into structure {structure.code}")
|
||||
total_imported += 1
|
||||
|
|
@ -216,4 +250,4 @@ class Command(BaseCommand):
|
|||
self.stdout.write(self.style.SUCCESS(f" Imported '{rel_name}' (Doc ID: {doc.pk})"))
|
||||
total_imported += 1
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f"\nDone! Total documents imported: {total_imported}"))
|
||||
self.stdout.write(self.style.SUCCESS(f"\nDone! Imported: {total_imported}, Skipped (already imported): {total_skipped}"))
|
||||
|
|
|
|||
Loading…
Reference in a new issue