From 34b58a5208b7cc18b2eb3d58d30781c6aaa8b07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Lutz?= Date: Fri, 19 Oct 2018 15:27:18 -0300 Subject: [PATCH] Adds draft phase functionality in legislation processes --- .../admin/legislation/processes_controller.rb | 3 ++ .../legislation/processes_controller.rb | 2 +- app/models/legislation/process.rb | 10 +++- .../legislation/processes/_form.html.erb | 28 +++++++++++ config/locales/en/activerecord.yml | 4 ++ config/locales/en/admin.yml | 2 + config/locales/es/activerecord.yml | 4 ++ config/locales/es/admin.yml | 2 + ...dd_draft_phase_to_legislation_processes.rb | 9 ++++ db/schema.rb | 41 +++++++++-------- spec/factories/legislations.rb | 8 ++++ .../admin/legislation/processes_spec.rb | 43 +++++++++++++++++ spec/features/legislation/processes_spec.rb | 2 + spec/models/legislation/process/phase_spec.rb | 46 +++++++++++++++++++ spec/models/legislation/process_spec.rb | 28 +++++++++-- 15 files changed, 209 insertions(+), 23 deletions(-) create mode 100644 db/migrate/20181016204729_add_draft_phase_to_legislation_processes.rb diff --git a/app/controllers/admin/legislation/processes_controller.rb b/app/controllers/admin/legislation/processes_controller.rb index ac54378b0..780ee7478 100644 --- a/app/controllers/admin/legislation/processes_controller.rb +++ b/app/controllers/admin/legislation/processes_controller.rb @@ -50,6 +50,8 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll :end_date, :debate_start_date, :debate_end_date, + :draft_start_date, + :draft_end_date, :draft_publication_date, :allegations_start_date, :allegations_end_date, @@ -57,6 +59,7 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll :proposals_phase_end_date, :result_publication_date, :debate_phase_enabled, + :draft_phase_enabled, :allegations_phase_enabled, :proposals_phase_enabled, :draft_publication_enabled, diff --git a/app/controllers/legislation/processes_controller.rb b/app/controllers/legislation/processes_controller.rb index f05d2fdda..c0ac5648e 100644 --- a/app/controllers/legislation/processes_controller.rb +++ b/app/controllers/legislation/processes_controller.rb @@ -8,7 +8,7 @@ class Legislation::ProcessesController < Legislation::BaseController def index @current_filter ||= 'open' - @processes = ::Legislation::Process.send(@current_filter).published.page(params[:page]) + @processes = ::Legislation::Process.send(@current_filter).published.not_in_draft.page(params[:page]) end def show diff --git a/app/models/legislation/process.rb b/app/models/legislation/process.rb index fcf450245..4e506de1f 100644 --- a/app/models/legislation/process.rb +++ b/app/models/legislation/process.rb @@ -15,7 +15,7 @@ class Legislation::Process < ActiveRecord::Base translates :additional_info, touch: true include Globalizable - PHASES_AND_PUBLICATIONS = %i(debate_phase allegations_phase proposals_phase draft_publication result_publication).freeze + PHASES_AND_PUBLICATIONS = %i(draft_phase debate_phase allegations_phase proposals_phase draft_publication result_publication).freeze has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id', dependent: :destroy @@ -29,6 +29,8 @@ class Legislation::Process < ActiveRecord::Base validates :end_date, presence: true validates :debate_start_date, presence: true, if: :debate_end_date? validates :debate_end_date, presence: true, if: :debate_start_date? + validates :draft_start_date, presence: true, if: :draft_end_date? + validates :draft_end_date, presence: true, if: :draft_start_date? validates :allegations_start_date, presence: true, if: :allegations_end_date? validates :allegations_end_date, presence: true, if: :allegations_start_date? validates :proposals_phase_end_date, presence: true, if: :proposals_phase_start_date? @@ -39,6 +41,11 @@ class Legislation::Process < ActiveRecord::Base scope :past, -> { where("end_date < ?", Date.current).order('id DESC') } scope :published, -> { where(published: true) } + scope :not_in_draft, -> { where("draft_phase_enabled = false or (draft_start_date IS NOT NULL and draft_end_date IS NOT NULL and (draft_start_date >= ? or draft_end_date <= ?))", Date.current, Date.current) } + + def draft_phase + Legislation::Process::Phase.new(draft_start_date, draft_end_date, draft_phase_enabled) + end def debate_phase Legislation::Process::Phase.new(debate_start_date, debate_end_date, debate_phase_enabled) @@ -85,6 +92,7 @@ class Legislation::Process < ActiveRecord::Base def valid_date_ranges errors.add(:end_date, :invalid_date_range) if end_date && start_date && end_date < start_date errors.add(:debate_end_date, :invalid_date_range) if debate_end_date && debate_start_date && debate_end_date < debate_start_date + errors.add(:draft_end_date, :invalid_date_range) if draft_end_date && draft_start_date && draft_end_date < draft_start_date if allegations_end_date && allegations_start_date && allegations_end_date < allegations_start_date errors.add(:allegations_end_date, :invalid_date_range) end diff --git a/app/views/admin/legislation/processes/_form.html.erb b/app/views/admin/legislation/processes/_form.html.erb index addb63522..1e43da6db 100644 --- a/app/views/admin/legislation/processes/_form.html.erb +++ b/app/views/admin/legislation/processes/_form.html.erb @@ -17,6 +17,34 @@ <% end %> +
+ +

