From 46c1bbbc6f3493504b97f4695e3dc71cf900f185 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 23 May 2019 14:28:14 +0200 Subject: [PATCH] Official support for declarative demarches --- README.md | 2 +- app/jobs/declarative_procedures_job.rb | 7 ++ app/models/dossier.rb | 4 +- app/models/procedure.rb | 27 ++++++ ...dd_declarative_with_state_to_procedures.rb | 6 ++ db/schema.rb | 2 + ...0523122639_set_declarative_procedures.rake | 22 +++++ spec/jobs/declarative_procedures_job_spec.rb | 82 +++++++++++++++++++ 8 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 app/jobs/declarative_procedures_job.rb create mode 100644 db/migrate/20190627090420_add_declarative_with_state_to_procedures.rb create mode 100644 lib/tasks/deployment/20190523122639_set_declarative_procedures.rake create mode 100644 spec/jobs/declarative_procedures_job_spec.rb diff --git a/README.md b/README.md index 03a30208e..b0f026bde 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ En local, un utilisateur de test est créé automatiquement, avec les identifian AutoArchiveProcedureJob.set(cron: "* * * * *").perform_later WeeklyOverviewJob.set(cron: "0 7 * * 1").perform_later - AutoReceiveDossiersForProcedureJob.set(cron: "* * * * *").perform_later(procedure_declaratoire_id, Dossier.states.fetch(:en_instruction)) + DeclarativeProceduresJob.set(cron: "* * * * *").perform_later UpdateAdministrateurUsageStatisticsJob.set(cron: "0 10 * * *").perform_later FindDubiousProceduresJob.set(cron: "0 0 * * *").perform_later Administrateurs::ActivateBeforeExpirationJob.set(cron: "0 8 * * *").perform_later diff --git a/app/jobs/declarative_procedures_job.rb b/app/jobs/declarative_procedures_job.rb new file mode 100644 index 000000000..7242c2215 --- /dev/null +++ b/app/jobs/declarative_procedures_job.rb @@ -0,0 +1,7 @@ +class DeclarativeProceduresJob < ApplicationJob + queue_as :cron + + def perform(*args) + Procedure.declarative.find_each(&:process_dossiers!) + end +end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 18164a03b..8b20e7e7f 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -411,13 +411,13 @@ class Dossier < ApplicationRecord end def send_dossier_received - if saved_change_to_state? && en_instruction? + if saved_change_to_state? && en_instruction? && !procedure.declarative_accepte? NotificationMailer.send_dossier_received(self).deliver_later end end def send_draft_notification_email - if brouillon? + if brouillon? && !procedure.declarative? DossierMailer.notify_new_draft(self).deliver_later end end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index c1eddeba0..7f8562310 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -46,6 +46,7 @@ class Procedure < ApplicationRecord scope :created_during, -> (range) { where(created_at: range) } scope :cloned_from_library, -> { where(cloned_from_library: true) } scope :avec_lien, -> { where.not(path: nil) } + scope :declarative, -> { where.not(declarative_with_state: nil) } scope :for_api, -> { includes( @@ -57,6 +58,11 @@ class Procedure < ApplicationRecord ) } + enum declarative_with_state: { + en_instruction: 'en_instruction', + accepte: 'accepte' + } + validates :libelle, presence: true, allow_blank: false, allow_nil: false validates :description, presence: true, allow_blank: false, allow_nil: false validates :administrateurs, presence: true @@ -141,6 +147,14 @@ class Procedure < ApplicationRecord module_api_carto&.use_api_carto? && module_api_carto&.migrated? end + def declarative? + declarative_with_state.present? + end + + def declarative_accepte? + declarative_with_state == Procedure.declarative_with_states.fetch(:accepte) + end + # Warning: dossier after_save build_default_champs must be removed # to save a dossier created from this method def new_dossier @@ -431,6 +445,19 @@ class Procedure < ApplicationRecord update!(collection_attribute_name => attributes) end + def process_dossiers! + case declarative_with_state + when Procedure.declarative_with_states.fetch(:en_instruction) + dossiers + .state_en_construction + .find_each(&:passer_automatiquement_en_instruction!) + when Procedure.declarative_with_states.fetch(:accepte) + dossiers + .state_en_construction + .find_each(&:accepter_automatiquement!) + end + end + private def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index) diff --git a/db/migrate/20190627090420_add_declarative_with_state_to_procedures.rb b/db/migrate/20190627090420_add_declarative_with_state_to_procedures.rb new file mode 100644 index 000000000..6c17cf6a0 --- /dev/null +++ b/db/migrate/20190627090420_add_declarative_with_state_to_procedures.rb @@ -0,0 +1,6 @@ +class AddDeclarativeWithStateToProcedures < ActiveRecord::Migration[5.2] + def change + add_column :procedures, :declarative_with_state, :string + add_index :procedures, :declarative_with_state + end +end diff --git a/db/schema.rb b/db/schema.rb index a6427974e..f2b821f01 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -492,6 +492,8 @@ ActiveRecord::Schema.define(version: 2019_06_27_132911) do t.boolean "durees_conservation_required", default: true t.string "path" t.boolean "expects_multiple_submissions", default: false, null: false + t.string "declarative_with_state" + t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state" t.index ["hidden_at"], name: "index_procedures_on_hidden_at" t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id" t.index ["service_id"], name: "index_procedures_on_service_id" diff --git a/lib/tasks/deployment/20190523122639_set_declarative_procedures.rake b/lib/tasks/deployment/20190523122639_set_declarative_procedures.rake new file mode 100644 index 000000000..ba2c11d7a --- /dev/null +++ b/lib/tasks/deployment/20190523122639_set_declarative_procedures.rake @@ -0,0 +1,22 @@ +namespace :after_party do + desc 'Deployment task: set_declarative_procedures' + task set_declarative_procedures: :environment do + puts "Running deploy task 'set_declarative_procedures'" + + Delayed::Job.where.not(cron: nil).find_each do |job| + job_data = YAML.load_dj(job.handler).job_data + + if job_data['job_class'] == 'AutoReceiveDossiersForProcedureJob' + procedure_id, state = job_data['arguments'] + procedure = Procedure.find(procedure_id) + procedure.declarative_with_state = state + procedure.save! + job.delete + 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: '20190523122639' + end +end diff --git a/spec/jobs/declarative_procedures_job_spec.rb b/spec/jobs/declarative_procedures_job_spec.rb new file mode 100644 index 000000000..ed17b5149 --- /dev/null +++ b/spec/jobs/declarative_procedures_job_spec.rb @@ -0,0 +1,82 @@ +require 'rails_helper' + +RSpec.describe DeclarativeProceduresJob, type: :job do + describe "perform" do + let(:date) { Time.utc(2017, 9, 1, 10, 5, 0) } + let(:instruction_date) { date + 120 } + + let(:state) { nil } + let(:procedure) { create(:procedure, :with_gestionnaire, declarative_with_state: state) } + let(:nouveau_dossier1) { create(:dossier, :en_construction, procedure: procedure) } + let(:nouveau_dossier2) { create(:dossier, :en_construction, procedure: procedure) } + let(:dossier_recu) { create(:dossier, :en_instruction, procedure: procedure) } + let(:dossier_brouillon) { create(:dossier, procedure: procedure) } + + before do + Timecop.freeze(date) + dossiers = [ + nouveau_dossier1, + nouveau_dossier2, + dossier_recu, + dossier_brouillon + ] + + create(:attestation_template, procedure: procedure) + DeclarativeProceduresJob.new.perform + + dossiers.each(&:reload) + end + + after { Timecop.return } + + context "with some dossiers" do + context "en_construction" do + let(:state) { Dossier.states.fetch(:en_instruction) } + let(:last_operation) { nouveau_dossier1.dossier_operation_logs.last } + + it { + expect(nouveau_dossier1.en_instruction?).to be true + expect(nouveau_dossier1.en_instruction_at).to eq(date) + expect(last_operation.operation).to eq('passer_en_instruction') + expect(last_operation.automatic_operation?).to be_truthy + + expect(nouveau_dossier2.en_instruction?).to be true + expect(nouveau_dossier2.en_instruction_at).to eq(date) + + expect(dossier_recu.en_instruction?).to be true + expect(dossier_recu.en_instruction_at).to eq(instruction_date) + + expect(dossier_brouillon.brouillon?).to be true + expect(dossier_brouillon.en_instruction_at).to eq(nil) + } + end + + context "accepte" do + let(:state) { Dossier.states.fetch(:accepte) } + let(:last_operation) { nouveau_dossier1.dossier_operation_logs.last } + + it { + expect(nouveau_dossier1.accepte?).to be true + expect(nouveau_dossier1.en_instruction_at).to eq(date) + expect(nouveau_dossier1.processed_at).to eq(date) + expect(nouveau_dossier1.attestation).to be_present + expect(last_operation.operation).to eq('accepter') + expect(last_operation.automatic_operation?).to be_truthy + + expect(nouveau_dossier2.accepte?).to be true + expect(nouveau_dossier2.en_instruction_at).to eq(date) + expect(nouveau_dossier2.processed_at).to eq(date) + expect(nouveau_dossier2.attestation).to be_present + + expect(dossier_recu.en_instruction?).to be true + expect(dossier_recu.en_instruction_at).to eq(instruction_date) + expect(dossier_recu.processed_at).to eq(nil) + + expect(dossier_brouillon.brouillon?).to be true + expect(dossier_brouillon.en_instruction_at).to eq(nil) + expect(dossier_brouillon.processed_at).to eq(nil) + } + end + end + end +end