diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 9b8c4de0..2b46dcb8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -90,9 +90,9 @@ def show @provenance_events = project.provenance_events.where.not(event_type: ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE) @project_status = project.metadata[:status] - @approve_status = Project::APPROVE_STATUS + @approved_status = Project::APPROVED_STATUS @eligible_editor = eligible_editor? - @project_eligible_to_edit = true if @project_status == @approve_status && eligible_editor? + @project_eligible_to_edit = true if @project_status == @approved_status && eligible_editor? respond_to do |format| format.html @@ -107,10 +107,10 @@ def show def edit project - if project.metadata[:status] != Project::APPROVE_STATUS + if project.metadata[:status] != Project::APPROVED_STATUS flash[:notice] = "Pending projects can not be edited." redirect_to project - elsif project.metadata[:status] == Project::APPROVE_STATUS && !eligible_editor? #check if the current user is a sponsor of manager + elsif project.metadata[:status] == Project::APPROVED_STATUS && !eligible_editor? #check if the current user is a sponsor of manager flash[:notice] = "Only data sponsors and data managers can revise this project." redirect_to project end @@ -121,7 +121,7 @@ def update #Approve action if params.key?("mediaflux_id") project.mediaflux_id = params["mediaflux_id"] - project.metadata_json["status"] = Project::APPROVE_STATUS + project.metadata_json["status"] = Project::APPROVED_STATUS project_metadata = ProjectMetadata.new(project: project, current_user:) project_params = params.dup project_metadata.approve_project(params: project_params) diff --git a/app/models/project.rb b/app/models/project.rb index b1216343..16f147e3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -3,9 +3,12 @@ class Project < ApplicationRecord validates_with ProjectValidator has_many :provenance_events, dependent: :destroy - # TODO: What are the valid statuses? + # Valid project status described in ADR 7 + # See `architecture-decisions/0007-valid-project-statuses.md` PENDING_STATUS = "pending" - APPROVE_STATUS = "active" + APPROVED_STATUS = "approved" + ACTIVE_STATUS = "active" + delegate :to_json, to: :metadata_json def metadata diff --git a/app/models/provenance_event.rb b/app/models/provenance_event.rb index df3ac7d1..10fc0f80 100644 --- a/app/models/provenance_event.rb +++ b/app/models/provenance_event.rb @@ -2,6 +2,7 @@ class ProvenanceEvent < ApplicationRecord SUBMISSION_EVENT_TYPE = "Submission" APPROVAL_EVENT_TYPE = "Approved" + ACTIVE_EVENT_TYPE = "Active" STATUS_UPDATE_EVENT_TYPE = "Status Update" belongs_to :project end diff --git a/architecture-decisions/0007-valid-project-status.md b/architecture-decisions/0007-valid-project-status.md new file mode 100644 index 00000000..39189806 --- /dev/null +++ b/architecture-decisions/0007-valid-project-status.md @@ -0,0 +1,26 @@ +# 7. Valid Statuses for a project + +Date: 2024-04-12 + +## Status + In discussion + + +## Context + + - When a project is created in the rails application — the status is recorded within the `status` field of the json-b metadata. + - It has a limited/ controlled vocabulary of valid options. + +## Decision + +- Status Options: + - `Project::PENDING_STATUS` — When a project is created, the status defaults to pending. Meaning it must be reviewed by a system administrator. + - `Project::APPROVED_STATUS` — When a project has been reviewed and approved by a system admninistrator. + - `Project::ACTIVE_STATUS` — When a project has been created in mediaflux. Also the rails Project has a `mediaflux_id` which can be queried in mediaflux. + +## Consequences + +- A system administrator has to take action in mediaflux and the rails application before a project can become active +- Approved and Active currently are distinct stages of a project, but may become the same in the future. +- There is currently no way to move backwards or downgrade a project from approved to pending or active back to approved. + diff --git a/spec/models/provenance_event_spec.rb b/spec/models/provenance_event_spec.rb index c2dc3cd5..bf3b43c0 100644 --- a/spec/models/provenance_event_spec.rb +++ b/spec/models/provenance_event_spec.rb @@ -2,25 +2,54 @@ require "rails_helper" RSpec.describe ProvenanceEvent, type: :model do - it "A submission event has the expected values" do - pe = described_class.new - pe.event_type = ProvenanceEvent::SUBMISSION_EVENT_TYPE - pe.event_details = "Requested by Joe Shmoe, 2023-01-19T12:00:00" - pe.event_person = "abc123" - pe.save + context "when a project is submitted" do + # When a project is submitted, it gets a submisssion event and a + # a status update event to mark is as pending + it "makes a provenance event recording the project submission" do + pe = described_class.new + pe.event_type = ProvenanceEvent::SUBMISSION_EVENT_TYPE + pe.event_details = "Requested by Joe Shmoe, 2023-01-19T12:00:00" + pe.event_person = "abc123" + pe.save + expect(pe.event_type).to eq(ProvenanceEvent::SUBMISSION_EVENT_TYPE) + end + it "makes a provenance event recording the status being set to pending" do + pe = described_class.new + pe.event_type = ProvenanceEvent::APPROVAL_EVENT_TYPE + pe.event_details = "Approved by Jane Doe, 2023-01-19T12:00:00" + pe.event_person = "abc123" + pe.save + expect(pe.event_type).to eq(ProvenanceEvent::APPROVAL_EVENT_TYPE) + end end - it "An approval event has the expected values" do - pe = described_class.new - pe.event_type = ProvenanceEvent::APPROVAL_EVENT_TYPE - pe.event_details = "Approved by Jane Doe, 2023-01-19T12:00:00" - pe.event_person = "abc123" - pe.save + context "when a project is approved" do + it "creates an approval event" do + pe = described_class.new + pe.event_type = ProvenanceEvent::APPROVAL_EVENT_TYPE + pe.event_details = "The Status was updated from pending to approved" + pe.event_person = "abc123" + pe.save + expect(pe.event_type).to eq(ProvenanceEvent::APPROVAL_EVENT_TYPE) + end end - it "A status update event has the expected values" do - pe = described_class.new - pe.event_type = ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE - pe.event_details = "The Status was updated from pending to approved" - pe.event_person = "abc123" - pe.save + context "when a project is made active" do + it "creates an active event type" do + pe = described_class.new + pe.event_type = ProvenanceEvent::ACTIVE_EVENT_TYPE + pe.event_details = "The Status was updated from approved to active" + pe.event_person = "abc123" + pe.save + expect(pe.event_type).to eq(ProvenanceEvent::ACTIVE_EVENT_TYPE) + end + end + context "when a project status is updated" do + it "creates a status update event" do + pe = described_class.new + pe.event_type = ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE + pe.event_details = "The Status was updated from approved to active" + pe.event_person = "abc123" + pe.save + expect(pe.event_type).to eq(ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE) + end end end diff --git a/spec/system/project_roles_spec.rb b/spec/system/project_roles_spec.rb index 737fdde1..5ee067ff 100644 --- a/spec/system/project_roles_spec.rb +++ b/spec/system/project_roles_spec.rb @@ -142,7 +142,7 @@ sign_in sponsor_user sponsor_user["eligible_sponsor"] = true sponsor_user.save! - project.metadata_json["status"] = Project::APPROVE_STATUS + project.metadata_json["status"] = Project::APPROVED_STATUS project.save! visit "/projects/#{project.id}/edit" fill_in "data_manager", with: new_data_manager.uid @@ -155,7 +155,7 @@ sign_in data_manager data_manager["eligible_sponsor"] = true data_manager.save - project.metadata_json["status"] = Project::APPROVE_STATUS + project.metadata_json["status"] = Project::APPROVED_STATUS project.save! visit "/projects/#{project.id}/edit" expect(page.find(:css, "#non-editable-data-sponsor").text).to eq sponsor_user.uid @@ -173,7 +173,7 @@ end context "Data Sponsors and Data Managers can assign Data Users" do - let(:project) { FactoryBot.create(:project, status: Project::APPROVE_STATUS) } + let(:project) { FactoryBot.create(:project, status: Project::APPROVED_STATUS) } let(:sponsor_user) { User.find_by(uid: project.metadata_json["data_sponsor"]) } let(:data_manager) { User.find_by(uid: project.metadata_json["data_manager"]) } let!(:ro_data_user) { FactoryBot.create(:user) } diff --git a/spec/system/project_show_spec.rb b/spec/system/project_show_spec.rb index fed2c7c3..115677e1 100644 --- a/spec/system/project_show_spec.rb +++ b/spec/system/project_show_spec.rb @@ -31,7 +31,7 @@ context "Navigation Buttons" do it "Shows the correct nav buttons for an approved project" do sign_in sponsor_user - project_in_mediaflux.metadata_json["status"] = Project::APPROVE_STATUS + project_in_mediaflux.metadata_json["status"] = Project::APPROVED_STATUS project_in_mediaflux.save! visit "/projects/#{project_in_mediaflux.id}" @@ -136,7 +136,7 @@ end context "system administrator" do - let(:project_in_mediaflux) { FactoryBot.create(:project, mediaflux_id: 1234, status: Project::APPROVE_STATUS, metadata: metadata) } + let(:project_in_mediaflux) { FactoryBot.create(:project, mediaflux_id: 1234, status: Project::APPROVED_STATUS, metadata: metadata) } let(:project_not_in_mediaflux) { FactoryBot.create(:project) } it "shows the sysadmin buttons for an approved project" do sign_in sysadmin_user diff --git a/spec/system/project_spec.rb b/spec/system/project_spec.rb index 95a16b03..2b2c291b 100644 --- a/spec/system/project_spec.rb +++ b/spec/system/project_spec.rb @@ -28,7 +28,7 @@ let(:mediaflux_id) { 1097 } let(:project_in_mediaflux) do project_not_in_mediaflux - project_not_in_mediaflux.metadata_json["status"] = Project::APPROVE_STATUS + project_not_in_mediaflux.metadata_json["status"] = Project::APPROVED_STATUS project_not_in_mediaflux.mediaflux_id = mediaflux_id project_not_in_mediaflux.save! project_not_in_mediaflux.reload @@ -114,7 +114,7 @@ context "a project is active" do it "redirects the user to the project details page if the user is not a sponsor or manager" do sign_in read_only - #project_in_mediaflux.metadata_json["status"] = Project::APPROVE_STATUS + #project_in_mediaflux.metadata_json["status"] = Project::APPROVED_STATUS #project_in_mediaflux.save! visit "/projects/#{project_in_mediaflux.id}/edit" @@ -124,7 +124,7 @@ before do sign_in sponsor_user - project_in_mediaflux.metadata_json["status"] = Project::APPROVE_STATUS + project_in_mediaflux.metadata_json["status"] = Project::APPROVED_STATUS project_in_mediaflux.save! visit "/projects/#{project_in_mediaflux.id}/edit" end @@ -448,7 +448,7 @@ project.reload expect(project.mediaflux_id).to eq(mediaflux_id) - expect(project.metadata_json["status"]).to eq Project::APPROVE_STATUS + expect(project.metadata_json["status"]).to eq Project::APPROVED_STATUS # redirects the user to the project show page end