Version label

This commit is contained in:
shamoon
2026-02-10 09:16:20 -08:00
parent 719582938e
commit 224a873de2
7 changed files with 87 additions and 8 deletions

View File

@@ -191,9 +191,12 @@ export class DocumentService extends AbstractPaperlessService<Document> {
return url
}
uploadVersion(documentId: number, file: File) {
uploadVersion(documentId: number, file: File, label?: string) {
const formData = new FormData()
formData.append('document', file, file.name)
if (label) {
formData.append('label', label)
}
return this.http.post(
this.getResourceUrl(documentId, 'update_version'),
formData,

View File

@@ -511,6 +511,8 @@ class ConsumerPlugin(
original_document.filename = None
original_document.archive_filename = None
original_document.archive_checksum = None
if self.metadata.version_label is not None:
original_document.version_label = self.metadata.version_label
original_document.modified = timezone.now()
original_document.save()
document = original_document
@@ -738,6 +740,9 @@ class ConsumerPlugin(
if self.metadata.asn is not None:
document.archive_serial_number = self.metadata.asn
if self.metadata.version_label is not None:
document.version_label = self.metadata.version_label
if self.metadata.owner_id:
document.owner = User.objects.get(
pk=self.metadata.owner_id,

View File

@@ -31,6 +31,7 @@ class DocumentMetadataOverrides:
change_groups: list[int] | None = None
custom_fields: dict | None = None
skip_asn_if_exists: bool = False
version_label: str | None = None
def update(self, other: "DocumentMetadataOverrides") -> "DocumentMetadataOverrides":
"""
@@ -52,6 +53,8 @@ class DocumentMetadataOverrides:
self.owner_id = other.owner_id
if other.skip_asn_if_exists:
self.skip_asn_if_exists = True
if other.version_label is not None:
self.version_label = other.version_label
# merge
if self.tag_ids is None:

View File

@@ -0,0 +1,24 @@
# Generated by Codex on 2026-02-10
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "0011_document_head_version"),
]
operations = [
migrations.AddField(
model_name="document",
name="version_label",
field=models.CharField(
blank=True,
help_text="Optional short label for a document version.",
max_length=64,
null=True,
verbose_name="version label",
),
),
]

View File

@@ -317,6 +317,14 @@ class Document(SoftDeleteModel, ModelWithOwner):
verbose_name=_("head version of document"),
)
version_label = models.CharField(
_("version label"),
max_length=64,
blank=True,
null=True,
help_text=_("Optional short label for a document version."),
)
class Meta:
ordering = ("-created",)
verbose_name = _("document")

View File

@@ -1062,6 +1062,12 @@ class DuplicateDocumentSummarySerializer(serializers.Serializer):
deleted_at = serializers.DateTimeField(allow_null=True)
class DocumentVersionInfoSerializer(serializers.Serializer):
id = serializers.IntegerField()
added = serializers.DateTimeField()
label = serializers.CharField(required=False, allow_null=True)
@extend_schema_serializer(
deprecate_fields=["created_date"],
)
@@ -1083,7 +1089,7 @@ class DocumentSerializer(
notes = NotesSerializer(many=True, required=False, read_only=True)
head_version = serializers.PrimaryKeyRelatedField(read_only=True)
versions = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
versions = SerializerMethodField()
custom_fields = CustomFieldInstanceSerializer(
many=True,
@@ -1117,6 +1123,28 @@ class DocumentSerializer(
duplicates = _get_viewable_duplicates(obj, user)
return list(duplicates.values("id", "title", "deleted_at"))
@extend_schema_field(DocumentVersionInfoSerializer(many=True))
def get_versions(self, obj):
head_doc = obj if obj.head_version_id is None else obj.head_version
versions_qs = Document.objects.filter(head_version=head_doc).only(
"id",
"added",
"checksum",
"version_label",
)
versions = [*versions_qs, head_doc]
def build_info(doc: Document) -> dict[str, object]:
return {
"id": doc.id,
"added": doc.added,
"label": doc.version_label,
}
info = [build_info(doc) for doc in versions]
info.sort(key=lambda item: item["id"], reverse=True)
return info
def get_original_file_name(self, obj) -> str | None:
return obj.original_filename
@@ -1136,10 +1164,6 @@ class DocumentSerializer(
request.version if request else settings.REST_FRAMEWORK["DEFAULT_VERSION"],
)
if doc.get("versions") is not None:
doc["versions"] = sorted(doc["versions"], reverse=True)
doc["versions"].append(doc["id"])
if api_version < 9 and "created" in self.fields:
# provide created as a datetime for backwards compatibility
from django.utils import timezone
@@ -2010,6 +2034,13 @@ class DocumentVersionSerializer(serializers.Serializer):
label="Document",
write_only=True,
)
label = serializers.CharField(
label="Version label",
required=False,
allow_blank=True,
allow_null=True,
max_length=64,
)
validate_document = PostDocumentSerializer().validate_document

View File

@@ -1471,7 +1471,7 @@ class DocumentViewSet(
"Error emailing documents, check logs for more detail.",
)
@action(methods=["post"], detail=True)
@action(methods=["post"], detail=True, parser_classes=[parsers.MultiPartParser])
def update_version(self, request, pk=None):
serializer = DocumentVersionSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
@@ -1489,6 +1489,7 @@ class DocumentViewSet(
try:
doc_name, doc_data = serializer.validated_data.get("document")
label = serializer.validated_data.get("label")
t = int(mktime(datetime.now().timetuple()))
@@ -1508,9 +1509,13 @@ class DocumentViewSet(
head_version_id=doc.pk,
)
overrides = DocumentMetadataOverrides()
if label:
overrides.version_label = label.strip()
async_task = consume_file.delay(
input_doc,
None,
overrides,
)
logger.debug(
f"Updated document {doc.id} with new version",