diff --git a/loko/documents/models.py b/loko/documents/models.py index d6800bf..24ea12a 100644 --- a/loko/documents/models.py +++ b/loko/documents/models.py @@ -731,9 +731,21 @@ class DocumentFolderAttachment(models.Model): def duplicate_file(field): if not field: return None - file_name = os.path.basename(field.name) - with field.open("rb") as f: - return ContentFile(f.read(), name=file_name) + try: + file_name = os.path.basename(field.name) + with field.open("rb") as f: + return ContentFile(f.read(), name=file_name) + except Exception: + # Fallback si le fichier historique est présent dans MEDIA_ROOT avant migration vers private storage + try: + if hasattr(settings, "MEDIA_ROOT") and field.name: + alt_path = os.path.join(settings.MEDIA_ROOT, field.name) + if os.path.exists(alt_path): + with open(alt_path, "rb") as f: + return ContentFile(f.read(), name=os.path.basename(field.name)) + except Exception: + pass + return None def ensure_document_for_legacy(instance, old_file_name=None): @@ -757,51 +769,57 @@ def ensure_document_for_legacy(instance, old_file_name=None): context_object = instance.get_document_context() title = instance.get_document_title() - if managed is None: - managed = ManagedDocument.objects.create( - title=title, - description=getattr(instance, "description", "") or "", - created_by=getattr(instance, "uploaded_by", None), - ) - instance.__class__.objects.filter(pk=instance.pk).update(managed_document=managed) - instance.managed_document = managed - - if context_object is not None: - DocumentAttachment.objects.get_or_create( - document=managed, - content_type=ContentType.objects.get_for_model(context_object), - object_id=context_object.pk, - defaults={"attached_by": getattr(instance, "uploaded_by", None)}, - ) - - if hasattr(instance, "document_type") and instance.document_type: - label = instance.document_type - if hasattr(instance, "get_document_type_display"): - label = instance.get_document_type_display() - doc_type, _created = DocumentType.objects.get_or_create( - code=slugify(instance.document_type), - defaults={"label": label}, - ) - managed.types.add(doc_type) - file_changed = bool(old_file_name and old_file_name != instance.file.name) - should_create_version = not managed.versions.exists() or file_changed + should_create_version = (managed is None) or not managed.versions.exists() or file_changed if should_create_version: new_file = duplicate_file(instance.file) - thumbnail_file = duplicate_file(getattr(instance, "thumbnail", None)) + if not new_file: + # Ne pas créer de ManagedDocument orphelin si le fichier physique est inaccessible + return - version = DocumentVersion( - document=managed, - file=new_file, - thumbnail=thumbnail_file, - uploaded_by=getattr(instance, "uploaded_by", None), - description=getattr(instance, "description", "") or "", - comment=_("Version synchronised from legacy module"), - status=DocumentVersion.STATUS_APPROVED, - validated_at=timezone.now(), - ) - version.save() + with transaction.atomic(): + if managed is None: + managed = ManagedDocument.objects.create( + title=title, + description=getattr(instance, "description", "") or "", + created_by=getattr(instance, "uploaded_by", None), + ) + instance.__class__.objects.filter(pk=instance.pk).update(managed_document=managed) + instance.managed_document = managed + + if context_object is not None: + DocumentAttachment.objects.get_or_create( + document=managed, + content_type=ContentType.objects.get_for_model(context_object), + object_id=context_object.pk, + defaults={"attached_by": getattr(instance, "uploaded_by", None)}, + ) + + if hasattr(instance, "document_type") and instance.document_type: + label = instance.document_type + if hasattr(instance, "get_document_type_display"): + label = instance.get_document_type_display() + doc_type, _created = DocumentType.objects.get_or_create( + code=slugify(instance.document_type), + defaults={"label": label}, + ) + managed.types.add(doc_type) + + thumbnail_file = duplicate_file(getattr(instance, "thumbnail", None)) + + version = DocumentVersion( + document=managed, + file=new_file, + thumbnail=thumbnail_file, + uploaded_by=getattr(instance, "uploaded_by", None), + description=getattr(instance, "description", "") or "", + comment=_("Version synchronised from legacy module"), + status=DocumentVersion.STATUS_APPROVED, + validated_at=timezone.now(), + ) + version.save() + managed.touch(version) elif managed.current_version is None: managed.touch(managed.versions.order_by("-version_number").first()) diff --git a/loko/documents/services.py b/loko/documents/services.py index 0946f1d..236119a 100644 --- a/loko/documents/services.py +++ b/loko/documents/services.py @@ -331,56 +331,57 @@ class DocumentManagementService: "message": _("New version added to existing document."), } else: - # Déterminer la visibilité - if visibility is None: - if content_object and getattr(getattr(content_object, '_meta', None), 'model_name', None) == 'project': - doc_visibility = VisibilityScope.SCOPED - elif target_folder and getattr(target_folder, 'visibility', None) == VisibilityScope.SCOPED: - doc_visibility = VisibilityScope.SCOPED + with transaction.atomic(): + # Déterminer la visibilité + if visibility is None: + if content_object and getattr(getattr(content_object, '_meta', None), 'model_name', None) == 'project': + doc_visibility = VisibilityScope.SCOPED + elif target_folder and getattr(target_folder, 'visibility', None) == VisibilityScope.SCOPED: + doc_visibility = VisibilityScope.SCOPED + else: + doc_visibility = VisibilityScope.INTERNAL else: - doc_visibility = VisibilityScope.INTERNAL - else: - doc_visibility = visibility + doc_visibility = visibility - # Créer un nouveau document - doc_title = title or (file.name if hasattr(file, "name") else _("Document")) - - document = ManagedDocument.objects.create( - title=doc_title, - description=description or "", - created_by=user, - unique_params=normalized_params, - visibility=doc_visibility, - ) - - # Ajouter le tag - if tag: - document.tags.add(tag) - - # Ajouter au répertoire - if target_folder: - document.folders.add(target_folder) - - # Créer la première version - version = DocumentVersion( - document=document, - file=file, - uploaded_by=user, - description=description or "", - comment=_("Initial version"), - status=DocumentVersion.STATUS_PENDING, - ) - version.save() - - # Attacher à l'objet de contexte si fourni - if content_object: - content_type = ContentType.objects.get_for_model(content_object) - DocumentAttachment.objects.get_or_create( - document=document, - content_type=content_type, - object_id=content_object.pk, - defaults={"attached_by": user}, + # Créer un nouveau document + doc_title = title or (file.name if hasattr(file, "name") else _("Document")) + + document = ManagedDocument.objects.create( + title=doc_title, + description=description or "", + created_by=user, + unique_params=normalized_params, + visibility=doc_visibility, ) + + # Ajouter le tag + if tag: + document.tags.add(tag) + + # Ajouter au répertoire + if target_folder: + document.folders.add(target_folder) + + # Créer la première version + version = DocumentVersion( + document=document, + file=file, + uploaded_by=user, + description=description or "", + comment=_("Initial version"), + status=DocumentVersion.STATUS_PENDING, + ) + version.save() + + # Attacher à l'objet de contexte si fourni + if content_object: + content_type = ContentType.objects.get_for_model(content_object) + DocumentAttachment.objects.get_or_create( + document=document, + content_type=content_type, + object_id=content_object.pk, + defaults={"attached_by": user}, + ) return { "document": document,