Merge pull request #7691 from betagouv/7667-zone-millesime

7667 Prendre en compte les changements de ministères
This commit is contained in:
krichtof 2022-09-26 17:06:47 +02:00 committed by GitHub
commit a054a4d0f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 330 additions and 55 deletions

View file

@ -48,6 +48,6 @@ class ZoneDashboard < Administrate::BaseDashboard
# across all pages of the admin dashboard.
#
def display_resource(zone)
"Zone #{zone.label}"
"Zone #{zone.current_label}"
end
end

View file

@ -1,9 +1,12 @@
module ZoneHelper
def grouped_options_for_zone
def grouped_options_for_zone(date)
collectivite = Zone.find_by(acronym: "COLLECTIVITE")
{
"--" => [[I18n.t('i_dont_know', scope: 'utils'), nil], [collectivite.label, collectivite.id]],
I18n.t('ministeres', scope: 'zones') => (Zone.order(:label) - [collectivite]).map { |m| [m.label, m.id] }
"--" => [
[I18n.t('i_dont_know', scope: 'utils'), nil],
[collectivite.label, collectivite.id]
],
I18n.t('ministeres', scope: 'zones') => (Zone.available_at(date) - [collectivite]).map { |m| [m.label_at(date), m.id] }
}
end
end

View file

@ -812,6 +812,10 @@ class Procedure < ApplicationRecord
api_particulier_sources['mesri'].present?
end
def published_or_created_at
published_at || created_at
end
private
def move_new_children_to_new_parent_coordinate(new_draft)

View file

@ -10,5 +10,23 @@
#
class Zone < ApplicationRecord
validates :acronym, presence: true, uniqueness: true
has_many :labels, -> { order(designated_on: :desc) }, class_name: 'ZoneLabel', inverse_of: :zone
has_many :procedures, -> { order(published_at: :desc) }, inverse_of: :zone
def current_label
labels.first.name
end
def label_at(date)
label = labels.where('designated_on < ?', date)&.first || labels.last
label.name
end
def available_at?(date)
label_at(date) != 'Non attribué'
end
def self.available_at(date)
Zone.all.filter { |zone| zone.available_at?(date) }.sort_by { |zone| zone.label_at(date) }
end
end

14
app/models/zone_label.rb Normal file
View file

@ -0,0 +1,14 @@
# == Schema Information
#
# Table name: zone_labels
#
# id :bigint not null, primary key
# designated_on :date not null
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# zone_id :bigint not null
#
class ZoneLabel < ApplicationRecord
belongs_to :zone
end

View file

@ -17,7 +17,7 @@
= f.label :zone do
= t('zone', scope: 'activerecord.attributes.procedure')
%span.mandatory *
= f.select :zone_id, grouped_options_for_zone
= f.select :zone_id, grouped_options_for_zone(@procedure.published_or_created_at)
%h3.header-subsection Logo de la démarche
= render Attachment::EditComponent.new(form: f, attached_file: @procedure.logo, direct_upload: true, user_can_destroy: true)

View file

