Skip to content

Commit

Permalink
fixup! feat: option to include deleted drafts while fetching unpublis…
Browse files Browse the repository at this point in the history
…hed entities
  • Loading branch information
navinkarkera committed Aug 16, 2024
1 parent 46da6c8 commit dfe7691
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 5 deletions.
26 changes: 21 additions & 5 deletions openedx_learning/apps/authoring/publishing/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from datetime import datetime, timezone

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import F, QuerySet
from django.db.models import F, Q, QuerySet
from django.db.transaction import atomic

from .model_mixins import PublishableContentModelRegistry, PublishableEntityMixin, PublishableEntityVersionMixin
Expand Down Expand Up @@ -226,10 +226,26 @@ def get_entities_with_unpublished_changes(
By default, this excludes soft-deleted drafts but can be included using include_deleted_drafts option.
"""
query_filters = {"learning_package_id": learning_package_id}
if not include_deleted_drafts:
query_filters['draft__version__isnull'] = False
return PublishableEntity.objects.filter(**query_filters).exclude(draft__version=F('published__version'))
entities_qs = (
PublishableEntity.objects
.filter(learning_package_id=learning_package_id)
.exclude(draft__version=F('published__version'))
)

if include_deleted_drafts:
# This means that we should also return PublishableEntities where the draft
# has been soft-deleted, but that deletion has not been published yet. Just
# excluding records where the Draft and Published versions don't match won't
# be enough here, because that will return soft-deletes that have already
# been published (since NULL != NULL in SQL).
#
# So we explicitly exclude already-published soft-deletes:
return entities_qs.exclude(
Q(draft__version__isnull=True) & Q(published__version__isnull=True)
)

# Simple case: exclude all entities that have been soft-deleted.
return entities_qs.exclude(draft__version__isnull=True)


def get_entities_with_unpublished_deletes(learning_package_id: int, /) -> QuerySet[PublishableEntity]:
Expand Down
41 changes: 41 additions & 0 deletions tests/openedx_learning/apps/authoring/publishing/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,47 @@ def test_reset_drafts_to_published(self) -> None:
pub_version_num
)

def test_get_entities_with_unpublished_changes(self) -> None:
"""Test fetching entities with unpublished changes after soft deletes."""
entity = publishing_api.create_publishable_entity(
self.learning_package.id,
"my_entity",
created=self.now,
created_by=None,
)
entity_version = publishing_api.create_publishable_entity_version(
entity.id,
version_num=1,
title="An Entity 🌴",
created=self.now,
created_by=None,
)

# Fetch unpublished entities
entities = publishing_api.get_entities_with_unpublished_changes(self.learning_package.id)
records = list(entities.all())
assert len(records) == 1
record = records[0]
assert record.id == entity.id

# Initial publish
publishing_api.publish_all_drafts(self.learning_package.id)

# soft-delete entity
publishing_api.soft_delete_draft(entity.id)
entities = publishing_api.get_entities_with_unpublished_changes(self.learning_package.id)
assert len(entities) == 0
entities = publishing_api.get_entities_with_unpublished_changes(self.learning_package.id,
include_deleted_drafts=True)
assert len(entities) == 1

# publish soft-delete
publishing_api.publish_all_drafts(self.learning_package.id)
entities = publishing_api.get_entities_with_unpublished_changes(self.learning_package.id,
include_deleted_drafts=True)
# should not return published soft-deleted entities.
assert len(entities) == 0

def _get_published_version_num(self, entity: PublishableEntity) -> int | None:
published_version = publishing_api.get_published_version(entity.id)
if published_version is not None:
Expand Down

0 comments on commit dfe7691

Please sign in to comment.