From 485c2a99fa3c672a9040fc66e45f180735d5c786 Mon Sep 17 00:00:00 2001 From: Zacharias Zacharodimos Date: Fri, 6 Oct 2023 16:14:16 +0200 Subject: [PATCH] service: fix restore/delete of specific record version --- invenio_rdm_records/records/api.py | 36 ++++++++++++++++++++++++ invenio_rdm_records/services/services.py | 29 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/invenio_rdm_records/records/api.py b/invenio_rdm_records/records/api.py index a2ee375a31..d9814bb1d6 100644 --- a/invenio_rdm_records/records/api.py +++ b/invenio_rdm_records/records/api.py @@ -10,6 +10,7 @@ from flask import g from invenio_communities.records.records.systemfields import CommunitiesField +from invenio_db import db from invenio_drafts_resources.records import Draft, Record from invenio_drafts_resources.records.api import ParentRecord as ParentRecordBase from invenio_drafts_resources.services.records.components.media_files import ( @@ -40,6 +41,10 @@ from invenio_vocabularies.records.api import Vocabulary from invenio_vocabularies.records.systemfields.relations import CustomFieldsRelation +from invenio_rdm_records.records.systemfields.deletion_status import ( + RecordDeletionStatusEnum, +) + from . import models from .dumpers import ( EDTFDumperExt, @@ -445,6 +450,37 @@ class RDMRecord(CommonFieldsMixin, Record): tombstone = TombstoneField() + @classmethod + def next_latest_published_record_by_parent(cls, parent): + """Get the next latest published record. + + This method gives back the next published latest record by parent or None if all + records are deleted i.e `record.deletion_status != 'P'`. + + :param parent: parent record. + :param excluded_latest: latest record to exclude find next published version + """ + + with db.session.no_autoflush: + rec_model_query = ( + cls.model_cls.query.filter_by(parent_id=parent.id) + .filter( + cls.model_cls.deletion_status + == RecordDeletionStatusEnum.PUBLISHED.value + ) + .order_by(cls.model_cls.index.desc()) + ) + current_latest_id = cls.get_latest_by_parent(parent, id_only=True) + if current_latest_id: + rec_model_query.filter(cls.model_cls.id != current_latest_id) + + rec_model = rec_model_query.first() + return ( + cls(rec_model.data, model=rec_model, parent=parent) + if rec_model + else None + ) + RDMFileRecord.record_cls = RDMRecord diff --git a/invenio_rdm_records/services/services.py b/invenio_rdm_records/services/services.py index 9a9debd4db..f5b795e1c0 100644 --- a/invenio_rdm_records/services/services.py +++ b/invenio_rdm_records/services/services.py @@ -184,9 +184,24 @@ def delete_record( "delete_record", identity, data=data, record=record, uow=uow ) + new_record_latest_version = None + if record.versions.is_latest == True: + # set latest to the previous non deleted record + new_record_latest_version = ( + self.record_cls.next_latest_published_record_by_parent(record.parent) + ) + if new_record_latest_version: + new_record_latest_version.versions.set_latest() + # Commit and reindex record uow.register(RecordCommitOp(record, indexer=self.indexer)) + # Commit and reindex new latest record + if new_record_latest_version: + uow.register( + RecordCommitOp(new_record_latest_version, indexer=self.indexer) + ) + return self.result_item( self, identity, @@ -258,9 +273,23 @@ def restore_record(self, identity, id_, expand=False, uow=None): # Run components self.run_components("restore_record", identity, record=record, uow=uow) + # set latest to the previous non deleted record + latest_record_version = self.record_cls.get_latest_by_parent(record.parent) + + if not latest_record_version: + # if all records were deleted then make the restored record latest + record.versions.set_latest() + elif record.versions.index > latest_record_version.versions.index: + # set current restored record as latest + record.versions.set_latest() + # Commit and reindex record uow.register(RecordCommitOp(record, indexer=self.indexer)) + # commit and reindex the old latest record + if latest_record_version and record.id != latest_record_version.id: + uow.register(RecordCommitOp(latest_record_version, indexer=self.indexer)) + return self.result_item( self, identity,