@ -1,37 +1,58 @@
ministeres:
- MAA:
label: "Ministère de l'Agriculture et de l'Alimentation"
- '2022-05-20': "Ministère de l'Agriculture et de la Souveraineté alimentaire"
- '2020-07-06': "Ministère de l'Agriculture et de l'Alimentation"
- MC:
label: "Ministère de la Culture"
- '2020-07-06': "Ministère de la Culture"
- MAS:
label: "Ministère des Solidarités et de la Santé"
- '2022-05-20': "Ministère de la Santé et de la Prévention"
- '2020-07-06': "Ministère des Solidarités et de la Santé"
- MSAPH:
- '2022-05-20': "Ministère des Solidarités, de l'Autonomie et des personnes handicapées"
- '2020-07-06': "Non attribué"
- MTEI:
label: "Ministère du Travail"
- '2022-05-20': "Ministère du Travail, du Plein emploi et de l'Insertion"
- '2020-07-06': "Ministère du Travail"
- MEAE:
label: "Ministère de l'Europe et des Affaires étrangères"
- '2020-07-06': "Ministère de l'Europe et des Affaires étrangères"
- MEF:
label: "Ministère de l'Économie, des Finances et de la Relance"
- '2022-05-20': "Ministère de l'Économie, des Finances et de la Souveraineté industrielle et numérique"
- '2020-07-06': "Ministère de l'Économie, des Finances et de la Relance"
- MJS:
label: "Ministère de la Jeunesse et des Sports"
- '2022-05-20': "Non attribué"
- '2020-07-06': "Ministère de la Jeunesse et des Sports"
- MSJO:
- '2022-05-20': "Ministère des Sports et des Jeux olympiques et paralympiques"
- '2020-07-06': "Non attribué"
- MEN:
label: "Ministère de l'Éducation nationale, de la Jeunesse et des Sports"
- '2022-05-20': "Ministère de l'Éducation nationale et de la Jeunesse"
- '2020-07-06': "Ministère de l'Éducation nationale, de la Jeunesse et des Sports"
- ESR:
label: "Ministère de l'Enseignement supérieur, de la Recherche et de l'Innovation"
- '2022-05-20': "Ministère de l'Enseignement supérieur et de la Recherche"
- '2020-07-06': "Ministère de l'Enseignement supérieur, de la Recherche et de l'Innovation"
- MI:
label: "Ministère de l'Intérieur"
- '2022-05-20': "Ministère de l'Intérieur et des Outre-mer"
- '2020-07-06': "Ministère de l'Intérieur"
- MINARM:
label: "Ministère des Armées"
- '2020-07-06': "Ministère des Armées"
- MJ:
label: "Ministère de la Justice"
- '2020-07-06': "Ministère de la Justice"
- MTES:
label: "Ministère de la Transition écologique"
- '2022-05-20': "Ministère de la Transition écologique et de la Cohésion des territoires"
- '2020-07-06': "Ministère de la Transition écologique"
- MTE:
- '2022-05-20': "Ministère de la Transition énergétique"
- '2020-07-06': "Non attribué"
- MCTRCT:
label: "Ministère de la Cohésion des territoires et des Relations avec les collectivités territoriales"
- '2022-05-20': "Non attribué"
- '2020-07-06': "Ministère de la Cohésion des territoires et des Relations avec les collectivités territoriales"
- PM:
label: "Premier ministre"
- '2020-07-06': "Premier ministre"
- MER:
label: "Ministère de la Mer"
- '2022-05-20': "Non attribué"
- '2020-07-06': "Ministère de la Mer"
- MTFP:
label: "Ministère de la Transformation et de la Fonction publiques"
- '2020-07-06': "Ministère de la Transformation et de la Fonction publiques"
- OM:
label: "Ministère des Outre-mer"
- '2022-05-20': "Non attribué"
- '2020-07-06': "Ministère des Outre-mer"

View file

@ -0,0 +1,11 @@
class CreateZoneLabels < ActiveRecord::Migration[6.1]
def change
create_table :zone_labels do |t|
t.belongs_to :zone, null: false, foreign_key: true
t.date :designated_on, null: false
t.string :name, null: false
t.timestamps
end
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2022_09_02_151920) do
ActiveRecord::Schema.define(version: 2022_09_11_134914) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
@ -861,6 +861,15 @@ ActiveRecord::Schema.define(version: 2022_09_02_151920) do
t.index ["procedure_id"], name: "index_without_continuation_mails_on_procedure_id"
end
create_table "zone_labels", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.date "designated_on", null: false
t.string "name", null: false
t.datetime "updated_at", precision: 6, null: false
t.bigint "zone_id", null: false
t.index ["zone_id"], name: "index_zone_labels_on_zone_id"
end
create_table "zones", force: :cascade do |t|
t.string "acronym", null: false
t.datetime "created_at", precision: 6, null: false
@ -922,4 +931,5 @@ ActiveRecord::Schema.define(version: 2022_09_02_151920) do
add_foreign_key "trusted_device_tokens", "instructeurs"
add_foreign_key "users", "users", column: "requested_merge_into_id"
add_foreign_key "without_continuation_mails", "procedures"
add_foreign_key "zone_labels", "zones"
end

View file

