diff --git a/README.md b/README.md index ff5e44d7..253ea769 100644 --- a/README.md +++ b/README.md @@ -34,16 +34,28 @@ docker-compose run -e "RAILS_ENV=test" app rake spec ``` ## Routes: +`GET /:repo/objects/:druid/lifecycle` - Returns the milestones in the lifecycle that have been completed + + +`POST /:repo/objects/:druid/versionClose` - Set all versioningWF steps to 'complete' and starts a new accessionWF unless `create-accession=false` is passed as a parameter. + + +These methods deal with the workflow for a single object ``` -GET /:repo/objects/:druid/lifecycle -POST /:repo/objects/:druid/versionClose PUT /:repo/objects/:druid/workflows/:workflow PUT /:repo/objects/:druid/workflows/:workflow/:process GET /:repo/objects/:druid/workflows GET /:repo/objects/:druid/workflows/:workflow DELETE /:repo/objects/:druid/workflows/:workflow -GET /workflow_archive +``` + +`GET /workflow_archive` - Deprecated. Currently just returns a count of the number of items/versions for the workflow + +These processes are used by robot-master to discover which steps need to be performed. +``` GET /workflow_queue/lane_ids GET /workflow_queue/all_queued GET /workflow_queue ``` + +`GET /workflow/:workflow` - Returns aggregate data of number of active processes in each workflow step diff --git a/app/controllers/status_controller.rb b/app/controllers/status_controller.rb new file mode 100644 index 00000000..0134a90e --- /dev/null +++ b/app/controllers/status_controller.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +## +# API for handling requests about the state of all objects in a workflow +class StatusController < ApplicationController + def show + workflow_name = params.require(:workflow) + @result = status_response(workflow_name) + + render json: { steps: @result } + end + + private + + def status_response(workflow_name) + tree = steps_for_workflow(workflow_name) + xml = WorkflowTemplateService.template_for(workflow_name) + processes = WorkflowParser.new(xml).processes + step_names = processes.map(&:process) + step_names.map do |process_name| + { name: process_name, object_status: tree.fetch(process_name, {}) } + end + end + + # Returns a hash of counts of objects in each step and status: + # @example + # {"start-accession"=>{"completed"=>1} + def steps_for_workflow(workflow) + counts = WorkflowStep.active.where(workflow: workflow).group(:process, :status).count + {}.tap do |tree| + counts.each do |(step, status), val| + tree[step] ||= {} + tree[step][status] = val + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index e764f9f3..47025d4a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,4 +25,6 @@ get 'all_queued' end end + + get '/workflow/:workflow', to: 'status#show', defaults: { format: :json } end diff --git a/spec/requests/workflow_status_spec.rb b/spec/requests/workflow_status_spec.rb new file mode 100644 index 00000000..0e9e3f12 --- /dev/null +++ b/spec/requests/workflow_status_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Get the status for a workflow', type: :request do + include XmlFixtures + + before do + allow(WorkflowTemplateService).to receive(:template_for).and_return(workflow_create) + end + + context 'for all workflows' do + before do + FactoryBot.create(:workflow_step, + status: 'completed', + active_version: true) + + FactoryBot.create(:workflow_step, + status: 'completed', + active_version: true) + + FactoryBot.create(:workflow_step, + status: 'waiting', + active_version: true) + + FactoryBot.create(:workflow_step, + status: 'waiting', + active_version: false) + + FactoryBot.create(:workflow_step, + status: 'error', + process: 'descriptive-metadata', + active_version: true) + + FactoryBot.create(:workflow_step, + status: 'error', + process: 'descriptive-metadata', + active_version: true) + + FactoryBot.create(:workflow_step, + status: 'waiting', + process: 'descriptive-metadata', + active_version: true) + end + + it 'displays the counts' do + get '/workflow/accessionWF' + expect(response).to be_successful + expect(JSON.parse(response.body)).to eq( + 'steps' => [ + { 'name' => 'start-accession', + 'object_status' => { 'completed' => 2, 'waiting' => 1 } }, + { 'name' => 'descriptive-metadata', + 'object_status' => { 'error' => 2, 'waiting' => 1 } }, + { 'name' => 'rights-metadata', 'object_status' => {} }, + { 'name' => 'content-metadata', 'object_status' => {} }, + { 'name' => 'technical-metadata', 'object_status' => {} }, + { 'name' => 'remediate-object', 'object_status' => {} }, + { 'name' => 'shelve', 'object_status' => {} }, + { 'name' => 'publish', 'object_status' => {} }, + { 'name' => 'provenance-metadata', 'object_status' => {} }, + { 'name' => 'sdr-ingest-transfer', 'object_status' => {} }, + { 'name' => 'sdr-ingest-received', 'object_status' => {} }, + { 'name' => 'reset-workspace', 'object_status' => {} }, + { 'name' => 'end-accession', 'object_status' => {} } + ] + ) + end + end +end