Merge pull request #8388 from demarches-simplifiees/prefill/siret

feat(dossier): prefill siret champ
This commit is contained in:
Sébastien Carceles 2023-02-27 13:20:38 +00:00 committed by GitHub
commit 899bb73ce8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 260 additions and 89 deletions

View file

@ -2,7 +2,7 @@
id: @champ.input_id, id: @champ.input_id,
aria: { describedby: @champ.describedby_id }, aria: { describedby: @champ.describedby_id },
placeholder: t(".placeholder"), placeholder: t(".placeholder"),
data: { controller: 'turbo-input', turbo_input_url_value: champs_siret_path(@champ.id) }, data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.etablissement.blank?, turbo_input_url_value: champs_siret_path(@champ.id) },
required: @champ.required?, required: @champ.required?,
pattern: "[0-9]{14}", pattern: "[0-9]{14}",
title: t(".title"), title: t(".title"),

View file

@ -3,61 +3,11 @@ class Champs::SiretController < ApplicationController
def show def show
@champ = policy_scope(Champ).find(params[:champ_id]) @champ = policy_scope(Champ).find(params[:champ_id])
@siret = read_param_value(@champ.input_name, 'value')
@etablissement = @champ.etablissement
if @siret.empty? if @champ.fetch_etablissement!(read_param_value(@champ.input_name, 'value'), current_user)
return clear_siret_and_etablissement @siret = @champ.etablissement.siret
else
@siret = @champ.etablissement_fetch_error_key
end end
if !Siret.new(siret: @siret).valid?
# i18n-tasks-use t('errors.messages.invalid_siret')
return siret_error(:invalid)
end
begin
etablissement = find_etablissement_with_siret
rescue => error
if error.try(:network_error?) && !APIEntrepriseService.api_up?
# TODO: notify ops
etablissement = APIEntrepriseService.create_etablissement_as_degraded_mode(@champ, @siret, current_user.id)
if !@champ.nil?
@champ.update!(value: etablissement.siret, etablissement: etablissement)
end
@siret = :api_entreprise_down
return
else
Sentry.capture_exception(error, extra: { dossier_id: @champ.dossier_id, siret: @siret })
# i18n-tasks-use t('errors.messages.siret_network_error')
return siret_error(:network_error)
end
end
if etablissement.nil?
# i18n-tasks-use t('errors.messages.siret_not_found')
return siret_error(:not_found)
end
@etablissement = etablissement
if !@champ.nil?
@champ.update!(value: etablissement.siret, etablissement: etablissement)
end
end
private
def find_etablissement_with_siret
APIEntrepriseService.create_etablissement(@champ, @siret, current_user.id)
end
def clear_siret_and_etablissement
@champ.update!(value: '')
@etablissement&.destroy
end
def siret_error(error)
clear_siret_and_etablissement
@siret = error
end end
end end

View file

@ -4,13 +4,18 @@ import { ApplicationController } from './application_controller';
export class TurboInputController extends ApplicationController { export class TurboInputController extends ApplicationController {
static values = { static values = {
url: String url: String,
loadOnConnect: { type: Boolean, default: false }
}; };
declare readonly urlValue: string; declare readonly urlValue: string;
declare readonly loadOnConnectValue: boolean;
connect(): void { connect(): void {
this.on('input', () => this.debounce(this.load, 200)); this.on('input', () => this.debounce(this.load, 200));
if (this.loadOnConnectValue) {
this.load();
}
} }
private load(): void { private load(): void {

View file

@ -21,6 +21,8 @@
# type_de_champ_id :integer # type_de_champ_id :integer
# #
class Champs::SiretChamp < Champ class Champs::SiretChamp < Champ
include SiretChampEtablissementFetchableConcern
def search_terms def search_terms
etablissement.present? ? etablissement.search_terms : [value] etablissement.present? ? etablissement.search_terms : [value]
end end

View file

@ -0,0 +1,46 @@
module SiretChampEtablissementFetchableConcern
extend ActiveSupport::Concern
attr_reader :etablissement_fetch_error_key
def fetch_etablissement!(siret, user)
return clear_etablissement!(:empty) if siret.empty?
return clear_etablissement!(:invalid_length) if invalid_because?(siret, :length) # i18n-tasks-use t('errors.messages.invalid_siret_length')
return clear_etablissement!(:invalid_checksum) if invalid_because?(siret, :checksum) # i18n-tasks-use t('errors.messages.invalid_siret_checksum')
return clear_etablissement!(:not_found) unless (etablissement = APIEntrepriseService.create_etablissement(self, siret, user&.id)) # i18n-tasks-use t('errors.messages.siret_not_found')
update!(value: siret, etablissement: etablissement)
rescue => error
if error.try(:network_error?) && !APIEntrepriseService.api_up?
# TODO: notify ops
update!(
value: siret,
etablissement: APIEntrepriseService.create_etablissement_as_degraded_mode(self, siret, user.id)
)
@etablissement_fetch_error_key = :api_entreprise_down
false
else
Sentry.capture_exception(error, extra: { dossier_id: dossier_id, siret: siret })
clear_etablissement!(:network_error) # i18n-tasks-use t('errors.messages.siret_network_error')
end
end
private
def clear_etablissement!(error_key)
@etablissement_fetch_error_key = error_key
etablissement_to_destroy = etablissement
update!(etablissement: nil)
etablissement_to_destroy&.destroy
false
end
def invalid_because?(siret, criteria)
validatable_siret = Siret.new(siret: siret)
return false if validatable_siret.valid?
validatable_siret.errors.details[:siret].any? && validatable_siret.errors.details[:siret].first[:error] == criteria
end
end

View file

@ -272,7 +272,8 @@ class TypeDeChamp < ApplicationRecord
TypeDeChamp.type_champs.fetch(:drop_down_list), TypeDeChamp.type_champs.fetch(:drop_down_list),
TypeDeChamp.type_champs.fetch(:repetition), TypeDeChamp.type_champs.fetch(:repetition),
TypeDeChamp.type_champs.fetch(:multiple_drop_down_list), TypeDeChamp.type_champs.fetch(:multiple_drop_down_list),
TypeDeChamp.type_champs.fetch(:epci) TypeDeChamp.type_champs.fetch(:epci),
TypeDeChamp.type_champs.fetch(:siret)
]) ])
end end

View file

@ -15,6 +15,9 @@ class APIEntrepriseService
etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params
return nil if etablissement_params.empty? return nil if etablissement_params.empty?
entreprise_params = APIEntreprise::EntrepriseAdapter.new(siret, procedure_id).to_params
etablissement_params.merge!(entreprise_params) if entreprise_params.any?
etablissement = dossier_or_champ.build_etablissement(etablissement_params) etablissement = dossier_or_champ.build_etablissement(etablissement_params)
etablissement.save! etablissement.save!

View file

@ -1 +1 @@
= turbo_stream.update dom_id(@champ, :siret_info), partial: 'shared/champs/siret/etablissement', locals: { siret: @siret, etablissement: @etablissement } = turbo_stream.update dom_id(@champ, :siret_info), partial: 'shared/champs/siret/etablissement', locals: { siret: @siret, etablissement: @champ.etablissement }

View file

@ -1,6 +1,9 @@
- case siret - case siret
- when :invalid - when :invalid_length
Le numéro de SIRET doit comporter exactement 14 chiffres. = t('errors.messages.invalid_siret_length')
- when :invalid_checksum
= t('errors.messages.invalid_siret_checksum')
- when :not_found - when :not_found
Nous navons pas trouvé détablissement correspondant à ce numéro de SIRET. Nous navons pas trouvé détablissement correspondant à ce numéro de SIRET.

View file

@ -136,6 +136,7 @@ en:
date_html: ISO8601 date date_html: ISO8601 date
datetime_html: ISO8601 datetime datetime_html: ISO8601 datetime
drop_down_list_other_html: Any value drop_down_list_other_html: Any value
siret_html: A SIRET number
repetition_html: A array of hashes with possible values for each field of the repetition. repetition_html: A array of hashes with possible values for each field of the repetition.
epci_html: An array of the department code and the <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">EPCI one</a>. epci_html: An array of the department code and the <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">EPCI one</a>.
examples: examples:
@ -154,6 +155,7 @@ en:
date: "2023-02-01" date: "2023-02-01"
datetime: "2023-02-01T10:30" datetime: "2023-02-01T10:30"
checkbox: "true" checkbox: "true"
siret: 13002526500013
prefill_link_title: Prefill link (GET) prefill_link_title: Prefill link (GET)
prefill_link_info: Use the button to copy the link, then remplace the values with your data. prefill_link_info: Use the button to copy the link, then remplace the values with your data.
prefill_link_too_long: Warning, the prefill link is too long and may not work on all browsers. prefill_link_too_long: Warning, the prefill link is too long and may not work on all browsers.
@ -509,7 +511,8 @@ en:
dossier_not_found: "The file does not exist or you do not have access to it." dossier_not_found: "The file does not exist or you do not have access to it."
# # dossier_map_not_activated: "The file does not have access to the map." # # dossier_map_not_activated: "The file does not have access to the map."
targeted_user_link_expired: "This invitation link or the file is no longer available." targeted_user_link_expired: "This invitation link or the file is no longer available."
invalid_siret: "The SIRET is incorrect" invalid_siret_length: "The SIRET number must contain exactly 14 numbers."
invalid_siret_checksum: "The SIRET number is invalid."
procedure_not_found: "The procedure does not exist" procedure_not_found: "The procedure does not exist"
siret_unknown: 'Sorry, we did not find any establishment registered under this SIRET number.' siret_unknown: 'Sorry, we did not find any establishment registered under this SIRET number.'
siret_network_error: 'Désolé, la récupération des informations SIRET est temporairement indisponible. Veuillez réessayer dans quelques instants.' siret_network_error: 'Désolé, la récupération des informations SIRET est temporairement indisponible. Veuillez réessayer dans quelques instants.'

View file

@ -127,6 +127,7 @@ fr:
datetime_html: Datetime au format ISO8601 datetime_html: Datetime au format ISO8601
date_html: Date au format ISO8601 date_html: Date au format ISO8601
drop_down_list_other_html: Toute valeur drop_down_list_other_html: Toute valeur
siret_html: Un numéro de SIRET
repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition. repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition.
epci_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">celui de l'EPCI</a>. epci_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">celui de l'EPCI</a>.
examples: examples:
@ -146,6 +147,7 @@ fr:
date: "2023-02-01" date: "2023-02-01"
datetime: "2023-02-01T10:30" datetime: "2023-02-01T10:30"
checkbox: "true" checkbox: "true"
siret: 13002526500013
prefill_link_title: Lien de préremplissage (GET) prefill_link_title: Lien de préremplissage (GET)
prefill_link_info: Copiez le lien grâce au bouton ci-dessous et remplacez les valeurs par les données dont vous disposez. prefill_link_info: Copiez le lien grâce au bouton ci-dessous et remplacez les valeurs par les données dont vous disposez.
prefill_link_too_long: Attention, ce lien de préremplissage est trop long et risque de ne pas fonctionner sur certains navigateurs. prefill_link_too_long: Attention, ce lien de préremplissage est trop long et risque de ne pas fonctionner sur certains navigateurs.
@ -505,7 +507,8 @@ fr:
dossier_not_found: "Le dossier nexiste pas ou vous ny avez pas accès." dossier_not_found: "Le dossier nexiste pas ou vous ny avez pas accès."
# dossier_map_not_activated: "Le dossier na pas accès à la cartographie." # dossier_map_not_activated: "Le dossier na pas accès à la cartographie."
targeted_user_link_expired: "Ce lien dinvitation nest plus valable ou le dossier nest plus accessible." targeted_user_link_expired: "Ce lien dinvitation nest plus valable ou le dossier nest plus accessible."
invalid_siret: "Le siret est incorrect" invalid_siret_length: "Le numéro de SIRET doit comporter exactement 14 chiffres."
invalid_siret_checksum: "Le format du numéro de SIRET est invalide."
procedure_not_found: "La démarche nexiste pas" procedure_not_found: "La démarche nexiste pas"
siret_unknown: 'Désolé, nous navons pas trouvé détablissement enregistré correspondant à ce numéro SIRET.' siret_unknown: 'Désolé, nous navons pas trouvé détablissement enregistré correspondant à ce numéro SIRET.'
siret_network_error: 'Désolé, la récupération des informations SIRET est temporairement indisponible. Veuillez réessayer dans quelques instants.' siret_network_error: 'Désolé, la récupération des informations SIRET est temporairement indisponible. Veuillez réessayer dans quelques instants.'

View file

