Merge pull request #7770 from betagouv/api-entreprise-degraded-mode

API entreprise: degraded mode
This commit is contained in:
LeSim 2022-09-16 11:55:26 +02:00 committed by GitHub
commit 7636d35241
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 532 additions and 46 deletions

View file

@ -2,11 +2,28 @@
class Dsfr::CalloutComponent < ApplicationComponent class Dsfr::CalloutComponent < ApplicationComponent
renders_one :body renders_one :body
private attr_reader :title, :theme, :icon
def initialize(title:) def initialize(title:, theme: :info, icon: nil)
@title = title @title = title
@theme = theme
@icon = icon
end end
attr_reader :title def callout_class
["fr-callout", theme_class, icon]
end
private
def theme_class
case theme
when :warning
"fr-callout--brown-caramel"
when :success
"fr-callout--green-emeraude"
else
# info is default theme
end
end
end end

View file

@ -1,3 +1,3 @@
%div.fr-callout %div{ class: callout_class }
%h3.fr-callout__title= title %h3.fr-callout__title= title
%p.fr-callout__text= body %p.fr-callout__text= body

View file

@ -112,11 +112,20 @@ module Users
end end
sanitized_siret = siret_model.siret sanitized_siret = siret_model.siret
begin etablissement = begin
etablissement = APIEntrepriseService.create_etablissement(@dossier, sanitized_siret, current_user.id) APIEntrepriseService.create_etablissement(@dossier, sanitized_siret, current_user.id)
rescue APIEntreprise::API::Error::RequestFailed, APIEntreprise::API::Error::BadGateway, APIEntreprise::API::Error::TimedOut, APIEntreprise::API::Error::ServiceUnavailable, APIEntrepriseToken::TokenError rescue => error
return render_siret_error(t('errors.messages.siret_network_error')) if error.try(:network_error?) && !APIEntrepriseService.api_up?
end # TODO: notify ops
APIEntrepriseService.create_etablissement_as_degraded_mode(@dossier, sanitized_siret, current_user.id)
else
Sentry.capture_exception(error, extra: { dossier_id: @dossier.id, siret: })
# probably random error, invite user to retry
return render_siret_error(t('errors.messages.siret_network_error'))
end
end
if etablissement.nil? if etablissement.nil?
return render_siret_error(t('errors.messages.siret_unknown')) return render_siret_error(t('errors.messages.siret_unknown'))
end end

View file

@ -90,10 +90,10 @@ module DossierHelper
l(dossier.expiration_date, format: '%d/%m/%Y') l(dossier.expiration_date, format: '%d/%m/%Y')
end end
def annuaire_link(siren = nil) def annuaire_link(siren_or_siret = nil)
base_url = "https://annuaire-entreprises.data.gouv.fr" base_url = "https://annuaire-entreprises.data.gouv.fr"
return base_url if siren.blank? return base_url if siren_or_siret.blank?
"#{base_url}/entreprise/#{siren}" "#{base_url}/rechercher?terme=#{siren_or_siret}"
end end
def exports_list(exports, statut = nil) def exports_list(exports, statut = nil)

View file

@ -1,4 +1,5 @@
@import '@gouvfr/dsfr/dist/core/core.css'; @import '@gouvfr/dsfr/dist/core/core.css';
@import '@gouvfr/dsfr/dist/utility/utility.css';
@import '@gouvfr/dsfr/dist/component/link/link.css'; @import '@gouvfr/dsfr/dist/component/link/link.css';
@import '@gouvfr/dsfr/dist/component/logo/logo.css'; @import '@gouvfr/dsfr/dist/component/logo/logo.css';
@import '@gouvfr/dsfr/dist/component/form/form.css'; @import '@gouvfr/dsfr/dist/component/form/form.css';

View file

@ -72,6 +72,13 @@ class APIEntreprise::API
call(url) call(url)
end end
def current_status
status_url = "https://entreprise.api.gouv.fr/watchdoge/dashboard/current_status"
response = Typhoeus.get(status_url, timeout: 1)
handle_response(response)
end
private private
def call_with_siret(resource_name, siret_or_siren, user_id: nil) def call_with_siret(resource_name, siret_or_siren, user_id: nil)

View file

@ -15,4 +15,8 @@ class APIEntreprise::API::Error < ::StandardError
super(msg) super(msg)
end end
def network_error?
true
end
end end

View file

@ -1,2 +1,5 @@
class APIEntreprise::API::Error::BadFormatRequest < APIEntreprise::API::Error class APIEntreprise::API::Error::BadFormatRequest < APIEntreprise::API::Error
def network_error?
false
end
end end

View file

@ -1,2 +1,5 @@
class APIEntreprise::API::Error::ResourceNotFound < APIEntreprise::API::Error class APIEntreprise::API::Error::ResourceNotFound < APIEntreprise::API::Error
def network_error?
false
end
end end

View file

@ -222,6 +222,10 @@ class Etablissement < ApplicationRecord
SpreadsheetArchitect.send("to_#{format}".to_sym, bilans_bdf_data) SpreadsheetArchitect.send("to_#{format}".to_sym, bilans_bdf_data)
end end
def as_degraded_mode?
adresse.nil? # TOOD: maybe dedicated column or more robust way
end
private private
def bilans_new_keys def bilans_new_keys

View file

@ -1,28 +1,62 @@
class APIEntrepriseService class APIEntrepriseService
# create etablissement with EtablissementAdapter class << self
# enqueue api_entreprise jobs to retrieve # create etablissement with EtablissementAdapter
# all informations we can get about a SIRET. # enqueue api_entreprise jobs to retrieve
# # all informations we can get about a SIRET.
# Returns nil if the SIRET is unknown #
# # Returns nil if the SIRET is unknown
# Raises a APIEntreprise::API::Error::RequestFailed exception on transient errors #
# (timeout, 5XX HTTP error code, etc.) # Raises a APIEntreprise::API::Error::RequestFailed exception on transient errors
def self.create_etablissement(dossier_or_champ, siret, user_id = nil) # (timeout, 5XX HTTP error code, etc.)
etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, dossier_or_champ.procedure.id).to_params #
return nil if etablissement_params.empty? def create_etablissement(dossier_or_champ, siret, user_id = nil)
procedure_id = dossier_or_champ.procedure.id
etablissement = dossier_or_champ.build_etablissement(etablissement_params) etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params
etablissement.save! return nil if etablissement_params.empty?
[ etablissement = dossier_or_champ.build_etablissement(etablissement_params)
APIEntreprise::EntrepriseJob, APIEntreprise::AssociationJob, APIEntreprise::ExercicesJob, etablissement.save!
APIEntreprise::EffectifsJob, APIEntreprise::EffectifsAnnuelsJob, APIEntreprise::AttestationSocialeJob,
APIEntreprise::BilansBdfJob perform_later_fetch_jobs(etablissement, procedure_id, user_id)
].each do |job|
job.perform_later(etablissement.id, dossier_or_champ.procedure.id) etablissement
end end
APIEntreprise::AttestationFiscaleJob.perform_later(etablissement.id, dossier_or_champ.procedure.id, user_id)
etablissement def create_etablissement_as_degraded_mode(dossier_or_champ, siret, user_id = nil)
etablissement = dossier_or_champ.build_etablissement(siret: siret)
etablissement.save!
procedure_id = dossier_or_champ.procedure.id
perform_later_fetch_jobs(etablissement, procedure_id, user_id, wait: 30.minutes)
etablissement
end
def perform_later_fetch_jobs(etablissement, procedure_id, user_id, wait: nil)
[
APIEntreprise::EntrepriseJob, APIEntreprise::AssociationJob, APIEntreprise::ExercicesJob,
APIEntreprise::EffectifsJob, APIEntreprise::EffectifsAnnuelsJob, APIEntreprise::AttestationSocialeJob,
APIEntreprise::BilansBdfJob
].each do |job|
job.set(wait:).perform_later(etablissement.id, procedure_id)
end
APIEntreprise::AttestationFiscaleJob.set(wait:).perform_later(etablissement.id, procedure_id, user_id)
end
def api_up?(uname = "apie_2_etablissements")
statuses = APIEntreprise::API.new.current_status.fetch(:results)
# find results having uname = apie_2_etablissements
status = statuses.find { |result| result[:uname] == uname }
status.fetch(:code) == 200
rescue => e
Sentry.capture_exception(e, extra: { uname: uname })
nil
end
end end
end end

View file

@ -304,6 +304,24 @@
%p.empty-text-details Vous navez commencé aucune démarche pour linstant. %p.empty-text-details Vous navez commencé aucune démarche pour linstant.
.container .container
%h1 Dsfr::CalloutComponent
= link_to "Documentation DSFR Mis en avant (callout)", "https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/mise-en-avant", **external_link_attributes
= render Dsfr::CalloutComponent.new(title: "Information minimale") do |c|
- c.with_body do
%p Ceci est le minimum pour afficher un callout.
= render Dsfr::CalloutComponent.new(title: "Information importante ou avertissement", theme: :warning) do |c|
- c.with_body do
%p Le contenu de cette description est libre.
= render Dsfr::CalloutComponent.new(title: "Titre d'une information positive", theme: :success, icon: "fr-icon-message-2-fill") do |c|
- c.with_body do
%p
N'importe quelle icône
= link_to("du jeu d'icônes", "https://www.systeme-de-design.gouv.fr/elements-d-interface/fondamentaux-techniques/icones", **external_link_attributes)
peut être utilisée.
%h1 Dsfr::CardVerticalComponent %h1 Dsfr::CardVerticalComponent
= link_to "Documentation DSFR Carte", "https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/carte", **external_link_attributes = link_to "Documentation DSFR Carte", "https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/carte", **external_link_attributes

View file

@ -153,5 +153,5 @@
- unless local_assigns[:short_identity] - unless local_assigns[:short_identity]
%p %p
= link_to "➡ Autres informations sur lorganisme sur « annuaire-entreprises.data.gouv.fr » (ex: fiche dimmatriculation RNCS)", = link_to "➡ Autres informations sur lorganisme sur « annuaire-entreprises.data.gouv.fr » (ex: fiche dimmatriculation RNCS)",
annuaire_link(etablissement.siren), annuaire_link(etablissement.siret),
target: "_blank" target: "_blank"

View file

@ -8,7 +8,23 @@
%h1 Informations sur létablissement %h1 Informations sur létablissement
- etablissement = @dossier.etablissement - etablissement = @dossier.etablissement
- if etablissement.diffusable_commercialement == false
- if etablissement.as_degraded_mode?
= render Dsfr::CalloutComponent.new(title: "Nous n'avons pas pu vérifier votre SIRET", theme: :warning, icon: "fr-icon-feedback-fill") do |c|
- c.with_body do
%p
L'annuaire INSEE est indisponible, nous ne pouvons pas vérifier votre SIRET.
%br
%br
Veuillez vérifier par vous-même que le numéro
%strong= etablissement.siret
correspond bien à votre entreprise :
%p
= link_to annuaire_link(etablissement.siret), class: "fr-btn fr-btn--secondary", **external_link_attributes do
Vérifier dans l'annuaire des entreprises
- elsif etablissement.diffusable_commercialement == false
%p= t('warning_for_private_info', scope: 'views.shared.dossiers.identite_entreprise', etablissement: raison_sociale_or_name(etablissement)) %p= t('warning_for_private_info', scope: 'views.shared.dossiers.identite_entreprise', etablissement: raison_sociale_or_name(etablissement))
- else - else

View file

@ -31,5 +31,5 @@
%p.etablissement-exercices Les 3 derniers bilans connus de votre entreprise par la Banque de France ont été joints à votre dossier. %p.etablissement-exercices Les 3 derniers bilans connus de votre entreprise par la Banque de France ont été joints à votre dossier.
%p %p
= link_to "➡ Autres informations sur lorganisme sur « annuaire-entreprises.data.gouv.fr »", = link_to "➡ Autres informations sur lorganisme sur « annuaire-entreprises.data.gouv.fr »",
annuaire_link(etablissement.siren), annuaire_link(etablissement.siret),
target: "_blank" target: "_blank"

View file