<%= t("admin.legislation.processes.form.draft_phase_description") %>

+
+ +
+ <%= f.text_field :draft_start_date, + label: t("admin.legislation.processes.form.start"), + value: format_date_for_calendar_form(@process.draft_start_date), + class: "js-calendar-full", + id: "draft_start_date" %> +
+ +
+ <%= f.text_field :draft_end_date, + label: t("admin.legislation.processes.form.end"), + value: format_date_for_calendar_form(@process.draft_end_date), + class: "js-calendar-full", + id: "draft_end_date" %> +
+
+ <%= f.check_box :draft_phase_enabled, checked: @process.draft_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
+ +
+
+
+
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index 6f834931e..0ed4a9872 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -231,6 +231,8 @@ en: end_date: End date debate_start_date: Debate start date debate_end_date: Debate end date + draft_start_date: Draft start date + draft_end_date: Draft end date draft_publication_date: Draft publication date allegations_start_date: Allegations start date allegations_end_date: Allegations end date @@ -340,6 +342,8 @@ en: invalid_date_range: must be on or after the start date debate_end_date: invalid_date_range: must be on or after the debate start date + draft_end_date: + invalid_date_range: must be on or after the draft start date allegations_end_date: invalid_date_range: must be on or after the allegations start date proposal: diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index e1281fb32..5cbcc89ff 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -373,6 +373,8 @@ en: enabled: Enabled process: Process debate_phase: Debate phase + draft_phase: Draft phase + draft_phase_description: If this phase is active, the process won't be listed on processes index. Allow to preview the process and create content before the start. allegations_phase: Comments phase proposals_phase: Proposals phase start: Start diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index ac197335e..15bbb35bf 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -231,6 +231,8 @@ es: end_date: Fecha de fin del proceso debate_start_date: Fecha de inicio del debate debate_end_date: Fecha de fin del debate + draft_start_date: Fecha de inicio del borrador + draft_end_date: Fecha de fin del borrador draft_publication_date: Fecha de publicación del borrador allegations_start_date: Fecha de inicio de alegaciones allegations_end_date: Fecha de fin de alegaciones @@ -340,6 +342,8 @@ es: invalid_date_range: tiene que ser igual o posterior a la fecha de inicio debate_end_date: invalid_date_range: tiene que ser igual o posterior a la fecha de inicio del debate + draft_end_date: + invalid_date_range: tiene que ser igual o posterior a la fecha de inicio del borrador allegations_end_date: invalid_date_range: tiene que ser igual o posterior a la fecha de inicio de las alegaciones proposal: diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index f7186d53b..ecaaaf6f2 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -373,6 +373,8 @@ es: enabled: Habilitado process: Proceso debate_phase: Fase previa + draft_phase: Fase de borrador + draft_phase_description: Si esta fase está activa, el proceso no aparecerá en la página de procesos. Permite previsualizar el proceso y crear contenido antes del inicio. allegations_phase: Fase de comentarios proposals_phase: Fase de propuestas start: Inicio diff --git a/db/migrate/20181016204729_add_draft_phase_to_legislation_processes.rb b/db/migrate/20181016204729_add_draft_phase_to_legislation_processes.rb new file mode 100644 index 000000000..f2b6220cb --- /dev/null +++ b/db/migrate/20181016204729_add_draft_phase_to_legislation_processes.rb @@ -0,0 +1,9 @@ +class AddDraftPhaseToLegislationProcesses < ActiveRecord::Migration + def change + add_column :legislation_processes, :draft_start_date, :date + add_index :legislation_processes, :draft_start_date + add_column :legislation_processes, :draft_end_date, :date + add_index :legislation_processes, :draft_end_date + add_column :legislation_processes, :draft_phase_enabled, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index ea0b1bbbd..d30f35716 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180924071722) do +ActiveRecord::Schema.define(version: 20181016204729) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -580,7 +580,7 @@ ActiveRecord::Schema.define(version: 20180924071722) do t.string "locale", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.text "title" + t.string "title" t.text "changelog" t.text "body" t.text "body_html" @@ -647,13 +647,18 @@ ActiveRecord::Schema.define(version: 20180924071722) do t.date "proposals_phase_end_date" t.boolean "proposals_phase_enabled" t.text "proposals_description" + t.date "draft_start_date" + t.date "draft_end_date" + t.boolean "draft_phase_enabled", default: false end add_index "legislation_processes", ["allegations_end_date"], name: "index_legislation_processes_on_allegations_end_date", using: :btree add_index "legislation_processes", ["allegations_start_date"], name: "index_legislation_processes_on_allegations_start_date", using: :btree add_index "legislation_processes", ["debate_end_date"], name: "index_legislation_processes_on_debate_end_date", using: :btree add_index "legislation_processes", ["debate_start_date"], name: "index_legislation_processes_on_debate_start_date", using: :btree + add_index "legislation_processes", ["draft_end_date"], name: "index_legislation_processes_on_draft_end_date", using: :btree add_index "legislation_processes", ["draft_publication_date"], name: "index_legislation_processes_on_draft_publication_date", using: :btree + add_index "legislation_processes", ["draft_start_date"], name: "index_legislation_processes_on_draft_start_date", using: :btree add_index "legislation_processes", ["end_date"], name: "index_legislation_processes_on_end_date", using: :btree add_index "legislation_processes", ["hidden_at"], name: "index_legislation_processes_on_hidden_at", using: :btree add_index "legislation_processes", ["result_publication_date"], name: "index_legislation_processes_on_result_publication_date", using: :btree @@ -1163,17 +1168,17 @@ ActiveRecord::Schema.define(version: 20180924071722) do add_index "site_customization_images", ["name"], name: "index_site_customization_images_on_name", unique: true, using: :btree create_table "site_customization_page_translations", force: :cascade do |t| - t.integer "site_customization_page_id", null: false - t.string "locale", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "title" - t.string "subtitle" - t.text "content" - end + t.integer "site_customization_page_id", null: false + t.string "locale", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "title" + t.string "subtitle" + t.text "content" + end - add_index "site_customization_page_translations", ["locale"], name: "index_site_customization_page_translations_on_locale", using: :btree - add_index "site_customization_page_translations", ["site_customization_page_id"], name: "index_7fa0f9505738cb31a31f11fb2f4c4531fed7178b", using: :btree + add_index "site_customization_page_translations", ["locale"], name: "index_site_customization_page_translations_on_locale", using: :btree + add_index "site_customization_page_translations", ["site_customization_page_id"], name: "index_7fa0f9505738cb31a31f11fb2f4c4531fed7178b", using: :btree create_table "site_customization_pages", force: :cascade do |t| t.string "slug", null: false @@ -1418,6 +1423,12 @@ ActiveRecord::Schema.define(version: 20180924071722) do add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope", using: :btree add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope", using: :btree + create_table "web_sections", force: :cascade do |t| + t.text "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "widget_card_translations", force: :cascade do |t| t.integer "widget_card_id", null: false t.string "locale", null: false @@ -1450,12 +1461,6 @@ ActiveRecord::Schema.define(version: 20180924071722) do t.datetime "updated_at", null: false end - create_table "web_sections", force: :cascade do |t| - t.text "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - add_foreign_key "administrators", "users" add_foreign_key "annotations", "legacy_legislations" add_foreign_key "annotations", "users" diff --git a/spec/factories/legislations.rb b/spec/factories/legislations.rb index bacfa19a3..79a617d67 100644 --- a/spec/factories/legislations.rb +++ b/spec/factories/legislations.rb @@ -56,6 +56,14 @@ FactoryBot.define do result_publication_date { Date.current - 2.days } end + trait :in_draft_phase do + start_date { Date.current - 5.days } + end_date { Date.current + 5.days } + draft_start_date { Date.current - 2.days } + draft_end_date { Date.current + 2.days } + draft_phase_enabled true + end + trait :in_debate_phase do start_date { Date.current - 5.days } end_date { Date.current + 5.days } diff --git a/spec/features/admin/legislation/processes_spec.rb b/spec/features/admin/legislation/processes_spec.rb index 44b033328..f9e575d3d 100644 --- a/spec/features/admin/legislation/processes_spec.rb +++ b/spec/features/admin/legislation/processes_spec.rb @@ -53,6 +53,8 @@ feature 'Admin legislation processes' do fill_in 'legislation_process[debate_start_date]', with: base_date.strftime("%d/%m/%Y") fill_in 'legislation_process[debate_end_date]', with: (base_date + 2.days).strftime("%d/%m/%Y") + fill_in 'legislation_process[draft_start_date]', with: (base_date - 3.days).strftime("%d/%m/%Y") + fill_in 'legislation_process[draft_end_date]', with: (base_date - 1.days).strftime("%d/%m/%Y") fill_in 'legislation_process[draft_publication_date]', with: (base_date + 3.days).strftime("%d/%m/%Y") fill_in 'legislation_process[allegations_start_date]', with: (base_date + 3.days).strftime("%d/%m/%Y") fill_in 'legislation_process[allegations_end_date]', with: (base_date + 5.days).strftime("%d/%m/%Y") @@ -75,6 +77,47 @@ feature 'Admin legislation processes' do expect(page).to have_content 'Summary of the process' expect(page).not_to have_content 'Describing the process' end + + scenario 'Legislation process in draft phase' do + visit admin_root_path + + within('#side_menu') do + click_link "Collaborative Legislation" + end + + expect(page).not_to have_content 'An example legislation process' + + click_link "New process" + + fill_in 'Process Title', with: 'An example legislation process in draft phase' + fill_in 'Summary', with: 'Summary of the process' + fill_in 'Description', with: 'Describing the process' + + base_date = Date.current - 2.days + fill_in 'legislation_process[start_date]', with: base_date.strftime("%d/%m/%Y") + fill_in 'legislation_process[end_date]', with: (base_date + 5.days).strftime("%d/%m/%Y") + + fill_in 'legislation_process[draft_start_date]', with: base_date.strftime("%d/%m/%Y") + fill_in 'legislation_process[draft_end_date]', with: (base_date + 3.days).strftime("%d/%m/%Y") + check 'legislation_process[draft_phase_enabled]' + + click_button 'Create process' + + expect(page).to have_content 'An example legislation process in draft phase' + expect(page).to have_content 'Process created successfully' + + click_link 'Click to visit' + + expect(page).to have_content 'An example legislation process in draft phase' + expect(page).not_to have_content 'Summary of the process' + expect(page).to have_content 'Describing the process' + + visit legislation_processes_path + + expect(page).not_to have_content 'An example legislation process in draft phase' + expect(page).not_to have_content 'Summary of the process' + expect(page).not_to have_content 'Describing the process' + end end context 'Update' do diff --git a/spec/features/legislation/processes_spec.rb b/spec/features/legislation/processes_spec.rb index 3f7d63fd9..870646ca1 100644 --- a/spec/features/legislation/processes_spec.rb +++ b/spec/features/legislation/processes_spec.rb @@ -66,11 +66,13 @@ feature 'Legislation' do create(:legislation_process, title: "Process open") create(:legislation_process, :next, title: "Process next") create(:legislation_process, :past, title: "Process past") + create(:legislation_process, :in_draft_phase, title: "Process in draft phase") visit legislation_processes_path expect(page).to have_content('Process open') expect(page).not_to have_content('Process next') expect(page).not_to have_content('Process past') + expect(page).not_to have_content('Process in draft phase') visit legislation_processes_path(filter: 'next') expect(page).not_to have_content('Process open') diff --git a/spec/models/legislation/process/phase_spec.rb b/spec/models/legislation/process/phase_spec.rb index 40d6296b2..f23db7c28 100644 --- a/spec/models/legislation/process/phase_spec.rb +++ b/spec/models/legislation/process/phase_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' RSpec.describe Legislation::Process::Phase, type: :model do let(:process) { create(:legislation_process) } + let(:process_in_draft_phase) { create(:legislation_process, :in_draft_phase) } describe "#enabled?" do it "checks debate phase" do @@ -11,6 +12,15 @@ RSpec.describe Legislation::Process::Phase, type: :model do expect(process.debate_phase.enabled?).to be false end + it "checks draft phase" do + expect(process.draft_phase.enabled?).to be false + expect(process_in_draft_phase.draft_phase.enabled?).to be true + + process.update_attributes(draft_phase_enabled: false) + expect(process.draft_phase.enabled?).to be false + end + + it "checks allegations phase" do expect(process.allegations_phase.enabled?).to be true @@ -38,6 +48,24 @@ RSpec.describe Legislation::Process::Phase, type: :model do expect(process.debate_phase.started?).to be true end + it "checks draft phase" do + # future + process.update_attributes(draft_start_date: Date.current + 2.days, draft_end_date: Date.current + 3.days, draft_phase_enabled: true) + expect(process.draft_phase.started?).to be false + + # started + process.update_attributes(draft_start_date: Date.current - 2.days, draft_end_date: Date.current + 1.day, draft_phase_enabled: true) + expect(process.draft_phase.started?).to be true + + # starts today + process.update_attributes(draft_start_date: Date.current, draft_end_date: Date.current + 1.day, draft_phase_enabled: true) + expect(process.draft_phase.started?).to be true + + # past + process.update_attributes(draft_start_date: Date.current - 2.days, draft_end_date: Date.current - 1.day, draft_phase_enabled: true) + expect(process.draft_phase.started?).to be true + end + it "checks allegations phase" do # future process.update_attributes(allegations_start_date: Date.current + 2.days, allegations_end_date: Date.current + 3.days) @@ -76,6 +104,24 @@ RSpec.describe Legislation::Process::Phase, type: :model do expect(process.debate_phase.open?).to be false end + it "checks draft phase" do + # future + process.update_attributes(draft_start_date: Date.current + 2.days, draft_end_date: Date.current + 3.days, draft_phase_enabled: true) + expect(process.draft_phase.open?).to be false + + # started + process.update_attributes(draft_start_date: Date.current - 2.days, draft_end_date: Date.current + 1.day, draft_phase_enabled: true) + expect(process.draft_phase.open?).to be true + + # starts today + process.update_attributes(draft_start_date: Date.current, draft_end_date: Date.current + 1.day, draft_phase_enabled: true) + expect(process.draft_phase.open?).to be true + + # past + process.update_attributes(draft_start_date: Date.current - 2.days, draft_end_date: Date.current - 1.day, draft_phase_enabled: true) + expect(process.draft_phase.open?).to be false + end + it "checks allegations phase" do # future diff --git a/spec/models/legislation/process_spec.rb b/spec/models/legislation/process_spec.rb index aef705d33..646cad653 100644 --- a/spec/models/legislation/process_spec.rb +++ b/spec/models/legislation/process_spec.rb @@ -45,17 +45,28 @@ describe Legislation::Process do expect(process).to be_valid end - it "is invalid if debate_end_date is before debate start_date" do + it "is valid if debate_end_date is the same as debate_start_date" do + process = build(:legislation_process, debate_start_date: Date.current - 1.day, debate_end_date: Date.current - 1.day) + expect(process).to be_valid + end + + it "is invalid if debate_end_date is before debate_start_date" do process = build(:legislation_process, debate_start_date: Date.current, debate_end_date: Date.current - 1.day) expect(process).to be_invalid expect(process.errors.messages[:debate_end_date]).to include("must be on or after the debate start date") end - it "is valid if debate_end_date is the same as debate_start_date" do - process = build(:legislation_process, debate_start_date: Date.current - 1.day, debate_end_date: Date.current - 1.day) + it "is valid if draft_end_date is the same as draft_start_date" do + process = build(:legislation_process, draft_start_date: Date.current - 1.day, draft_end_date: Date.current - 1.day) expect(process).to be_valid end + it "is invalid if draft_end_date is before draft_start_date" do + process = build(:legislation_process, draft_start_date: Date.current, draft_end_date: Date.current - 1.day) + expect(process).to be_invalid + expect(process.errors.messages[:draft_end_date]).to include("must be on or after the draft start date") + end + it "is invalid if allegations_end_date is before allegations_start_date" do process = build(:legislation_process, allegations_start_date: Date.current, allegations_end_date: Date.current - 1.day) expect(process).to be_invalid @@ -73,6 +84,9 @@ describe Legislation::Process do @process_1 = create(:legislation_process, start_date: Date.current - 2.days, end_date: Date.current + 1.day) @process_2 = create(:legislation_process, start_date: Date.current + 1.day, end_date: Date.current + 3.days) @process_3 = create(:legislation_process, start_date: Date.current - 4.days, end_date: Date.current - 3.days) + @process_4 = create(:legislation_process, draft_start_date: Date.current - 3.days, draft_end_date: Date.current - 2.days) + @process_5 = create(:legislation_process, draft_start_date: Date.current - 2.days, draft_end_date: Date.current + 2.days, draft_phase_enabled: false) + @process_6 = create(:legislation_process, draft_start_date: Date.current - 2.days, draft_end_date: Date.current + 2.days, draft_phase_enabled: true) end it "filters open" do @@ -83,6 +97,14 @@ describe Legislation::Process do expect(open_processes).not_to include(@process_3) end + it "filters draft phase" do + draft_processes = ::Legislation::Process.not_in_draft + + expect(draft_processes).to include(@process_4) + expect(draft_processes).to include(@process_5) + expect(draft_processes).not_to include(@process_6) + end + it "filters next" do next_processes = ::Legislation::Process.next