@ -31,6 +31,8 @@ describe Champs::SiretController, type: :controller do
sign_in user sign_in user
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
.to_return(status: api_etablissement_status, body: api_etablissement_body) .to_return(status: api_etablissement_status, body: api_etablissement_body)
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siret[0..8]}/)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
allow_any_instance_of(APIEntrepriseToken).to receive(:roles) allow_any_instance_of(APIEntrepriseToken).to receive(:roles)
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"]) .and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired) allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired)
@ -39,10 +41,8 @@ describe Champs::SiretController, type: :controller do
context 'when the SIRET is empty' do context 'when the SIRET is empty' do
subject! { get :show, params: params, format: :turbo_stream } subject! { get :show, params: params, format: :turbo_stream }
it 'clears the etablissement and SIRET on the model' do it 'clears the etablissement on the model' do
champ.reload expect(champ.reload.etablissement).to be_nil
expect(champ.etablissement).to be_nil
expect(champ.value).to be_empty
end end
it 'clears any information or error message' do it 'clears any information or error message' do
@ -50,15 +50,13 @@ describe Champs::SiretController, type: :controller do
end end
end end
context 'when the SIRET is invalid' do context "when the SIRET is invalid because of it's length" do
let(:siret) { '1234' } let(:siret) { '1234' }
subject! { get :show, params: params, format: :turbo_stream } subject! { get :show, params: params, format: :turbo_stream }
it 'clears the etablissement and SIRET on the model' do it 'clears the etablissement on the model' do
champ.reload expect(champ.reload.etablissement).to be_nil
expect(champ.etablissement).to be_nil
expect(champ.value).to be_empty
end end
it 'displays a “SIRET is invalid” error message' do it 'displays a “SIRET is invalid” error message' do
@ -66,6 +64,20 @@ describe Champs::SiretController, type: :controller do
end end
end end
context "when the SIRET is invalid because of it's checksum" do
let(:siret) { '82812345600023' }
subject! { get :show, params: params, format: :turbo_stream }
it 'clears the etablissement on the model' do
expect(champ.reload.etablissement).to be_nil
end
it 'displays a “SIRET is invalid” error message' do
expect(response.body).to include('Le format du numéro de SIRET est invalide.')
end
end
context 'when the API is unavailable due to network error' do context 'when the API is unavailable due to network error' do
let(:siret) { '82161143100015' } let(:siret) { '82161143100015' }
let(:api_etablissement_status) { 503 } let(:api_etablissement_status) { 503 }
@ -76,10 +88,8 @@ describe Champs::SiretController, type: :controller do
subject! { get :show, params: params, format: :turbo_stream } subject! { get :show, params: params, format: :turbo_stream }
it 'clears the etablissement and SIRET on the model' do it 'clears the etablissement on the model' do
champ.reload expect(champ.reload.etablissement).to be_nil
expect(champ.etablissement).to be_nil
expect(champ.value).to be_empty
end end
it 'displays a “API is unavailable” error message' do it 'displays a “API is unavailable” error message' do
@ -115,10 +125,8 @@ describe Champs::SiretController, type: :controller do
subject! { get :show, params: params, format: :turbo_stream } subject! { get :show, params: params, format: :turbo_stream }
it 'clears the etablissement and SIRET on the model' do it 'clears the etablissement on the model' do
champ.reload expect(champ.reload.etablissement).to be_nil
expect(champ.etablissement).to be_nil
expect(champ.value).to be_empty
end end
it 'displays a “SIRET not found” error message' do it 'displays a “SIRET not found” error message' do

View file

