fix: add legacy file fallback and use atomic transactions for document creation
This commit is contained in:
parent
55cad6d6cc
commit
c7c76f28dc
2 changed files with 109 additions and 90 deletions
|
|
@ -731,9 +731,21 @@ class DocumentFolderAttachment(models.Model):
|
||||||
def duplicate_file(field):
|
def duplicate_file(field):
|
||||||
if not field:
|
if not field:
|
||||||
return None
|
return None
|
||||||
file_name = os.path.basename(field.name)
|
try:
|
||||||
with field.open("rb") as f:
|
file_name = os.path.basename(field.name)
|
||||||
return ContentFile(f.read(), name=file_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):
|
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()
|
context_object = instance.get_document_context()
|
||||||
title = instance.get_document_title()
|
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)
|
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:
|
if should_create_version:
|
||||||
new_file = duplicate_file(instance.file)
|
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(
|
with transaction.atomic():
|
||||||
document=managed,
|
if managed is None:
|
||||||
file=new_file,
|
managed = ManagedDocument.objects.create(
|
||||||
thumbnail=thumbnail_file,
|
title=title,
|
||||||
uploaded_by=getattr(instance, "uploaded_by", None),
|
description=getattr(instance, "description", "") or "",
|
||||||
description=getattr(instance, "description", "") or "",
|
created_by=getattr(instance, "uploaded_by", None),
|
||||||
comment=_("Version synchronised from legacy module"),
|
)
|
||||||
status=DocumentVersion.STATUS_APPROVED,
|
instance.__class__.objects.filter(pk=instance.pk).update(managed_document=managed)
|
||||||
validated_at=timezone.now(),
|
instance.managed_document = managed
|
||||||
)
|
|
||||||
version.save()
|
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:
|
elif managed.current_version is None:
|
||||||
managed.touch(managed.versions.order_by("-version_number").first())
|
managed.touch(managed.versions.order_by("-version_number").first())
|
||||||
|
|
|
||||||
|
|
@ -331,56 +331,57 @@ class DocumentManagementService:
|
||||||
"message": _("New version added to existing document."),
|
"message": _("New version added to existing document."),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
# Déterminer la visibilité
|
with transaction.atomic():
|
||||||
if visibility is None:
|
# Déterminer la visibilité
|
||||||
if content_object and getattr(getattr(content_object, '_meta', None), 'model_name', None) == 'project':
|
if visibility is None:
|
||||||
doc_visibility = VisibilityScope.SCOPED
|
if content_object and getattr(getattr(content_object, '_meta', None), 'model_name', None) == 'project':
|
||||||
elif target_folder and getattr(target_folder, 'visibility', None) == VisibilityScope.SCOPED:
|
doc_visibility = VisibilityScope.SCOPED
|
||||||
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:
|
else:
|
||||||
doc_visibility = VisibilityScope.INTERNAL
|
doc_visibility = visibility
|
||||||
else:
|
|
||||||
doc_visibility = visibility
|
|
||||||
|
|
||||||
# Créer un nouveau document
|
# Créer un nouveau document
|
||||||
doc_title = title or (file.name if hasattr(file, "name") else _("Document"))
|
doc_title = title or (file.name if hasattr(file, "name") else _("Document"))
|
||||||
|
|
||||||
document = ManagedDocument.objects.create(
|
document = ManagedDocument.objects.create(
|
||||||
title=doc_title,
|
title=doc_title,
|
||||||
description=description or "",
|
description=description or "",
|
||||||
created_by=user,
|
created_by=user,
|
||||||
unique_params=normalized_params,
|
unique_params=normalized_params,
|
||||||
visibility=doc_visibility,
|
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},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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 {
|
return {
|
||||||
"document": document,
|
"document": document,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue