Skip to content

Commit

Permalink
[BUG FIX] [MER-4178] [MER-4186] Fix required survey issues (#5363)
Browse files Browse the repository at this point in the history
* fix required survey issues

* Auto format

---------

Co-authored-by: darrensiegel <[email protected]>
  • Loading branch information
darrensiegel and darrensiegel authored Jan 21, 2025
1 parent 1960a4e commit 92adcb8
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 17 deletions.
73 changes: 56 additions & 17 deletions lib/oli/delivery/sections/updates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ defmodule Oli.Delivery.Sections.Updates do
end

PostProcessing.apply(section, :all)

Oli.Delivery.maybe_update_section_contains_explorations(section)
Oli.Delivery.maybe_update_section_contains_deliberate_practice(section)
end

# Implements the logic to determine *how* to apply the update to the course section,
Expand Down Expand Up @@ -179,6 +176,44 @@ defmodule Oli.Delivery.Sections.Updates do
end
end

def ensure_section_resource_exists(_section_slug, nil), do: {:ok, :exists}

def ensure_section_resource_exists(section_slug, resource_id) do
case Oli.Publishing.DeliveryResolver.from_resource_id(section_slug, resource_id) do
nil ->
# Fetch the published revision of this revision along with section and project id
query =
Oli.Delivery.Sections.SectionsProjectsPublications
|> join(:left, [spp], pr in Oli.Publishing.PublishedResource,
on: pr.publication_id == spp.publication_id
)
|> join(:left, [_, pr], rev in Oli.Resources.Revision, on: rev.id == pr.revision_id)
|> join(:left, [spp, _, _], s in Oli.Delivery.Sections.Section,
on: s.id == spp.section_id
)
|> where([spp, pr, rev, s], s.slug == ^section_slug and pr.resource_id == ^resource_id)
|> select([spp, _pr, rev, section], %{
revision: rev,
section: section,
project_id: spp.project_id
})
|> limit(1)

case Repo.one(query) do
nil ->
{:error, :not_found}

# Create the section resource record, using the exact same logic used in creating SR records
# during publication application
%{revision: revision, section: section, project_id: project_id} ->
bulk_create_section_resources([revision], section, project_id)
end

_ ->
{:ok, :exists}
end
end

# Add all and delete all SR records that were added/deleted in the publication diff
defp add_remove_srs(%PublicationDiff{} = diff, section, project_id) do
case diff
Expand Down Expand Up @@ -373,22 +408,26 @@ defmodule Oli.Delivery.Sections.Updates do
end)
|> List.flatten()

project = Oli.Authoring.Course.get_project!(publication.project_id)

# Determine the unreachable page resource ids, but taking into account if
# EITHER the project or the section has a required survey resource id to
# ensure that it never gets culled.
additional_excluded_ids =
[section.required_survey_resource_id, project.required_survey_resource_id]
|> Enum.filter(&(&1 != nil))
|> MapSet.new()

# Determine the unreachable page resource ids based strictly on hierarchy navigability
unreachable_page_resource_ids =
case section.required_survey_resource_id do
nil ->
Oli.Delivery.Sections.determine_unreachable_pages(
[publication.id],
hierarchy_ids,
all_links
)
Oli.Delivery.Sections.determine_unreachable_pages(
[publication.id],
hierarchy_ids,
all_links
)

id ->
Oli.Delivery.Sections.determine_unreachable_pages(
[publication.id],
[id | hierarchy_ids],
all_links
)
end
# But filter out any additional excluded resource ids (like required surveys)
|> Enum.filter(fn id -> !Enum.member?(additional_excluded_ids, id) end)

project_id = publication.project_id

Expand Down
8 changes: 8 additions & 0 deletions lib/oli_web/live/delivery/student_onboarding/survey.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ defmodule OliWeb.Delivery.StudentOnboarding.Survey do
survey = assigns.survey
datashop_session_id = assigns.datashop_session_id