@ -207,6 +207,7 @@ describe Users::DossiersController, type: :controller do
let(:api_etablissement_status) { 200 } let(:api_etablissement_status) { 200 }
let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') } let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
let(:token_expired) { false } let(:token_expired) { false }
let(:api_current_status_response) { nil }
before do before do
sign_in(user) sign_in(user)
@ -215,6 +216,11 @@ describe Users::DossiersController, type: :controller do
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)
if api_current_status_response
stub_request(:get, "https://entreprise.api.gouv.fr/watchdoge/dashboard/current_status")
.to_return(body: api_current_status_response)
end
end end
subject! { post :update_siret, params: { id: dossier.id, user: { siret: params_siret } } } subject! { post :update_siret, params: { id: dossier.id, user: { siret: params_siret } } }
@ -255,12 +261,25 @@ describe Users::DossiersController, type: :controller do
context 'with a valid SIRET' do context 'with a valid SIRET' do
let(:params_siret) { '418 166 096 00051' } let(:params_siret) { '418 166 096 00051' }
context 'When API-Entreprise is down' do
context 'When API-Entreprise is ponctually down' do
let(:api_etablissement_status) { 502 } let(:api_etablissement_status) { 502 }
let(:api_current_status_response) { File.read('spec/fixtures/files/api_entreprise/current_status.json') }
it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error') it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error')
end end
context 'When API-Entreprise is globally down' do
let(:api_etablissement_status) { 502 }
let(:api_current_status_response) { File.read('spec/fixtures/files/api_entreprise/current_status.json').tr('200', '502') }
it "create an etablissement only with SIRET as degraded mode" do
dossier.reload
expect(dossier.etablissement.siret).to eq(siret)
expect(dossier.etablissement).to be_as_degraded_mode
end
end
context 'when API-Entreprise doesnt know this SIRET' do context 'when API-Entreprise doesnt know this SIRET' do
let(:api_etablissement_status) { 404 } let(:api_etablissement_status) { 404 }
@ -269,6 +288,7 @@ describe Users::DossiersController, type: :controller do
context 'when default token has expired' do context 'when default token has expired' do
let(:api_etablissement_status) { 200 } let(:api_etablissement_status) { 200 }
let(:api_current_status_response) { File.read('spec/fixtures/files/api_entreprise/current_status.json') }
let(:token_expired) { true } let(:token_expired) { true }
it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error') it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error')

View file

@ -0,0 +1,265 @@
{
"results": [
{
"uname": "apie_2_etablissements",
"name": "Etablissements",
"provider": "insee",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:40.442Z",
"endpoint": "api_entreprise/v2/etablissements_restored"
},
{
"uname": "apie_2_certificats_qualibat",
"name": "Certificats Qualibat",
"provider": "qualibat",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:28.848Z",
"endpoint": "api_entreprise/v2/certificats_qualibat"
},
{
"uname": "apie_2_effectifs_annuels_acoss",
"name": "Effectifs annuels",
"provider": "acoss",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:41.415Z",
"endpoint": "api_entreprise/v2/effectifs_annuels_entreprise_acoss_covid"
},
{
"uname": "apie_2_effectifs_mensuels_entreprise_acoss",
"name": "Effectifs mensuels (entreprise)",
"provider": "acoss",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:17.437Z",
"endpoint": "api_entreprise/v2/effectifs_mensuels_entreprise_acoss_covid"
},
{
"uname": "apie_2_effectifs_mensuels_etablissement_acoss",
"name": "Effectifs mensuels (établissement)",
"provider": "acoss",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:52.412Z",
"endpoint": "api_entreprise/v2/effectifs_mensuels_etablissement_acoss_covid"
},
{
"uname": "apie_2_conventions_collectives",
"name": "Conventions Collectives",
"provider": "fabsocial",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:03.003Z",
"endpoint": "api_entreprise/v2/conventions_collectives"
},
{
"uname": "apie_2_agence_bio",
"name": "Certifications BIO",
"provider": "agencebio",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:03.042Z",
"endpoint": "api_entreprise/v2/certificats_agence_bio"
},
{
"uname": "apie_2_entreprises",
"name": "Entreprise",
"provider": "insee",
"api_version": 2,
"code": 206,
"timestamp": "2022-09-15T14:33:27.934Z",
"endpoint": "api_entreprise/v2/entreprises_restored"
},
{
"uname": "apie_2_eori",
"name": "Immatriculation EORI Douanes",
"provider": "douanes",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:33:46.047Z",
"endpoint": "api_entreprise/v2/eori_douanes"
},
{
"uname": "apie_2_attestations_fiscales_dgfip",
"name": "Attestations fiscales",
"provider": "dgfip",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:32.503Z",
"endpoint": "api_entreprise/v2/attestations_fiscales_dgfip"
},
{
"uname": "apie_2_cma_france",
"name": "Entreprises Artisanales CMA France",
"provider": "cmafrance",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:55.431Z",
"endpoint": "api_entreprise/v2/entreprises_artisanales"
},
{
"uname": "apie_2_liasses_fiscales_dgfip_complete",
"name": "Liasses fiscales (complete)",
"provider": "dgfip",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:32:55.595Z",
"endpoint": "api_entreprise/v2/liasses_fiscales_dgfip"
},
{
"uname": "apie_2_exercices_dgfip",
"name": "Exercices",
"provider": "dgfip",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:19:15.501Z",
"endpoint": "api_entreprise/v2/exercices"
},
{
"uname": "apie_2_cotisations_msa",
"name": "Cotisations MSA",
"provider": "msa",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:57.747Z",
"endpoint": "api_entreprise/v2/cotisations_msa"
},
{
"uname": "apie_2_eligibilites_cotisation_retraite_probtp",
"name": "Eligibilité cotisation retraite ProBTP",
"provider": "probtp",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:30:36.979Z",
"endpoint": "api_entreprise/v2/eligibilites_cotisation_retraite_probtp"
},
{
"uname": "apie_2_documents_associations_rna",
"name": "Documents associations",
"provider": "rna",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:57.924Z",
"endpoint": "api_entreprise/v2/documents_associations"
},
{
"uname": "apie_2_cartes_professionnelles_fntp",
"name": "Cartes professionnelles FNTP",
"provider": "fntp",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:06.107Z",
"endpoint": "api_entreprise/v2/cartes_professionnelles_fntp"
},
{
"uname": "apie_2_associations_rna",
"name": "Associations",
"provider": "rna",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:33:12.993Z",
"endpoint": "api_entreprise/v2/associations"
},
{
"uname": "apie_2_attestations_agefiph",
"name": "Attestations agefiph",
"provider": "agefiph",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:32:15.345Z",
"endpoint": "api_entreprise/v2/attestations_agefiph"
},
{
"uname": "apie_2_extraits_rcs_infogreffe",
"name": "Extraits RCS (Infogreffe)",
"provider": "infogreffe",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:33:48.762Z",
"endpoint": "api_entreprise/v2/extraits_rcs_infogreffe"
},
{
"uname": "apie_2_liasses_fiscales_dgfip_dictionnaire",
"name": "Liasses fiscales (dictionnaire)",
"provider": "dgfip",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:31:36.557Z",
"endpoint": "api_entreprise/v2/liasses_fiscales_dgfip"
},
{
"uname": "apie_2_certificats_cnetp",
"name": "Certificats CNETP",
"provider": "cnetp",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:32:23.801Z",
"endpoint": "api_entreprise/v2/certificats_cnetp"
},
{
"uname": "apie_2_certificats_opqibi",
"name": "Certificats OPQIBI",
"provider": "opqibi",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:03.725Z",
"endpoint": "api_entreprise/v2/certificats_opqibi"
},
{
"uname": "apie_2_certificats_rge_ademe",
"name": "Certificats RGE ADEME",
"provider": "ademe",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:04.174Z",
"endpoint": "api_entreprise/v2/certificats_rge_ademe"
},
{
"uname": "apie_2_liasses_fiscales_dgfip_declaration",
"name": "Liasses fiscales (déclaration)",
"provider": "dgfip",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:03.654Z",
"endpoint": "api_entreprise/v2/liasses_fiscales_dgfip"
},
{
"uname": "apie_2_extraits_courts_inpi",
"name": "Extraits courts INPI",
"provider": "inpi",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:04.660Z",
"endpoint": "api_entreprise/v2/extraits_courts_inpi"
},
{
"uname": "apie_2_actes_inpi",
"name": "Actes INPI",
"provider": "inpi",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:04.263Z",
"endpoint": "api_entreprise/v2/documents_inpi"
},
{
"uname": "apie_2_bilans_inpi",
"name": "Bilans INPI",
"provider": "inpi",
"api_version": 2,
"code": 200,
"timestamp": "2022-09-15T14:00:04.446Z",
"endpoint": "api_entreprise/v2/documents_inpi"
},
{
"uname": "apie_2_bilans_entreprises_bdf",
"name": "Bilans Entreprises Banque de France",
"provider": "bdf",
"api_version": 2,
"code": 404,
"timestamp": "2022-09-15T14:00:07.312Z",
"endpoint": "api_entreprise/v2/bilans_entreprises_bdf"
}
]
}

