From f03181ba67dd3815ccb40a5f9e532b28d24b70ac Mon Sep 17 00:00:00 2001 From: aandrade Date: Fri, 22 Dec 2023 14:53:39 -0500 Subject: [PATCH 1/2] [TTPLAT-2353] Create new primary_scenario property for scenarios, allow users to select a single primary scenario per agency/fy, update views with the new data, ensure every agency/fy has a primary_scenario selected at all times when a scenario is created for it --- app/controllers/scenarios_controller.rb | 33 +++++++++++++++++-- app/models/draft_project.rb | 2 ++ app/models/scenario.rb | 1 + .../draft_projects/_index_table.html.haml | 1 + app/views/draft_projects/index.xlsx.axlsx | 1 + app/views/draft_projects/phases.xlsx.axlsx | 1 + app/views/scenarios/index.html.haml | 6 ++-- app/views/scenarios/show.html.haml | 26 +++++++++++++-- config/routes.rb | 1 + ...02118_add_primary_scenario_to_scenarios.rb | 5 +++ 10 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20231218202118_add_primary_scenario_to_scenarios.rb diff --git a/app/controllers/scenarios_controller.rb b/app/controllers/scenarios_controller.rb index d5615e7b..28370821 100644 --- a/app/controllers/scenarios_controller.rb +++ b/app/controllers/scenarios_controller.rb @@ -50,7 +50,7 @@ def show end #@phase_filter_ali_code = params[:filter_ali] || @scenario.draft_project_phases.min_by(&:fy_year).team_ali_code #TODO: what should be default here? respond_to do |format| - format.html + format.html {render :show, locals: {new_scenario: params[:new_scenario]}} end end @@ -90,7 +90,7 @@ def create respond_to do |format| if @scenario.update(form_params) - format.html { redirect_to scenario_path(@scenario) } + format.html { redirect_to scenario_path(@scenario, new_scenario: true) } else format.html end @@ -139,6 +139,35 @@ def copy end end + #----------------------------------------------------------------------------- + # Toggle Primary Scenario + #----------------------------------------------------------------------------- + def toggle_primary + set_scenario + + unless @scenario.primary_scenario + if old_primary = Scenario.find_by(organization: @scenario.organization, fy_year: @scenario.fy_year, primary_scenario: true) + unless old_primary.update(primary_scenario: false) + error = old_primary.errors.try(:first) + if error + flash.alert = error.try(:last) + end + end + end + end + + respond_to do |format| + if @scenario.update(primary_scenario: !@scenario.primary_scenario) + format.html { redirect_to scenario_path(@scenario) } + else + error = @scenario.errors.try(:first) + if error + flash.alert = error.try(:last) + end + end + end + end + #----------------------------------------------------------------------------- # Transition States # diff --git a/app/models/draft_project.rb b/app/models/draft_project.rb index fa5c5790..70a3cff1 100644 --- a/app/models/draft_project.rb +++ b/app/models/draft_project.rb @@ -185,6 +185,7 @@ def as_json(options={}) agency: organization.try(:to_s), fy_year: formatted_fiscal_year, project_number: project_number, + primary_scenario: scenario.try(:primary_scenario), scope: team_ali_code.try(:scope), is_emergency: emergency?, is_sogr: sogr?, @@ -218,6 +219,7 @@ def self.to_csv scenarios "Org": "organization_short_name", "FY": "formatted_fiscal_year", "Project": "project_number", + "Primary Scenario": "primary_scenario", "Title": "title", "Scope": "scope", "Cost": "cost", diff --git a/app/models/scenario.rb b/app/models/scenario.rb index 578cfced..7b80e3e5 100644 --- a/app/models/scenario.rb +++ b/app/models/scenario.rb @@ -77,6 +77,7 @@ class Scenario < ApplicationRecord validates :organization_id, presence: true validates :fy_year, presence: true validates :ending_fy_year, presence: true + validates :primary_scenario, uniqueness: {scope: [:organization, :fy_year]}, if: :primary_scenario #------------------------------------------------------------------------------ # Scopes diff --git a/app/views/draft_projects/_index_table.html.haml b/app/views/draft_projects/_index_table.html.haml index 6802010b..7d1a255a 100644 --- a/app/views/draft_projects/_index_table.html.haml +++ b/app/views/draft_projects/_index_table.html.haml @@ -63,6 +63,7 @@ %th.left{data: {field: 'agency', visible: "#{@organization_list.count > 1}"}} Agency %th.center.nowrap{data: {field: 'fy_year'}} #{get_fy_label} %th.left.nowrap{data: {field: 'project_number'}} Project Name + %th.center{data: {field: 'primary_scenario', formatter: 'raw_boolean_x_formatter'}} Primary Scenario %th.left{data: {visible: 'false', field: 'title'}} Title %th.left.nowrap{data: {visible: 'false', field: 'description'}} Project Description %th.left.nowrap{data: {visible: 'false', field: 'justification'}} Project Justification diff --git a/app/views/draft_projects/index.xlsx.axlsx b/app/views/draft_projects/index.xlsx.axlsx index 8c5cc472..95f77c44 100644 --- a/app/views/draft_projects/index.xlsx.axlsx +++ b/app/views/draft_projects/index.xlsx.axlsx @@ -17,6 +17,7 @@ wb.styles do |style| organization: ["Agency", "project.organization.short_name"], year: ["FY", "format_as_fiscal_year(project.fy_year)"], project_id: ["Project Name", "project.project_number.to_s.split('#').last"], + primary_scenario: ["Primary Scenario", "format_as_yes_no(project.scenario.try(:primary_scenario))"], title: ["Title", "project.title"], project_description: ["Project Description", "project.description"], project_justification: ["Project Justification", "project.justification"], diff --git a/app/views/draft_projects/phases.xlsx.axlsx b/app/views/draft_projects/phases.xlsx.axlsx index 66c16dcd..2cadfc4d 100644 --- a/app/views/draft_projects/phases.xlsx.axlsx +++ b/app/views/draft_projects/phases.xlsx.axlsx @@ -18,6 +18,7 @@ wb.styles do |style| project_id: ["Project ID", "phase.draft_project.project_number.to_s.split('#').last"], organization: ["Organization", "phase.scenario.organization"], project_year: ["Project Year", "format_as_fiscal_year(phase.draft_project.fy_year)"], + primary_scenario: ["Primary Scenario", "format_as_yes_no(phase.scenario.primary_scenario)"], project_title: ["Project Title", "phase.draft_project.title"], scope: ["Scope", "phase.team_ali_code.try(:scope)"], project_type: ["Project Type", "phase.draft_project.capital_project_type"], diff --git a/app/views/scenarios/index.html.haml b/app/views/scenarios/index.html.haml index 1e4a6d90..2f75c8a4 100644 --- a/app/views/scenarios/index.html.haml +++ b/app/views/scenarios/index.html.haml @@ -89,10 +89,11 @@ :search => 'client', :export => "['csv', 'txt']", :columns => '{"name":{"name": "Name","type":"drilldown-link"}, + "primary_scenario":{"name":"Primary Scenario","type":"x-column"}, "status":{"name":"Status"}, "org":{"name":"Organization"}, "created_at":{"name":"Created At"}}', - :selected_columns => "name,status,org,created_at", + :selected_columns => "name,primary_scenario,status,org,created_at", :cookies => "true", :sort => 'client', :sort_params => @params, @@ -105,7 +106,8 @@ add_row('#{table_dom_id}', { "name": '#{link_to scenario.name, scenario_path(scenario)}', + "primary_scenario": "#{format_as_boolean(scenario.primary_scenario, "fa-times")}", "status": '#{scenario.state_title}', "org": '#{scenario.organization.name}', "created_at": "#{format_as_date_time(scenario.created_at)}" - }, #{index}); + }, #{index}); \ No newline at end of file diff --git a/app/views/scenarios/show.html.haml b/app/views/scenarios/show.html.haml index 3cc49543..55ae00bd 100644 --- a/app/views/scenarios/show.html.haml +++ b/app/views/scenarios/show.html.haml @@ -10,6 +10,15 @@ cursor: pointer; } + #primary-scenario-selector { + font-size: large; + } + + #primary-scenario-selector a { + text-decoration: none; + color: inherit; + } + .row.text-center %h1 =@scenario.name @@ -44,7 +53,17 @@ =link_to assets_scenario_path(@scenario), target: "_blank" do %i.fa.fa-search Assets - + .row + #primary-scenario-selector + - if !@scenario.primary_scenario + - old_primary = Scenario.find_by(organization: @scenario.organization, fy_year: @scenario.fy_year, primary_scenario: true) + =link_to toggle_primary_scenario_path(@scenario), + method: :put, + data: old_primary ? {confirm: "This agency already has a Primary Scenario for this fiscal year. Would you like to mark this scenario as the new Primary Scenario?"} : {} do + %i{class: "fa fa-square-o"} + - else + %i{class: "fa fa-times-rectangle-o"} + %strong Primary Scenario .col-md-4 // .progress @@ -287,7 +306,10 @@ } }); - + // Check the Primary Scenario box if this scenario is new, triggering confirmation if previous scenario selected + if (#{new_scenario == "true"}) { + $('#primary-scenario-selector a').click(); + } }); diff --git a/config/routes.rb b/config/routes.rb index 9d5204db..dc8a741b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -88,6 +88,7 @@ get 'assets' post 'copy' get 'dotgrants_export' + put 'toggle_primary' end end diff --git a/db/migrate/20231218202118_add_primary_scenario_to_scenarios.rb b/db/migrate/20231218202118_add_primary_scenario_to_scenarios.rb new file mode 100644 index 00000000..5f6da100 --- /dev/null +++ b/db/migrate/20231218202118_add_primary_scenario_to_scenarios.rb @@ -0,0 +1,5 @@ +class AddPrimaryScenarioToScenarios < ActiveRecord::Migration[5.2] + def change + add_column :scenarios, :primary_scenario, :boolean + end +end From 8d52512dab77861871fa0704ab9f7db991e4707c Mon Sep 17 00:00:00 2001 From: "W. Scott Meeks" Date: Sun, 7 Jan 2024 13:04:36 -0500 Subject: [PATCH 2/2] Bump version --- lib/transam_cpt/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/transam_cpt/version.rb b/lib/transam_cpt/version.rb index 1d4abc62..eb0a53e3 100644 --- a/lib/transam_cpt/version.rb +++ b/lib/transam_cpt/version.rb @@ -1,3 +1,3 @@ module TransamCpt - VERSION = "2.35.0-rc2" + VERSION = "2.38.0-rc" end