Merge pull request #4772 from tchak/discard
Use discard gem instead of DIY solution
This commit is contained in:
commit
67867d7cff
19 changed files with 44 additions and 72 deletions
1
Gemfile
1
Gemfile
|
@ -23,6 +23,7 @@ gem 'delayed_job_active_record'
|
||||||
gem 'delayed_job_web'
|
gem 'delayed_job_web'
|
||||||
gem 'devise' # Gestion des comptes utilisateurs
|
gem 'devise' # Gestion des comptes utilisateurs
|
||||||
gem 'devise-async'
|
gem 'devise-async'
|
||||||
|
gem 'discard'
|
||||||
gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails
|
gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails
|
||||||
gem 'flipper'
|
gem 'flipper'
|
||||||
gem 'flipper-active_record'
|
gem 'flipper-active_record'
|
||||||
|
|
|
@ -187,6 +187,8 @@ GEM
|
||||||
activejob (>= 5.0)
|
activejob (>= 5.0)
|
||||||
devise (>= 4.0)
|
devise (>= 4.0)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.3)
|
||||||
|
discard (1.1.0)
|
||||||
|
activerecord (>= 4.2, < 7)
|
||||||
domain_name (0.5.20180417)
|
domain_name (0.5.20180417)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
dotenv (2.5.0)
|
dotenv (2.5.0)
|
||||||
|
@ -737,6 +739,7 @@ DEPENDENCIES
|
||||||
delayed_job_web
|
delayed_job_web
|
||||||
devise
|
devise
|
||||||
devise-async
|
devise-async
|
||||||
|
discard
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
factory_bot
|
factory_bot
|
||||||
flipper
|
flipper
|
||||||
|
|
|
@ -9,10 +9,10 @@ module Manager
|
||||||
def scoped_resource
|
def scoped_resource
|
||||||
if unfiltered_list?
|
if unfiltered_list?
|
||||||
# Don't display deleted dossiers in the unfiltered list…
|
# Don't display deleted dossiers in the unfiltered list…
|
||||||
Procedure
|
Procedure.kept
|
||||||
else
|
else
|
||||||
# … but allow them to be searched and displayed.
|
# … but allow them to be searched and displayed.
|
||||||
Procedure.with_hidden
|
Procedure.with_discarded
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@ class Dossier < ApplicationRecord
|
||||||
self.ignored_columns = ['json_latlngs']
|
self.ignored_columns = ['json_latlngs']
|
||||||
include DossierFilteringConcern
|
include DossierFilteringConcern
|
||||||
|
|
||||||
|
include Discard::Model
|
||||||
|
self.discard_column = :hidden_at
|
||||||
|
default_scope -> { kept }
|
||||||
|
|
||||||
enum state: {
|
enum state: {
|
||||||
brouillon: 'brouillon',
|
brouillon: 'brouillon',
|
||||||
en_construction: 'en_construction',
|
en_construction: 'en_construction',
|
||||||
|
@ -94,9 +98,6 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
default_scope { where(hidden_at: nil) }
|
|
||||||
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
|
|
||||||
scope :with_hidden, -> { unscope(where: :hidden_at) }
|
|
||||||
scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) }
|
scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) }
|
||||||
scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) }
|
scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) }
|
||||||
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
|
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
|
||||||
|
@ -378,7 +379,7 @@ class Dossier < ApplicationRecord
|
||||||
|
|
||||||
def delete_and_keep_track(author)
|
def delete_and_keep_track(author)
|
||||||
deleted_dossier = DeletedDossier.create_from_dossier(self)
|
deleted_dossier = DeletedDossier.create_from_dossier(self)
|
||||||
update(hidden_at: deleted_dossier.deleted_at)
|
discard!
|
||||||
|
|
||||||
if en_construction?
|
if en_construction?
|
||||||
administration_emails = followers_instructeurs.present? ? followers_instructeurs.map(&:email) : procedure.administrateurs.map(&:email)
|
administration_emails = followers_instructeurs.present? ? followers_instructeurs.map(&:email) : procedure.administrateurs.map(&:email)
|
||||||
|
|
|
@ -16,5 +16,7 @@ class Invite < ApplicationRecord
|
||||||
# and Dossier from their respective `default_scope`s.
|
# and Dossier from their respective `default_scope`s.
|
||||||
# Therefore, we also remove `Invite`s for such effectively deleted `Dossier`s
|
# Therefore, we also remove `Invite`s for such effectively deleted `Dossier`s
|
||||||
# from their default scope.
|
# from their default scope.
|
||||||
default_scope { joins(:dossier).where(dossiers: { hidden_at: nil }) }
|
scope :kept, -> { joins(:dossier).merge(Dossier.kept) }
|
||||||
|
|
||||||
|
default_scope { kept }
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,10 @@ class Procedure < ApplicationRecord
|
||||||
|
|
||||||
include ProcedureStatsConcern
|
include ProcedureStatsConcern
|
||||||
|
|
||||||
|
include Discard::Model
|
||||||
|
self.discard_column = :hidden_at
|
||||||
|
default_scope -> { kept }
|
||||||
|
|
||||||
MAX_DUREE_CONSERVATION = 36
|
MAX_DUREE_CONSERVATION = 36
|
||||||
MAX_DUREE_CONSERVATION_EXPORT = 3.hours
|
MAX_DUREE_CONSERVATION_EXPORT = 3.hours
|
||||||
|
|
||||||
|
@ -44,9 +48,6 @@ class Procedure < ApplicationRecord
|
||||||
accepts_nested_attributes_for :types_de_champ, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
accepts_nested_attributes_for :types_de_champ, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||||
accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||||
|
|
||||||
default_scope { where(hidden_at: nil) }
|
|
||||||
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
|
|
||||||
scope :with_hidden, -> { unscope(where: :hidden_at) }
|
|
||||||
scope :brouillons, -> { where(aasm_state: :brouillon) }
|
scope :brouillons, -> { where(aasm_state: :brouillon) }
|
||||||
scope :publiees, -> { where(aasm_state: :publiee) }
|
scope :publiees, -> { where(aasm_state: :publiee) }
|
||||||
scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
|
scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
|
||||||
|
@ -99,7 +100,6 @@ class Procedure < ApplicationRecord
|
||||||
state :brouillon, initial: true
|
state :brouillon, initial: true
|
||||||
state :publiee
|
state :publiee
|
||||||
state :close
|
state :close
|
||||||
state :hidden
|
|
||||||
state :depubliee
|
state :depubliee
|
||||||
|
|
||||||
event :publish, before: :before_publish, after: :after_publish do
|
event :publish, before: :before_publish, after: :after_publish do
|
||||||
|
@ -112,12 +112,6 @@ class Procedure < ApplicationRecord
|
||||||
transitions from: :publiee, to: :close
|
transitions from: :publiee, to: :close
|
||||||
end
|
end
|
||||||
|
|
||||||
event :hide, after: :after_hide do
|
|
||||||
transitions from: :brouillon, to: :hidden
|
|
||||||
transitions from: :publiee, to: :hidden
|
|
||||||
transitions from: :close, to: :hidden
|
|
||||||
end
|
|
||||||
|
|
||||||
event :unpublish, after: :after_unpublish do
|
event :unpublish, after: :after_unpublish do
|
||||||
transitions from: :publiee, to: :depubliee
|
transitions from: :publiee, to: :depubliee
|
||||||
end
|
end
|
||||||
|
@ -597,6 +591,12 @@ class Procedure < ApplicationRecord
|
||||||
groupe_instructeurs.count > 1
|
groupe_instructeurs.count > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def hide!
|
||||||
|
discard!
|
||||||
|
dossiers.discard_all
|
||||||
|
purge_export_files
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index)
|
def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index)
|
||||||
|
@ -629,13 +629,6 @@ class Procedure < ApplicationRecord
|
||||||
purge_export_files
|
purge_export_files
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_hide
|
|
||||||
now = Time.zone.now
|
|
||||||
update!(hidden_at: now)
|
|
||||||
dossiers.update_all(hidden_at: now)
|
|
||||||
purge_export_files
|
|
||||||
end
|
|
||||||
|
|
||||||
def after_unpublish
|
def after_unpublish
|
||||||
update!(unpublished_at: Time.zone.now)
|
update!(unpublished_at: Time.zone.now)
|
||||||
end
|
end
|
||||||
|
|
|
@ -108,7 +108,7 @@ class User < ApplicationRecord
|
||||||
dossiers.each do |dossier|
|
dossiers.each do |dossier|
|
||||||
dossier.delete_and_keep_track(administration)
|
dossier.delete_and_keep_track(administration)
|
||||||
end
|
end
|
||||||
dossiers.with_hidden.destroy_all
|
dossiers.with_discarded.destroy_all
|
||||||
destroy!
|
destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ as well as a link to its edit page.
|
||||||
<%= link_to 'whitelister', whitelist_manager_procedure_path(procedure), method: :post, class: 'button' %>
|
<%= link_to 'whitelister', whitelist_manager_procedure_path(procedure), method: :post, class: 'button' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if !procedure.hidden? %>
|
<% if !procedure.discarded? %>
|
||||||
<%= link_to 'supprimer la démarche', hide_manager_procedure_path(procedure), method: :post, class: 'button', data: { confirm: "Confirmez-vous la suppression de la démarche ?" } %>
|
<%= link_to 'supprimer la démarche', hide_manager_procedure_path(procedure), method: :post, class: 'button', data: { confirm: "Confirmez-vous la suppression de la démarche ?" } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace :fix_timestamps_of_migrated_dossiers do
|
||||||
desc 'Fix the timestamps of dossiers affected by the faulty PJ migration'
|
desc 'Fix the timestamps of dossiers affected by the faulty PJ migration'
|
||||||
task run: :environment do
|
task run: :environment do
|
||||||
affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0)
|
affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0)
|
||||||
dossiers = Dossier.with_hidden.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range)
|
dossiers = Dossier.with_discarded.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range)
|
||||||
|
|
||||||
progress = ProgressReport.new(dossiers.count)
|
progress = ProgressReport.new(dossiers.count)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ namespace :after_party do
|
||||||
task create_dummy_paths_for_archived_and_hidden_procedures: :environment do
|
task create_dummy_paths_for_archived_and_hidden_procedures: :environment do
|
||||||
rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'"
|
rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'"
|
||||||
|
|
||||||
Procedure.with_hidden.archivees.where(path: nil).each do |p|
|
Procedure.with_discarded.archivees.where(path: nil).each do |p|
|
||||||
p.update_column(:path, SecureRandom.uuid)
|
p.update_column(:path, SecureRandom.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace :after_party do
|
||||||
desc 'Deployment task: create_default_groupe_instructeur'
|
desc 'Deployment task: create_default_groupe_instructeur'
|
||||||
task create_default_groupe_instructeur: :environment do
|
task create_default_groupe_instructeur: :environment do
|
||||||
Procedure
|
Procedure
|
||||||
.with_hidden
|
.with_discarded
|
||||||
.left_outer_joins(:groupe_instructeurs)
|
.left_outer_joins(:groupe_instructeurs)
|
||||||
.where('groupe_instructeurs.id is null')
|
.where('groupe_instructeurs.id is null')
|
||||||
.find_each do |procedure|
|
.find_each do |procedure|
|
||||||
|
|
|
@ -61,7 +61,7 @@ FactoryBot.define do
|
||||||
archived { false }
|
archived { false }
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :hidden do
|
trait :discarded do
|
||||||
hidden_at { Time.zone.now }
|
hidden_at { Time.zone.now }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :hidden do
|
trait :discarded do
|
||||||
after(:build) do |procedure, _evaluator|
|
after(:build) do |procedure, _evaluator|
|
||||||
procedure.path = generate(:published_path)
|
procedure.path = generate(:published_path)
|
||||||
procedure.publish!
|
procedure.publish!
|
||||||
|
|
|
@ -46,8 +46,8 @@ RSpec.describe FindDubiousProceduresJob, type: :job do
|
||||||
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
|
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'and a hidden procedure' do
|
context 'and a discarded procedure' do
|
||||||
let(:procedure) { create(:procedure, :hidden) }
|
let(:procedure) { create(:procedure, :discarded) }
|
||||||
|
|
||||||
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
|
it { expect(AdministrationMailer).to have_received(:dubious_procedures).with([]) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,17 +18,17 @@ describe '20190819142551_create_default_groupe_instructeur.rake' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a procedure hidden without gi' do
|
context 'with a procedure discarded without gi' do
|
||||||
let!(:procedure_hidden_without_gi) { create(:procedure, :hidden) }
|
let!(:procedure_discarded_without_gi) { create(:procedure, :discarded) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
procedure_hidden_without_gi.groupe_instructeurs.destroy_all
|
procedure_discarded_without_gi.groupe_instructeurs.destroy_all
|
||||||
end
|
end
|
||||||
|
|
||||||
it do
|
it do
|
||||||
expect(procedure_hidden_without_gi.groupe_instructeurs).to be_empty
|
expect(procedure_discarded_without_gi.groupe_instructeurs).to be_empty
|
||||||
subject
|
subject
|
||||||
expect(procedure_hidden_without_gi.reload.groupe_instructeurs.pluck(:label)).to eq(['défaut'])
|
expect(procedure_discarded_without_gi.reload.groupe_instructeurs.pluck(:label)).to eq(['défaut'])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,31 +8,13 @@ describe Dossier do
|
||||||
describe 'scopes' do
|
describe 'scopes' do
|
||||||
describe '.default_scope' do
|
describe '.default_scope' do
|
||||||
let!(:dossier) { create(:dossier) }
|
let!(:dossier) { create(:dossier) }
|
||||||
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
let!(:discarded_dossier) { create(:dossier, :discarded) }
|
||||||
|
|
||||||
subject { Dossier.all }
|
subject { Dossier.all }
|
||||||
|
|
||||||
it { is_expected.to match_array([dossier]) }
|
it { is_expected.to match_array([dossier]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.hidden' do
|
|
||||||
let!(:dossier) { create(:dossier) }
|
|
||||||
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
|
||||||
|
|
||||||
subject { Dossier.all.hidden }
|
|
||||||
|
|
||||||
it { is_expected.to match_array([hidden_dossier]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.with_hidden' do
|
|
||||||
let!(:dossier) { create(:dossier) }
|
|
||||||
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
|
||||||
|
|
||||||
subject { Dossier.all.with_hidden }
|
|
||||||
|
|
||||||
it { is_expected.to match_array([dossier, hidden_dossier]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.without_followers' do
|
describe '.without_followers' do
|
||||||
let!(:dossier_with_follower) { create(:dossier, :followed, :with_entreprise, user: user) }
|
let!(:dossier_with_follower) { create(:dossier, :followed, :with_entreprise, user: user) }
|
||||||
let!(:dossier_without_follower) { create(:dossier, :with_entreprise, user: user) }
|
let!(:dossier_without_follower) { create(:dossier, :with_entreprise, user: user) }
|
||||||
|
|
|
@ -61,14 +61,14 @@ describe Invite do
|
||||||
let(:dossier) { create(:dossier, hidden_at: hidden_at) }
|
let(:dossier) { create(:dossier, hidden_at: hidden_at) }
|
||||||
let!(:invite) { create(:invite, email: "email@totor.com", dossier: dossier) }
|
let!(:invite) { create(:invite, email: "email@totor.com", dossier: dossier) }
|
||||||
|
|
||||||
context "when dossier is not hidden" do
|
context "when dossier is not discarded" do
|
||||||
let(:hidden_at) { nil }
|
let(:hidden_at) { nil }
|
||||||
|
|
||||||
it { expect(Invite.count).to eq(1) }
|
it { expect(Invite.count).to eq(1) }
|
||||||
it { expect(Invite.all).to include(invite) }
|
it { expect(Invite.all).to include(invite) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when dossier is hidden" do
|
context "when dossier is discarded" do
|
||||||
let(:hidden_at) { 1.day.ago }
|
let(:hidden_at) { 1.day.ago }
|
||||||
|
|
||||||
it { expect(Invite.count).to eq(0) }
|
it { expect(Invite.count).to eq(0) }
|
||||||
|
|
|
@ -153,22 +153,12 @@ describe Procedure do
|
||||||
|
|
||||||
describe 'scopes' do
|
describe 'scopes' do
|
||||||
let!(:procedure) { create(:procedure) }
|
let!(:procedure) { create(:procedure) }
|
||||||
let!(:hidden_procedure) { create(:procedure, :hidden) }
|
let!(:discarded_procedure) { create(:procedure, :discarded) }
|
||||||
|
|
||||||
describe 'default_scope' do
|
describe 'default_scope' do
|
||||||
subject { Procedure.all }
|
subject { Procedure.all }
|
||||||
it { is_expected.to match_array([procedure]) }
|
it { is_expected.to match_array([procedure]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.hidden' do
|
|
||||||
subject { Procedure.all.hidden }
|
|
||||||
it { is_expected.to match_array([hidden_procedure]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.with_hidden' do
|
|
||||||
subject { Procedure.all.with_hidden }
|
|
||||||
it { is_expected.to match_array([procedure, hidden_procedure]) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validation' do
|
describe 'validation' do
|
||||||
|
|
|
@ -259,7 +259,7 @@ describe User, type: :model do
|
||||||
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
||||||
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
||||||
|
|
||||||
context 'without a hidden dossier' do
|
context 'without a discarded dossier' do
|
||||||
it "keep track of dossiers and delete user" do
|
it "keep track of dossiers and delete user" do
|
||||||
user.delete_and_keep_track_dossiers(administration)
|
user.delete_and_keep_track_dossiers(administration)
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ describe User, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a hidden dossier' do
|
context 'with a discarded dossier' do
|
||||||
let!(:dossier_cache) do
|
let!(:dossier_cache) do
|
||||||
create(:dossier, :en_construction, user: user)
|
create(:dossier, :en_construction, user: user)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue