dossiers: add a validation on dossier individual
Validate that a dossier on a `for_individual?` procedure always has an `individual` associated record. For this, the individual needs to be built before the record is validated (i.e. even before the `before_create` callback is run). This should help with #4596: now if a dossier is created without an `individual`, or if the `invividual` record is later removed, the validation will fail.
This commit is contained in:
parent
e32a42cfe6
commit
5e05556ee8
4 changed files with 45 additions and 66 deletions
|
@ -238,10 +238,6 @@ module Users
|
||||||
)
|
)
|
||||||
|
|
||||||
if dossier.procedure.for_individual
|
if dossier.procedure.for_individual
|
||||||
if current_user.france_connect_information.present?
|
|
||||||
dossier.update_with_france_connect(current_user.france_connect_information)
|
|
||||||
end
|
|
||||||
|
|
||||||
redirect_to identite_dossier_path(dossier)
|
redirect_to identite_dossier_path(dossier)
|
||||||
else
|
else
|
||||||
redirect_to siret_dossier_path(id: dossier.id)
|
redirect_to siret_dossier_path(id: dossier.id)
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Dossier < ApplicationRecord
|
||||||
DRAFT_EXPIRATION = 1.month + 5.days
|
DRAFT_EXPIRATION = 1.month + 5.days
|
||||||
|
|
||||||
has_one :etablissement, dependent: :destroy
|
has_one :etablissement, dependent: :destroy
|
||||||
has_one :individual, dependent: :destroy
|
has_one :individual, validate: false, dependent: :destroy
|
||||||
has_one :attestation, dependent: :destroy
|
has_one :attestation, dependent: :destroy
|
||||||
|
|
||||||
has_one_attached :justificatif_motivation
|
has_one_attached :justificatif_motivation
|
||||||
|
@ -207,9 +207,10 @@ class Dossier < ApplicationRecord
|
||||||
delegate :france_connect_information, to: :user
|
delegate :france_connect_information, to: :user
|
||||||
|
|
||||||
before_validation :update_state_dates, if: -> { state_changed? }
|
before_validation :update_state_dates, if: -> { state_changed? }
|
||||||
|
before_validation :build_default_individual,
|
||||||
|
if: -> { new_record? && procedure.for_individual? && individual.blank? }
|
||||||
|
|
||||||
before_save :build_default_champs, if: Proc.new { groupe_instructeur_id_was.nil? }
|
before_save :build_default_champs, if: Proc.new { groupe_instructeur_id_was.nil? }
|
||||||
before_save :build_default_individual, if: Proc.new { procedure.for_individual? }
|
|
||||||
before_save :update_search_terms
|
before_save :update_search_terms
|
||||||
|
|
||||||
after_save :send_dossier_received
|
after_save :send_dossier_received
|
||||||
|
@ -217,6 +218,7 @@ class Dossier < ApplicationRecord
|
||||||
after_create :send_draft_notification_email
|
after_create :send_draft_notification_email
|
||||||
|
|
||||||
validates :user, presence: true
|
validates :user, presence: true
|
||||||
|
validates :individual, presence: true, if: -> { procedure.for_individual? }
|
||||||
|
|
||||||
def update_search_terms
|
def update_search_terms
|
||||||
self.search_terms = [
|
self.search_terms = [
|
||||||
|
@ -239,8 +241,10 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_default_individual
|
def build_default_individual
|
||||||
if Individual.where(dossier_id: self.id).count == 0
|
self.individual = if france_connect_information.present?
|
||||||
build_individual
|
Individual.from_france_connect(france_connect_information)
|
||||||
|
else
|
||||||
|
Individual.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -579,10 +583,6 @@ class Dossier < ApplicationRecord
|
||||||
!PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP
|
!PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_with_france_connect(fc_information)
|
|
||||||
self.individual = Individual.create_from_france_connect(fc_information)
|
|
||||||
end
|
|
||||||
|
|
||||||
def linked_dossiers
|
def linked_dossiers
|
||||||
Dossier.where(id: champs.filter(&:dossier_link?).map(&:value).compact)
|
Dossier.where(id: champs.filter(&:dossier_link?).map(&:value).compact)
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,8 +9,8 @@ class Individual < ApplicationRecord
|
||||||
GENDER_MALE = 'M.'
|
GENDER_MALE = 'M.'
|
||||||
GENDER_FEMALE = 'Mme'
|
GENDER_FEMALE = 'Mme'
|
||||||
|
|
||||||
def self.create_from_france_connect(fc_information)
|
def self.from_france_connect(fc_information)
|
||||||
create!(
|
new(
|
||||||
nom: fc_information.family_name,
|
nom: fc_information.family_name,
|
||||||
prenom: fc_information.given_name,
|
prenom: fc_information.given_name,
|
||||||
gender: fc_information.gender == 'female' ? GENDER_FEMALE : GENDER_MALE
|
gender: fc_information.gender == 'female' ? GENDER_FEMALE : GENDER_MALE
|
||||||
|
|
|
@ -5,6 +5,13 @@ describe Dossier do
|
||||||
|
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
|
subject(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
it { is_expected.to validate_presence_of(:individual) }
|
||||||
|
end
|
||||||
|
|
||||||
describe "without_followers scope" do
|
describe "without_followers scope" do
|
||||||
let!(:dossier) { create(:dossier, :followed, :with_entreprise, user: user) }
|
let!(:dossier) { create(:dossier, :followed, :with_entreprise, user: user) }
|
||||||
let!(:dossier2) { create(:dossier, :with_entreprise, user: user) }
|
let!(:dossier2) { create(:dossier, :with_entreprise, user: user) }
|
||||||
|
@ -112,56 +119,44 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#build_default_champs' do
|
describe '#create' do
|
||||||
context 'when dossier is linked to a procedure with type_de_champ_public and private' do
|
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private) }
|
||||||
let(:dossier) { create(:dossier, user: user) }
|
let(:dossier) { create(:dossier, procedure: procedure, user: user) }
|
||||||
|
|
||||||
it 'build all champs needed' do
|
it 'builds public and private champs' do
|
||||||
expect(dossier.champs.count).to eq(1)
|
expect(dossier.champs.count).to eq(1)
|
||||||
|
expect(dossier.champs_private.count).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the dossier belongs to a procedure for individuals' do
|
||||||
|
let(:procedure) { create(:procedure, :with_type_de_champ, for_individual: true) }
|
||||||
|
|
||||||
|
it 'creates a default individual' do
|
||||||
|
expect(dossier.individual).to be_present
|
||||||
|
expect(dossier.individual.nom).to be_nil
|
||||||
|
expect(dossier.individual.prenom).to be_nil
|
||||||
|
expect(dossier.individual.gender).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'build all champs_private needed' do
|
context 'and the user signs-in using France Connect' do
|
||||||
expect(dossier.champs_private.count).to eq(1)
|
let(:france_connect_information) { build(:france_connect_information) }
|
||||||
|
let(:user) { build(:user, france_connect_information: france_connect_information) }
|
||||||
|
|
||||||
|
it 'fills the individual with the informations from France Connect' do
|
||||||
|
expect(dossier.individual.nom).to eq('DUBOIS')
|
||||||
|
expect(dossier.individual.prenom).to eq('Angela Claire Louise')
|
||||||
|
expect(dossier.individual.gender).to eq(Individual::GENDER_FEMALE)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
describe '#build_default_individual' do
|
context 'when the dossier belongs to a procedure for moral personas' do
|
||||||
context 'when dossier is linked to a procedure with for_individual attr false' do
|
let(:procedure) { create(:procedure, :with_type_de_champ, for_individual: false) }
|
||||||
let(:dossier) { create(:dossier, user: user) }
|
|
||||||
|
|
||||||
it 'have no object created' do
|
it 'doesn’t create a individual' do
|
||||||
expect(dossier.individual).to be_nil
|
expect(dossier.individual).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when dossier is linked to a procedure with for_individual attr true' do
|
|
||||||
let(:dossier) { create(:dossier, user: user, procedure: (create :procedure, for_individual: true)) }
|
|
||||||
|
|
||||||
it 'have no object created' do
|
|
||||||
expect(dossier.individual).not_to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#save' do
|
|
||||||
subject { build(:dossier, procedure: procedure, user: user) }
|
|
||||||
let!(:procedure) { create(:procedure) }
|
|
||||||
|
|
||||||
context 'when is linked to a procedure' do
|
|
||||||
it 'creates default champs' do
|
|
||||||
expect(subject).to receive(:build_default_champs)
|
|
||||||
subject.save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
context 'when is not linked to a procedure' do
|
|
||||||
subject { create(:dossier, procedure: nil, user: user) }
|
|
||||||
|
|
||||||
it 'does not create default champs' do
|
|
||||||
expect(subject).not_to receive(:build_default_champs)
|
|
||||||
subject.update(state: Dossier.states.fetch(:en_construction))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1019,18 +1014,6 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#update_with_france_connect' do
|
|
||||||
let(:dossier) { create(:dossier, user: user) }
|
|
||||||
let(:user_info) { create(:france_connect_information) }
|
|
||||||
|
|
||||||
it {
|
|
||||||
dossier.update_with_france_connect(user_info)
|
|
||||||
expect(dossier.individual.gender).to eq 'Mme'
|
|
||||||
expect(dossier.individual.nom).to eq user_info.family_name
|
|
||||||
expect(dossier.individual.prenom).to eq user_info.given_name
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#for_procedure' do
|
describe '#for_procedure' do
|
||||||
let!(:procedure_1) { create(:procedure) }
|
let!(:procedure_1) { create(:procedure) }
|
||||||
let!(:procedure_2) { create(:procedure) }
|
let!(:procedure_2) { create(:procedure) }
|
||||||
|
|
Loading…
Add table
Reference in a new issue