@ -0,0 +1,28 @@
namespace :after_party do
desc 'Deployment task: populate_zones'
task populate_zones: :environment do
if Flipper.enabled? :zonage
puts "Running deploy task 'populate_zones'"
collectivite = Zone.find_or_create_by!(acronym: 'COLLECTIVITE')
coll_label = collectivite.labels.find_or_initialize_by(designated_on: Date.parse('1977-07-30'))
coll_label.update(name: 'Collectivité territoriale')
config = Psych.safe_load(File.read(Rails.root.join("config", "zones.yml")))
config["ministeres"].each do |ministere|
acronym = ministere.keys.first
zone = Zone.find_or_create_by!(acronym: acronym)
labels_a = ministere[acronym]
labels_a.each do |label_h|
designated_on = label_h.keys.first
label = zone.labels.find_or_initialize_by(designated_on: designated_on)
label.update(name: label_h[designated_on])
end
end
end
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord
.create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
end
end

View file

@ -1,12 +0,0 @@
namespace :zones do
task populate_zones: :environment do
puts "Running deploy task 'populate_zones'"
Zone.create!(acronym: 'COLLECTIVITE', label: 'Collectivité territoriale')
config = Psych.safe_load(File.read(Rails.root.join("config", "zones.yml")))
config["ministeres"].each do |ministere|
acronym = ministere.keys.first
Zone.create!(acronym: acronym, label: ministere["label"])
end
end
end

View file

@ -1,6 +1,14 @@
FactoryBot.define do
factory :zone do
sequence(:acronym) { |n| "MA#{n}" }
sequence(:label) { |n| "Ministère de l'Education Populaire #{n}" }
transient do
labels { [{ designated_on: '1981-05-08', name: "Ministère de l'Education Populaire" }] }
end
after(:create) do |zone, evaluator|
evaluator.labels.each do |label|
zone.labels.create(designated_on: label[:designated_on], name: label[:name])
end
end
end
end

View file

@ -0,0 +1,19 @@
describe '20220922151100_populate_zones' do
let(:rake_task) { Rake::Task['after_party:populate_zones'] }
subject(:run_task) do
Flipper.enable :zonage
rake_task.invoke
end
after(:each) do
rake_task.reenable
end
it 'populates zones' do
run_task
expect(Zone.find_by(acronym: 'PM').label).to eq "Premier ministre"
expect(Zone.find_by(acronym: 'MTEI').labels.first.designated_on).to eq Date.parse('2022-05-20')
expect(Zone.find_by(acronym: 'MTEI').labels.first.name).to eq "Ministère du Travail, du Plein emploi et de l'Insertion"
expect(Zone.find_by(acronym: 'MTEI').labels.last.designated_on).to eq Date.parse('2020-07-06')
expect(Zone.find_by(acronym: 'MTEI').labels.last.name).to eq "Ministère du Travail"
end
end

View file

@ -1,14 +0,0 @@
describe 'populate_zones' do
let(:rake_task) { Rake::Task['zones:populate_zones'] }
subject(:run_task) do
rake_task.invoke
end
after(:each) do
rake_task.reenable
end
it 'populates zones' do
run_task
expect(Zone.find_by(acronym: 'PM').label).to eq "Premier ministre"
end
end

121
spec/models/zone_spec.rb Normal file
View file

@ -0,0 +1,121 @@
describe Zone do
let(:now) { Time.zone.parse("2022-08-11") }
before do
Timecop.freeze(now)
end
after do
Timecop.return
end
describe '#label' do
let(:start_previous_government) { Date.parse('2020-07-06') }
let(:start_last_government) { Date.parse('2022-05-20') }
let(:zone) do
create(:zone, labels: [
{
designated_on: start_previous_government,
name: "Ministère de l'Économie, des Finances et de la Relance"
},
{
designated_on: start_last_government,
name: "Ministère de l'Économie, des Finances et de la Souveraineté industrielle et numérique"
}
])
end
it 'returns label for the current millesime' do
expect(zone.current_label).to eq "Ministère de l'Économie, des Finances et de la Souveraineté industrielle et numérique"
end
it 'returns label at specific date' do
expect(zone.label_at(start_previous_government + 1.week)).to eq "Ministère de l'Économie, des Finances et de la Relance"
expect(zone.label_at(start_last_government + 1.week)).to eq "Ministère de l'Économie, des Finances et de la Souveraineté industrielle et numérique"
expect(zone.label_at(start_previous_government - 1.week)).to eq "Ministère de l'Économie, des Finances et de la Relance"
end
end
describe "#available_at?" do
let(:start_previous_government) { Date.parse('2020-07-06') }
let(:start_last_government) { Date.parse('2022-05-20') }
let(:start_futur_government) { Date.parse('2027-05-20') }
let(:zone) do
create(:zone, labels: [
{
designated_on: start_previous_government,
name: "Ministère des Outre-mer"
},
{
designated_on: start_last_government,
name: "Non attribué"
},
{
designated_on: start_futur_government,
name: "Ministère des Territoires d'Outre-mer"
}
])
end
it "returns false if the zone does'nt exist at a specific date" do
expect(zone.available_at?(start_last_government + 1.week)).to be_falsy
end
it "returns true if the zone exist at a specific date" do
expect(zone.available_at?(start_futur_government + 1.week)).to be_truthy
expect(zone.available_at?(start_previous_government + 1.week)).to be_truthy
end
end
describe "#self.available_at?" do
let(:start_previous_government) { Date.parse('2020-07-06') }
let(:start_last_government) { Date.parse('2022-05-20') }
let(:start_futur_government) { Date.parse('2027-05-20') }
let(:om) do
create(:zone, labels: [
{
designated_on: start_previous_government,
name: "Ministère des Outre-mer"
},
{
designated_on: start_last_government,
name: "Non attribué"
},
{
designated_on: start_futur_government,
name: "Ministère des Territoires d'Outre-mer"
}
])
end
let!(:culture) do
create(:zone, labels: [
{
designated_on: start_previous_government,
name: "Ministère de la Culture"
}
])
end
let!(:om) do
create(:zone, labels: [
{
designated_on: start_previous_government,
name: "Ministère des Outre-mer"
},
{
designated_on: start_last_government,
name: "Non attribué"
},
{
designated_on: start_futur_government,
name: "Ministère des Territoires d'Outre-mer"
}
])
end
it 'returns only available zones at specific date' do
expect(Zone.available_at(start_last_government + 1.day)).to eq [culture]
expect(Zone.available_at(start_previous_government + 1.day)).to eq [culture, om]
end
end
end

View file

@ -1,10 +1,11 @@
describe UpdateZoneToProceduresService do
before(:each) do
Rake::Task['zones:populate_zones'].invoke
Flipper.enable :zonage
Rake::Task['after_party:populate_zones'].invoke
end
after(:each) do
Rake::Task['zones:populate_zones'].reenable
Rake::Task['after_party:populate_zones'].reenable
end
describe '#call' do

View file

@ -1,15 +1,58 @@
describe 'administrateurs/procedures/edit.html.haml' do
let(:logo) { fixture_file_upload('spec/fixtures/files/logo_test_procedure.png', 'image/png') }
let(:procedure) { create(:procedure, logo: logo, lien_site_web: 'http://some.website') }
let(:populate_zones_task) { Rake::Task['after_party:populate_zones'] }
before do
assign(:procedure, procedure)
render
Flipper.enable(:zonage)
populate_zones_task.invoke
end
after do
populate_zones_task.reenable
end
context 'when procedure logo is present' do
it 'display on the page' do
assign(:procedure, procedure)
render
expect(rendered).to have_selector('.procedure-logos')
end
end
context 'when procedure has never been published' do
before { Timecop.freeze(now) }
after { Timecop.return }
let(:procedure) { create(:procedure, zone: Zone.find_by(acronym: 'MTEI')) }
let(:now) { Time.zone.parse('18/05/2022') }
it 'displays zones with label available at the creation date' do
assign(:procedure, procedure)
render
expect(rendered).to have_content("Ministère du Travail")
expect(rendered).not_to have_content("Ministère du Travail, du Plein emploi et de l'Insertion")
end
end
context 'when procedure has been published' do
before { Timecop.freeze(now) }
after { Timecop.return }
let(:procedure) { create(:procedure, zone: Zone.find_by(acronym: 'MTEI')) }
let(:now) { Time.zone.parse('18/05/2022') }
it 'displays zones with label available at the creation date' do
Timecop.freeze(Time.zone.parse('22/05/2022')) do
procedure.publish!
end
assign(:procedure, procedure)
render
expect(rendered).to have_content("Ministère du Travail, du Plein emploi et de l'Insertion")
end
end
end