# Just in time addition of the survey to the course section's section resources.
# This was needed due to a hotfix bug that was causing the survey to not be added
# to the section resources at publication application time.
Oli.Delivery.Sections.Updates.ensure_section_resource_exists(
section.slug,
section.required_survey_resource_id
)

context =
Oli.Delivery.Page.PageContext.create_for_visit(
section,
Expand Down
4 changes: 4 additions & 0 deletions lib/oli_web/plugs/force_required_survey.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ defmodule Oli.Plugs.ForceRequiredSurvey do
section_slug = conn.assigns.section.slug
user = conn.assigns[:current_user]

# Just in time, make sure the section resource record exists
survey_id = conn.assigns.section.required_survey_resource_id
Oli.Delivery.Sections.Updates.ensure_section_resource_exists(section_slug, survey_id)

has_completed_survey =
Oli.Delivery.has_completed_survey?(section_slug, user.id) or
Sections.is_instructor?(user, section_slug)
Expand Down
112 changes: 112 additions & 0 deletions test/oli/delivery/sections/ensure_resource_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
defmodule Oli.Delivery.Sections.SectionResourceDepotTest do
use Oli.DataCase

import Ecto.Query
import Oli.Factory

alias Oli.Delivery.Sections
alias Oli.Delivery.Sections.SectionResource
alias Oli.Delivery.Sections.Updates
alias Oli.Resources.ResourceType

describe "ensure resource exists" do
setup [:create_project]

test "gets hierarchy and triggers Depot", ctx do
%{
section: %{id: section_id} = section,
page_1_revision: page_1_revision
} = ctx

# Verify that when the resource exists, it doesn't get created again
{:ok, :exists} =
Updates.ensure_section_resource_exists(section.slug, page_1_revision.resource_id)

# simulate a missing SR by deleting it
Oli.Repo.delete_all(
from(sr in SectionResource,
where: sr.section_id == ^section_id and sr.resource_id == ^page_1_revision.resource_id
)
)

# Ensure the resource gets created
{:ok, count_created} =
Updates.ensure_section_resource_exists(section.slug, page_1_revision.resource_id)

assert count_created == 1
end
end

defp create_project(_) do
# Revisions tree
page_1_revision =
insert(:revision,
resource_type_id: ResourceType.id_for_page(),
title: "Page 1"
)

# Graded page
page_2_revision =
insert(:revision,
resource_type_id: ResourceType.id_for_page(),
title: "Page 2",
graded: true
)

module_1_revision =
insert(:revision,
resource_type_id: ResourceType.id_for_container(),
children: [page_1_revision.resource_id, page_2_revision.resource_id],
title: "Module 1"
)

# Root container
container_revision =
insert(:revision,
resource_type_id: ResourceType.id_for_container(),
title: "Root Container",
children: [module_1_revision.resource_id]
)

instructor = insert(:user)
project = insert(:project, authors: [instructor.author])

all_revisions = [container_revision, module_1_revision, page_1_revision, page_2_revision]

# Asociate resources to project
Enum.each(all_revisions, fn revision ->
insert(:project_resource, %{
project_id: project.id,
resource_id: revision.resource_id
})
end)

# Publish project
publication =
insert(:publication, %{project: project, root_resource_id: container_revision.resource_id})

# Publish resources
Enum.each(all_revisions, fn revision ->
insert(:published_resource, %{
publication: publication,
resource: revision.resource,
revision: revision,
author: instructor.author
})
end)

# Create section
section = insert(:section, base_project: project, title: "The Project")

# Create section-resources
{:ok, section} = Sections.create_section_resources(section, publication)

%{
section: section,
container_revision: container_revision,
module_1_revision: module_1_revision,
page_1_revision: page_1_revision,
page_2_revision: page_2_revision
}
end
end

0 comments on commit 92adcb8

Please sign in to comment.