@ -196,6 +196,8 @@ describe Users::DossiersController, type: :controller do
sign_in(user) sign_in(user)
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
.to_return(status: api_etablissement_status, body: api_etablissement_body) .to_return(status: api_etablissement_status, body: api_etablissement_body)
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
.to_return(body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'), status: 200)
allow_any_instance_of(APIEntrepriseToken).to receive(:roles) allow_any_instance_of(APIEntrepriseToken).to receive(:roles)
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"]) .and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired) allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired)

View file

@ -6,7 +6,10 @@ RSpec.describe DossierPrefillableConcern do
let(:dossier) { create(:dossier, :brouillon, procedure: procedure) } let(:dossier) { create(:dossier, :brouillon, procedure: procedure) }
let(:types_de_champ_public) { [] } let(:types_de_champ_public) { [] }
subject(:fill) { dossier.prefill!(values); dossier.reload } subject(:fill) do
dossier.prefill!(values)
dossier.reload
end
shared_examples 'a dossier marked as prefilled' do shared_examples 'a dossier marked as prefilled' do
it 'marks the dossier as prefilled' do it 'marks the dossier as prefilled' do

View file

@ -0,0 +1,115 @@
RSpec.describe SiretChampEtablissementFetchableConcern do
describe '.fetch_etablissement!' do
let(:api_etablissement_status) { 200 }
let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
let(:token_expired) { false }
let!(:champ) { create(:champ_siret) }
before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
.to_return(status: api_etablissement_status, body: api_etablissement_body)
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siret[0..8]}/)
.to_return(body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'), status: 200)
allow_any_instance_of(APIEntrepriseToken).to receive(:roles)
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(token_expired)
end
subject(:fetch_etablissement!) { champ.fetch_etablissement!(siret, build_stubbed(:user)) }
shared_examples 'an error occured' do |error|
it { expect { fetch_etablissement! }.to change { champ.reload.etablissement }.to(nil) }
it { expect { fetch_etablissement! }.to change { Etablissement.count }.by(-1) }
it { expect(fetch_etablissement!).to eq(false) }
it 'populates the etablissement_fetch_error_key' do
fetch_etablissement!
expect(champ.etablissement_fetch_error_key).to eq(error)
end
end
context 'when the SIRET is empty' do
let(:siret) { '' }
it_behaves_like 'an error occured', :empty
end
context "when the SIRET is invalid because of it's length" do
let(:siret) { '1234' }
it_behaves_like 'an error occured', :invalid_length
end
context "when the SIRET is invalid because of it's checksum" do
let(:siret) { '82812345600023' }
it_behaves_like 'an error occured', :invalid_checksum
end
context 'when the API is unavailable due to network error' do
let(:siret) { '82161143100015' }
let(:api_etablissement_status) { 503 }
before { expect(APIEntrepriseService).to receive(:api_up?).and_return(true) }
it_behaves_like 'an error occured', :network_error
it 'sends the error to Sentry' do
expect(Sentry).to receive(:capture_exception)
fetch_etablissement!
end
end
context 'when the API is unavailable due to an api maintenance or pb' do
let(:siret) { '82161143100015' }
let(:api_etablissement_status) { 502 }
before { expect(APIEntrepriseService).to receive(:api_up?).and_return(false) }
it { expect { fetch_etablissement! }.to change { champ.reload.value }.to(siret) }
it { expect { fetch_etablissement! }.to change { champ.reload.etablissement } }
it { expect { fetch_etablissement! }.to change { champ.reload.etablissement.as_degraded_mode? }.to(true) }
it { expect { fetch_etablissement! }.to change { Etablissement.count }.by(1) }
it { expect(fetch_etablissement!).to eq(false) }
it 'populates the etablissement_fetch_error_key' do
fetch_etablissement!
expect(champ.etablissement_fetch_error_key).to eq(:api_entreprise_down)
end
end
context 'when the SIRET is valid but unknown' do
let(:siret) { '00000000000000' }
let(:api_etablissement_status) { 404 }
it_behaves_like 'an error occured', :not_found
end
context 'when the SIRET informations are retrieved successfully' do
let(:siret) { '41816609600051' }
let(:api_etablissement_status) { 200 }
let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
it { expect { fetch_etablissement! }.to change { champ.reload.value }.to(siret) }
it { expect { fetch_etablissement! }.to change { champ.reload.etablissement.siret }.to(siret) }
it { expect { fetch_etablissement! }.to change { champ.reload.etablissement.naf }.to("6202A") }
it { expect { fetch_etablissement! }.to change { Etablissement.count }.by(1) }
it { expect(fetch_etablissement!).to eq(true) }
it "fetches the entreprise raison sociale" do
fetch_etablissement!
expect(champ.reload.etablissement.entreprise_raison_sociale).to eq("OCTO-TECHNOLOGY")
end
end
end
end

View file

@ -142,6 +142,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is authorized", :communes, ['01', '01457'] it_behaves_like "a champ public value that is authorized", :communes, ['01', '01457']
it_behaves_like "a champ public value that is authorized", :multiple_drop_down_list, ["val1", "val2"] it_behaves_like "a champ public value that is authorized", :multiple_drop_down_list, ["val1", "val2"]
it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935'] it_behaves_like "a champ public value that is authorized", :epci, ['01', '200042935']
it_behaves_like "a champ public value that is authorized", :siret, "13002526500013"
context "when the public type de champ is authorized (repetition)" do context "when the public type de champ is authorized (repetition)" do
let(:types_de_champ_public) { [{ type: :repetition, children: [{ type: :text }] }] } let(:types_de_champ_public) { [{ type: :repetition, children: [{ type: :text }] }] }
@ -175,6 +176,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ private value that is authorized", :checkbox, "false" it_behaves_like "a champ private value that is authorized", :checkbox, "false"
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value" it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
it_behaves_like "a champ private value that is authorized", :regions, "93" it_behaves_like "a champ private value that is authorized", :regions, "93"
it_behaves_like "a champ private value that is authorized", :siret, "13002526500013"
it_behaves_like "a champ private value that is authorized", :departements, "03" it_behaves_like "a champ private value that is authorized", :departements, "03"
it_behaves_like "a champ private value that is authorized", :communes, ['01', '01457'] it_behaves_like "a champ private value that is authorized", :communes, ['01', '01457']
it_behaves_like "a champ private value that is authorized", :multiple_drop_down_list, ["val1", "val2"] it_behaves_like "a champ private value that is authorized", :multiple_drop_down_list, ["val1", "val2"]
@ -217,7 +219,6 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is unauthorized", :regions, "value" it_behaves_like "a champ public value that is unauthorized", :regions, "value"
it_behaves_like "a champ public value that is unauthorized", :departements, "value" it_behaves_like "a champ public value that is unauthorized", :departements, "value"
it_behaves_like "a champ public value that is unauthorized", :communes, "value" it_behaves_like "a champ public value that is unauthorized", :communes, "value"
it_behaves_like "a champ public value that is unauthorized", :siret, "value"
it_behaves_like "a champ public value that is unauthorized", :rna, "value" it_behaves_like "a champ public value that is unauthorized", :rna, "value"
it_behaves_like "a champ public value that is unauthorized", :annuaire_education, "value" it_behaves_like "a champ public value that is unauthorized", :annuaire_education, "value"
it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, ["value"] it_behaves_like "a champ public value that is unauthorized", :multiple_drop_down_list, ["value"]

View file

@ -255,6 +255,7 @@ describe TypeDeChamp do
it_behaves_like "a prefillable type de champ", :type_de_champ_repetition it_behaves_like "a prefillable type de champ", :type_de_champ_repetition
it_behaves_like "a prefillable type de champ", :type_de_champ_multiple_drop_down_list it_behaves_like "a prefillable type de champ", :type_de_champ_multiple_drop_down_list
it_behaves_like "a prefillable type de champ", :type_de_champ_epci it_behaves_like "a prefillable type de champ", :type_de_champ_epci
it_behaves_like "a prefillable type de champ", :type_de_champ_siret
it_behaves_like "a non-prefillable type de champ", :type_de_champ_number it_behaves_like "a non-prefillable type de champ", :type_de_champ_number
it_behaves_like "a non-prefillable type de champ", :type_de_champ_dossier_link it_behaves_like "a non-prefillable type de champ", :type_de_champ_dossier_link
@ -269,7 +270,6 @@ describe TypeDeChamp do
it_behaves_like "a non-prefillable type de champ", :type_de_champ_mesri it_behaves_like "a non-prefillable type de champ", :type_de_champ_mesri
it_behaves_like "a non-prefillable type de champ", :type_de_champ_carte it_behaves_like "a non-prefillable type de champ", :type_de_champ_carte
it_behaves_like "a non-prefillable type de champ", :type_de_champ_address it_behaves_like "a non-prefillable type de champ", :type_de_champ_address
it_behaves_like "a non-prefillable type de champ", :type_de_champ_siret
it_behaves_like "a non-prefillable type de champ", :type_de_champ_rna it_behaves_like "a non-prefillable type de champ", :type_de_champ_rna
it_behaves_like "a non-prefillable type de champ", :type_de_champ_annuaire_education it_behaves_like "a non-prefillable type de champ", :type_de_champ_annuaire_education
end end

View file

@ -15,11 +15,16 @@ describe APIEntrepriseService do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
.to_return(body: etablissements_body, status: etablissements_status) .to_return(body: etablissements_body, status: etablissements_status)
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siret[0..8]}/)
.to_return(body: entreprises_body, status: entreprises_status)
end end
let(:siret) { '41816609600051' } let(:siret) { '41816609600051' }
let(:raison_sociale) { "OCTO-TECHNOLOGY" }
let(:etablissements_status) { 200 } let(:etablissements_status) { 200 }
let(:etablissements_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') } let(:etablissements_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
let(:entreprises_status) { 200 }
let(:entreprises_body) { File.read('spec/fixtures/files/api_entreprise/entreprises.json') }
let(:valid_token) { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" } let(:valid_token) { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" }
let(:procedure) { create(:procedure, api_entreprise_token: valid_token) } let(:procedure) { create(:procedure, api_entreprise_token: valid_token) }
let(:dossier) { create(:dossier, procedure: procedure) } let(:dossier) { create(:dossier, procedure: procedure) }
@ -35,6 +40,10 @@ describe APIEntrepriseService do
expect(subject[:siret]).to eq(siret) expect(subject[:siret]).to eq(siret)
end end
it 'should fetch entreprise params' do
expect(subject[:entreprise_raison_sociale]).to eq(raison_sociale)
end
it_behaves_like 'schedule fetch of all etablissement params' it_behaves_like 'schedule fetch of all etablissement params'
end end

View file

@ -1,13 +1,9 @@
shared_examples "the user has got a prefilled dossier, owned by themselves" do shared_examples "the user has got a prefilled dossier, owned by themselves" do
scenario "the user has got a prefilled dossier, owned by themselves" do scenario "the user has got a prefilled dossier, owned by themselves" do
siret = '41816609600051'
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
expect(dossier.user).to eq(user) expect(dossier.user).to eq(user)
expect(page).to have_current_path siret_dossier_path(procedure.dossiers.last) expect(page).to have_current_path siret_dossier_path(procedure.dossiers.last)
fill_in 'Numéro SIRET', with: siret fill_in 'Numéro SIRET', with: siret_value
click_on 'Valider' click_on 'Valider'
expect(page).to have_current_path(etablissement_dossier_path(dossier)) expect(page).to have_current_path(etablissement_dossier_path(dossier))
@ -18,6 +14,7 @@ shared_examples "the user has got a prefilled dossier, owned by themselves" do
expect(page).to have_field(type_de_champ_text.libelle, with: text_value) expect(page).to have_field(type_de_champ_text.libelle, with: text_value)
expect(page).to have_field(type_de_champ_phone.libelle, with: phone_value) expect(page).to have_field(type_de_champ_phone.libelle, with: phone_value)
expect(page).to have_css('label', text: type_de_champ_phone.libelle) expect(page).to have_css('label', text: type_de_champ_phone.libelle)
expect(page).to have_field(type_de_champ_siret.libelle, with: siret_value)
expect(page).to have_css('h3', text: type_de_champ_repetition.libelle) expect(page).to have_css('h3', text: type_de_champ_repetition.libelle)
expect(page).to have_field(text_repetition_libelle, with: text_repetition_value) expect(page).to have_field(text_repetition_libelle, with: text_repetition_value)
expect(page).to have_field(integer_repetition_libelle, with: integer_repetition_value) expect(page).to have_field(integer_repetition_libelle, with: integer_repetition_value)

View file

@ -1,4 +1,4 @@
describe 'Prefilling a dossier (with a GET request):' do describe 'Prefilling a dossier (with a GET request):', js: true do
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) } let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
let(:password) { 'my-s3cure-p4ssword' } let(:password) { 'my-s3cure-p4ssword' }
@ -8,13 +8,16 @@ describe 'Prefilling a dossier (with a GET request):' do
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) } let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) } let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
let(:type_de_champ_siret) { create(:type_de_champ_siret, procedure: procedure) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) } let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) }
let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) } let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) }
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) } let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
let(:type_de_champ_commune) { create(:type_de_champ_communes, procedure: procedure) } let(:type_de_champ_commune) { create(:type_de_champ_communes, procedure: procedure) }
let(:type_de_champ_repetition) { create(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure) } let(:type_de_champ_repetition) { create(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure) }
let(:text_value) { "My Neighbor Totoro is the best movie ever" } let(:text_value) { "My Neighbor Totoro is the best movie ever" }
let(:phone_value) { "invalid phone value" } let(:phone_value) { "invalid phone value" }
let(:siret_value) { '41816609600051' }
let(:datetime_value) { "2023-02-01T10:32" } let(:datetime_value) { "2023-02-01T10:32" }
let(:multiple_drop_down_list_values) { let(:multiple_drop_down_list_values) {
[ [
@ -39,6 +42,7 @@ describe 'Prefilling a dossier (with a GET request):' do
"champ_#{type_de_champ_multiple_drop_down_list.to_typed_id_for_query}" => multiple_drop_down_list_values, "champ_#{type_de_champ_multiple_drop_down_list.to_typed_id_for_query}" => multiple_drop_down_list_values,
"champ_#{type_de_champ_epci.to_typed_id_for_query}" => epci_value, "champ_#{type_de_champ_epci.to_typed_id_for_query}" => epci_value,
"champ_#{type_de_champ_commune.to_typed_id_for_query}" => commune_value, "champ_#{type_de_champ_commune.to_typed_id_for_query}" => commune_value,
"champ_#{type_de_champ_siret.to_typed_id_for_query}" => siret_value,
"champ_#{type_de_champ_repetition.to_typed_id_for_query}" => [ "champ_#{type_de_champ_repetition.to_typed_id_for_query}" => [
{ {
"champ_#{sub_type_de_champs_repetition.first.to_typed_id_for_query}": text_repetition_value, "champ_#{sub_type_de_champs_repetition.first.to_typed_id_for_query}": text_repetition_value,
@ -52,6 +56,12 @@ describe 'Prefilling a dossier (with a GET request):' do
allow(Rails).to receive(:cache).and_return(memory_store) allow(Rails).to receive(:cache).and_return(memory_store)
Rails.cache.clear Rails.cache.clear
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\//)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siret_value[0..8]}/)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
VCR.insert_cassette('api_geo_departements') VCR.insert_cassette('api_geo_departements')
VCR.insert_cassette('api_geo_communes') VCR.insert_cassette('api_geo_communes')
VCR.insert_cassette('api_geo_epcis') VCR.insert_cassette('api_geo_epcis')

View file

@ -1,4 +1,4 @@
describe 'Prefilling a dossier (with a POST request):' do describe 'Prefilling a dossier (with a POST request):', js: true do
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) } let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
let(:password) { 'my-s3cure-p4ssword' } let(:password) { 'my-s3cure-p4ssword' }
@ -8,13 +8,16 @@ describe 'Prefilling a dossier (with a POST request):' do
let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) } let(:type_de_champ_text) { create(:type_de_champ_text, procedure: procedure) }
let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) } let(:type_de_champ_phone) { create(:type_de_champ_phone, procedure: procedure) }
let(:type_de_champ_siret) { create(:type_de_champ_siret, procedure: procedure) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) } let(:type_de_champ_datetime) { create(:type_de_champ_datetime, procedure: procedure) }
let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) } let(:type_de_champ_multiple_drop_down_list) { create(:type_de_champ_multiple_drop_down_list, procedure: procedure) }
let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) } let(:type_de_champ_epci) { create(:type_de_champ_epci, procedure: procedure) }
let(:type_de_champ_repetition) { create(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure) } let(:type_de_champ_repetition) { create(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure) }
let(:type_de_champ_commune) { create(:type_de_champ_communes, procedure: procedure) } let(:type_de_champ_commune) { create(:type_de_champ_communes, procedure: procedure) }
let(:text_value) { "My Neighbor Totoro is the best movie ever" } let(:text_value) { "My Neighbor Totoro is the best movie ever" }
let(:phone_value) { "invalid phone value" } let(:phone_value) { "invalid phone value" }
let(:siret_value) { '41816609600051' }
let(:datetime_value) { "2023-02-01T10:32" } let(:datetime_value) { "2023-02-01T10:32" }
let(:multiple_drop_down_list_values) { let(:multiple_drop_down_list_values) {
[ [
@ -34,6 +37,12 @@ describe 'Prefilling a dossier (with a POST request):' do
allow(Rails).to receive(:cache).and_return(memory_store) allow(Rails).to receive(:cache).and_return(memory_store)
Rails.cache.clear Rails.cache.clear
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret_value}/)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siret_value[0..8]}/)
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
VCR.insert_cassette('api_geo_departements') VCR.insert_cassette('api_geo_departements')
VCR.insert_cassette('api_geo_communes') VCR.insert_cassette('api_geo_communes')
VCR.insert_cassette('api_geo_epcis') VCR.insert_cassette('api_geo_epcis')
@ -132,6 +141,7 @@ describe 'Prefilling a dossier (with a POST request):' do
params: { params: {
"champ_#{type_de_champ_text.to_typed_id_for_query}" => text_value, "champ_#{type_de_champ_text.to_typed_id_for_query}" => text_value,
"champ_#{type_de_champ_phone.to_typed_id_for_query}" => phone_value, "champ_#{type_de_champ_phone.to_typed_id_for_query}" => phone_value,
"champ_#{type_de_champ_siret.to_typed_id_for_query}" => siret_value,
"champ_#{type_de_champ_repetition.to_typed_id_for_query}" => [ "champ_#{type_de_champ_repetition.to_typed_id_for_query}" => [
{ {
"champ_#{sub_type_de_champs_repetition.first.to_typed_id_for_query}": text_repetition_value, "champ_#{sub_type_de_champs_repetition.first.to_typed_id_for_query}": text_repetition_value,