Skip to content

Commit

Permalink
Merge pull request #9758 from CitizenLabDotCo/TAN-3332-BE-returns-fol…
Browse files Browse the repository at this point in the history
…lowed-and-all-areas-projects-if-areas-param-omitted-with-index-for-areas

[TAN-3332] BE returns followed & all-areas projects from index_for_areas if param omitted
  • Loading branch information
jinjagit authored Dec 13, 2024
2 parents 8ed8b0a + b9ab082 commit 13131f6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 51 deletions.
9 changes: 3 additions & 6 deletions back/app/controllers/web_api/v1/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,12 @@ def index_with_active_participatory_phase
end

# For use with 'Areas or topics' homepage widget. Uses ProjectMiniSerializer.
# Returns all non-draft projects that are visible to user, for the selected areas.
# If :areas param: Returns all non-draft projects that are visible to user, for the selected areas.
# Else: Returns all non-draft projects that are visible to user, for the areas user follows or for all-areas.
# Ordered by created_at, newest first.
def index_for_areas
projects = policy_scope(Project)
projects = projects.not_draft
projects = projects
.where(include_all_areas: true)
.or(projects.with_some_areas(params[:areas]))
.order(created_at: :desc)
projects = ProjectsFinderService.new(projects, current_user, params).projects_for_areas

@projects = paginate projects
@projects = @projects.includes(:project_images, phases: [:report, { permissions: [:groups] }])
Expand Down
29 changes: 29 additions & 0 deletions back/app/services/projects_finder_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def initialize(projects, user = nil, params = {})
@page_size = (params.dig(:page, :size) || 500).to_i
@page_number = (params.dig(:page, :number) || 1).to_i
@filter_by = params[:filter_by]
@areas = params[:areas]
end

# Returns an ActiveRecord collection of published projects that are
Expand Down Expand Up @@ -112,6 +113,34 @@ def followed_by_user
.order('subquery.latest_follower_created_at DESC')
end

# Returns an ActiveRecord collection of published projects, visible to user, that are also
# If :areas param: Returns all non-draft projects that are visible to user, for the selected areas.
# Else: Returns all non-draft projects that are visible to user, for the areas the user follows or for all-areas.
# Ordered by created_at, newest first.
# # => [Project]
def projects_for_areas
@projects = @projects.not_draft

projects = if @areas.present?
@projects.where(include_all_areas: true).or(@projects.with_some_areas(@areas))
else
subquery = Follower
.where(user_id: @user&.id)
.where.not(followable_type: 'Initiative')
.joins(
'LEFT JOIN areas AS followed_areas ON followers.followable_type = \'Area\' ' \
'AND followed_areas.id = followers.followable_id'
)
.joins('LEFT JOIN areas_projects ON areas_projects.area_id = followed_areas.id')
.joins('INNER JOIN projects ON areas_projects.project_id = projects.id')
.select('projects.id AS project_id')

@projects.where(include_all_areas: true).or(@projects.where(id: subquery))
end

projects.order(created_at: :desc)
end

# Returns ActiveRecord collection of projects that are either (finished OR have a last phase that contains a report)
# OR are archived, ordered by last phase end_at (nulls first), creation date second and ID third.
# => [Project]
Expand Down
48 changes: 3 additions & 45 deletions back/spec/acceptance/projects_mini_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -362,55 +362,13 @@
expect(project_ids).to match_array [project_with_areas.id, project_for_all_areas.id]
end

example 'Orders projects by created_at DESC', document: false do
project2 = create(:project)
project3 = create(:project)
create(:areas_project, project: project2, area: area1)
create(:areas_project, project: project3, area: area1)

project_with_areas.update!(created_at: 4.days.ago)
project2.update!(created_at: 1.day.ago)
project3.update!(created_at: 3.days.ago)
project_for_all_areas.update!(created_at: 2.days.ago)

do_request areas: [area1.id]
expect(status).to eq 200

project_ids = json_response[:data].pluck(:id)
expect(project_ids).to eq [project2.id, project_for_all_areas.id, project3.id, project_with_areas.id]
end

example_request 'Does not return duplicate projects when more than one areas_project matches', document: false do
do_request areas: [area1.id, area2.id]
expect(status).to eq 200

project_ids = json_response[:data].pluck(:id)
expect(project_ids).to match_array [project_with_areas.id, project_for_all_areas.id]
end

example_request 'Returns empty list when areas param is nil and no projects are for all areas', document: false do
project_for_all_areas.destroy!
example_request 'Returns projects for followed areas & for all areas when areas param is blank', document: false do
create(:follower, followable: area1, user: @user)

do_request
expect(status).to eq 200
expect(json_response[:data]).to eq []
end

context 'when admin' do
before do
@user = create(:admin)
header_token_for @user
end

example 'Does not include draft projects', document: false do
project_with_areas.update!(admin_publication_attributes: { publication_status: 'draft' })

do_request areas: [area1.id]
expect(status).to eq 200

project_ids = json_response[:data].pluck(:id)
expect(project_ids).to eq [project_for_all_areas.id]
end
expect(json_response[:data].pluck(:id)).to match_array [project_for_all_areas.id, project_with_areas.id]
end
end

Expand Down
58 changes: 58 additions & 0 deletions back/spec/services/projects_finder_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -401,4 +401,62 @@
end
end
end

describe 'projects_for_areas' do
let!(:area1) { create(:area) }
let!(:area2) { create(:area) }
let!(:project_with_areas) { create(:project_with_active_ideation_phase) }
let!(:_areas_project1) { create(:areas_project, project: project_with_areas, area: area1) }
let!(:_areas_project2) { create(:areas_project, project: project_with_areas, area: area2) }

let!(:project_for_all_areas) { create(:project_with_active_ideation_phase, include_all_areas: true) }

let!(:_project_without_area) { create(:project) }

it 'Lists projects for a given area OR for all areas' do
result = service.new(Project.all, user, { areas: [area1.id] }).projects_for_areas

expect(Project.count).to eq 3
expect(result).to match_array [project_with_areas, project_for_all_areas]
end

it 'Orders projects by created_at DESC' do
project2 = create(:project)
project3 = create(:project)
create(:areas_project, project: project2, area: area1)
create(:areas_project, project: project3, area: area1)

project_with_areas.update!(created_at: 4.days.ago)
project2.update!(created_at: 1.day.ago)
project3.update!(created_at: 3.days.ago)
project_for_all_areas.update!(created_at: 2.days.ago)

result = service.new(Project.all, user, { areas: [area1.id] }).projects_for_areas

expect(result).to eq [project2, project_for_all_areas, project3, project_with_areas]
end

it 'Does not return duplicate projects when more than one areas_project matches' do
result = service.new(Project.all, user, { areas: [area1.id, area2.id] }).projects_for_areas

expect(result).to eq [project_for_all_areas, project_with_areas]
end

it 'Returns projects for followed areas & for all areas when areas param is nil' do
create(:follower, followable: area1, user: user)

result = service.new(Project.all, user, {}).projects_for_areas

expect(result).to match_array [project_with_areas, project_for_all_areas]
end

it 'Does not include draft projects, even for an admin' do
user = create(:admin)
project_with_areas.update!(admin_publication_attributes: { publication_status: 'draft' })

result = service.new(Project.all, user, { areas: [area1.id] }).projects_for_areas

expect(result).to eq [project_for_all_areas]
end
end
end

0 comments on commit 13131f6

Please sign in to comment.