View file

@ -289,4 +289,18 @@ describe APIEntreprise::API do
expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/) expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
end end
end end
describe 'current_status' do
subject { described_class.new.current_status }
let(:body) { File.read('spec/fixtures/files/api_entreprise/current_status.json') }
before do
stub_request(:get, "https://entreprise.api.gouv.fr/watchdoge/dashboard/current_status")
.to_return(body: body)
end
it "returns the current status response" do
expect(subject).to eq(JSON.parse(body, symbolize_names: true))
end
end
end end

View file

@ -1,4 +1,16 @@
describe APIEntrepriseService do describe APIEntrepriseService do
shared_examples 'schedule fetch of all etablissement params' do
[
APIEntreprise::EntrepriseJob, APIEntreprise::AssociationJob, APIEntreprise::ExercicesJob,
APIEntreprise::EffectifsJob, APIEntreprise::EffectifsAnnuelsJob, APIEntreprise::AttestationSocialeJob,
APIEntreprise::BilansBdfJob
].each do |job|
it "should enqueue #{job.class.name}" do
expect { subject }.to have_enqueued_job(job)
end
end
end
describe '#create_etablissement' do describe '#create_etablissement' 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}/)
@ -23,15 +35,7 @@ describe APIEntrepriseService do
expect(subject[:siret]).to eq(siret) expect(subject[:siret]).to eq(siret)
end end
[ it_behaves_like 'schedule fetch of all etablissement params'
APIEntreprise::EntrepriseJob, APIEntreprise::AssociationJob, APIEntreprise::ExercicesJob,
APIEntreprise::EffectifsJob, APIEntreprise::EffectifsAnnuelsJob, APIEntreprise::AttestationSocialeJob,
APIEntreprise::BilansBdfJob
].each do |job|
it "should enqueue #{job.class.name}" do
expect { subject }.to have_enqueued_job(job)
end
end
end end
context 'when etablissement api down' do context 'when etablissement api down' do
@ -52,4 +56,62 @@ describe APIEntrepriseService do
end end
end end
end end
describe '#create_etablissement_as_degraded_mode' do
let(:siret) { '41816609600051' }
let(:procedure) { create(:procedure) }
let(:dossier) { create(:dossier, procedure: procedure) }
let(:user_id) { 12 }
subject(:etablissement) { APIEntrepriseService.create_etablissement_as_degraded_mode(dossier, siret, user_id) }
it 'should create an etablissement with minimumal attributes' do
etablissement = subject
expect(etablissement.siret).to eq(siret)
expect(etablissement).to be_as_degraded_mode
end
it_behaves_like 'schedule fetch of all etablissement params'
end
describe "#api_up?" do
subject { described_class.api_up? }
let(:body) { File.read('spec/fixtures/files/api_entreprise/current_status.json') }
let(:status) { 200 }
before do
stub_request(:get, "https://entreprise.api.gouv.fr/watchdoge/dashboard/current_status")
.to_return(body: body, status: status)
end
it "returns true when api etablissement is up" do
expect(subject).to be_truthy
end
context "when api entreprise is down" do
let(:body) do
original_body = super()
json = JSON.parse(original_body)
# API etablissements is the first listed
json["results"][0]["code"] = 502
JSON.generate(json)
end
it "returns false" do
expect(subject).to be_falsy
end
end
context "when api entreprise status is unknown" do
let(:body) { "" }
let(:status) { 0 }
it "returns nil" do
expect(subject).to be_nil
end
end
end
end end

View file

@ -27,4 +27,13 @@ describe 'users/dossiers/etablissement.html.haml', type: :view do
it 'prépare le footer' do it 'prépare le footer' do
expect(footer).to have_selector('footer') expect(footer).to have_selector('footer')
end end
context 'etablissement as degraded mode' do
let(:etablissement) { Etablissement.create!(siret: '41816609600051') }
it "affiche une notice avec un lien de vérification vers l'annuaire" do
expect(rendered).to have_text(etablissement.siret)
expect(rendered).to have_link("Vérifier dans l'annuaire des entreprises", href: "https://annuaire-entreprises\.data\.gouv\.fr/rechercher?terme=#{etablissement.siret}")
end
end
end end