diff --git a/app/components/dsfr/callout_component.rb b/app/components/dsfr/callout_component.rb index 43f015174..0f5eb9af8 100644 --- a/app/components/dsfr/callout_component.rb +++ b/app/components/dsfr/callout_component.rb @@ -2,11 +2,28 @@ class Dsfr::CalloutComponent < ApplicationComponent renders_one :body - private + attr_reader :title, :theme, :icon - def initialize(title:) + def initialize(title:, theme: :info, icon: nil) @title = title + @theme = theme + @icon = icon 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 diff --git a/app/components/dsfr/callout_component/callout_component.html.haml b/app/components/dsfr/callout_component/callout_component.html.haml index 83c986ce3..5b48a61de 100644 --- a/app/components/dsfr/callout_component/callout_component.html.haml +++ b/app/components/dsfr/callout_component/callout_component.html.haml @@ -1,3 +1,3 @@ -%div.fr-callout +%div{ class: callout_class } %h3.fr-callout__title= title %p.fr-callout__text= body diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index dbc6a0611..d8b7392d2 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -112,11 +112,20 @@ module Users end sanitized_siret = siret_model.siret - begin - etablissement = 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 - return render_siret_error(t('errors.messages.siret_network_error')) - end + etablissement = begin + APIEntrepriseService.create_etablissement(@dossier, sanitized_siret, current_user.id) + rescue => error + if error.try(:network_error?) && !APIEntrepriseService.api_up? + # 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? return render_siret_error(t('errors.messages.siret_unknown')) end diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb index 3de889329..61496b0cf 100644 --- a/app/helpers/dossier_helper.rb +++ b/app/helpers/dossier_helper.rb @@ -90,10 +90,10 @@ module DossierHelper l(dossier.expiration_date, format: '%d/%m/%Y') end - def annuaire_link(siren = nil) + def annuaire_link(siren_or_siret = nil) base_url = "https://annuaire-entreprises.data.gouv.fr" - return base_url if siren.blank? - "#{base_url}/entreprise/#{siren}" + return base_url if siren_or_siret.blank? + "#{base_url}/rechercher?terme=#{siren_or_siret}" end def exports_list(exports, statut = nil) diff --git a/app/javascript/entrypoints/main.css b/app/javascript/entrypoints/main.css index 218b14d5f..f84c191f7 100644 --- a/app/javascript/entrypoints/main.css +++ b/app/javascript/entrypoints/main.css @@ -1,4 +1,5 @@ @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/logo/logo.css'; @import '@gouvfr/dsfr/dist/component/form/form.css'; diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index 4588ea4ab..20b07099e 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -72,6 +72,13 @@ class APIEntreprise::API call(url) 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 def call_with_siret(resource_name, siret_or_siren, user_id: nil) diff --git a/app/lib/api_entreprise/api/error.rb b/app/lib/api_entreprise/api/error.rb index f0aa3de7d..7a37417f5 100644 --- a/app/lib/api_entreprise/api/error.rb +++ b/app/lib/api_entreprise/api/error.rb @@ -15,4 +15,8 @@ class APIEntreprise::API::Error < ::StandardError super(msg) end + + def network_error? + true + end end diff --git a/app/lib/api_entreprise/api/error/bad_format_request.rb b/app/lib/api_entreprise/api/error/bad_format_request.rb index 52cf8e517..147718e0e 100644 --- a/app/lib/api_entreprise/api/error/bad_format_request.rb +++ b/app/lib/api_entreprise/api/error/bad_format_request.rb @@ -1,2 +1,5 @@ class APIEntreprise::API::Error::BadFormatRequest < APIEntreprise::API::Error + def network_error? + false + end end diff --git a/app/lib/api_entreprise/api/error/resource_not_found.rb b/app/lib/api_entreprise/api/error/resource_not_found.rb index 4fc38f86e..f6cb118f7 100644 --- a/app/lib/api_entreprise/api/error/resource_not_found.rb +++ b/app/lib/api_entreprise/api/error/resource_not_found.rb @@ -1,2 +1,5 @@ class APIEntreprise::API::Error::ResourceNotFound < APIEntreprise::API::Error + def network_error? + false + end end diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index 8082085bf..fb6c6fc4d 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -222,6 +222,10 @@ class Etablissement < ApplicationRecord SpreadsheetArchitect.send("to_#{format}".to_sym, bilans_bdf_data) end + def as_degraded_mode? + adresse.nil? # TOOD: maybe dedicated column or more robust way + end + private def bilans_new_keys diff --git a/app/services/api_entreprise_service.rb b/app/services/api_entreprise_service.rb index bc27431d1..ac363cb49 100644 --- a/app/services/api_entreprise_service.rb +++ b/app/services/api_entreprise_service.rb @@ -1,28 +1,62 @@ class APIEntrepriseService - # create etablissement with EtablissementAdapter - # enqueue api_entreprise jobs to retrieve - # all informations we can get about a SIRET. - # - # Returns nil if the SIRET is unknown - # - # Raises a APIEntreprise::API::Error::RequestFailed exception on transient errors - # (timeout, 5XX HTTP error code, etc.) - def self.create_etablissement(dossier_or_champ, siret, user_id = nil) - etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, dossier_or_champ.procedure.id).to_params - return nil if etablissement_params.empty? + class << self + # create etablissement with EtablissementAdapter + # enqueue api_entreprise jobs to retrieve + # all informations we can get about a SIRET. + # + # Returns nil if the SIRET is unknown + # + # Raises a APIEntreprise::API::Error::RequestFailed exception on transient errors + # (timeout, 5XX HTTP error code, etc.) + # + 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.save! + etablissement_params = APIEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params + return nil if etablissement_params.empty? - [ - APIEntreprise::EntrepriseJob, APIEntreprise::AssociationJob, APIEntreprise::ExercicesJob, - APIEntreprise::EffectifsJob, APIEntreprise::EffectifsAnnuelsJob, APIEntreprise::AttestationSocialeJob, - APIEntreprise::BilansBdfJob - ].each do |job| - job.perform_later(etablissement.id, dossier_or_champ.procedure.id) + etablissement = dossier_or_champ.build_etablissement(etablissement_params) + etablissement.save! + + perform_later_fetch_jobs(etablissement, procedure_id, user_id) + + etablissement 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 diff --git a/app/views/root/patron.html.haml b/app/views/root/patron.html.haml index 907ba3118..823857395 100644 --- a/app/views/root/patron.html.haml +++ b/app/views/root/patron.html.haml @@ -304,6 +304,24 @@ %p.empty-text-details Vous n’avez commencé aucune démarche pour l’instant. .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 = link_to "Documentation DSFR Carte", "https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/carte", **external_link_attributes diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 2ce7df007..20e804c52 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -153,5 +153,5 @@ - unless local_assigns[:short_identity] %p = link_to "➡ Autres informations sur l’organisme sur « annuaire-entreprises.data.gouv.fr » (ex: fiche d’immatriculation RNCS)", - annuaire_link(etablissement.siren), + annuaire_link(etablissement.siret), target: "_blank" diff --git a/app/views/users/dossiers/etablissement.html.haml b/app/views/users/dossiers/etablissement.html.haml index 6fca32e50..bbedeb3d2 100644 --- a/app/views/users/dossiers/etablissement.html.haml +++ b/app/views/users/dossiers/etablissement.html.haml @@ -8,7 +8,23 @@ %h1 Informations sur l’établissement - 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)) - else diff --git a/app/views/users/dossiers/etablissement/_infos_entreprise.html.haml b/app/views/users/dossiers/etablissement/_infos_entreprise.html.haml index fc9458f5f..0fce019c6 100644 --- a/app/views/users/dossiers/etablissement/_infos_entreprise.html.haml +++ b/app/views/users/dossiers/etablissement/_infos_entreprise.html.haml @@ -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 = link_to "➡ Autres informations sur l’organisme sur « annuaire-entreprises.data.gouv.fr »", - annuaire_link(etablissement.siren), + annuaire_link(etablissement.siret), target: "_blank" diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 33c4d699e..ab2ffac25 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -207,6 +207,7 @@ describe Users::DossiersController, type: :controller do let(:api_etablissement_status) { 200 } let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') } let(:token_expired) { false } + let(:api_current_status_response) { nil } before do sign_in(user) @@ -215,6 +216,11 @@ describe Users::DossiersController, type: :controller do 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) + + 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 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 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_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') 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 doesn’t know this SIRET' do let(:api_etablissement_status) { 404 } @@ -269,6 +288,7 @@ describe Users::DossiersController, type: :controller do context 'when default token has expired' do let(:api_etablissement_status) { 200 } + let(:api_current_status_response) { File.read('spec/fixtures/files/api_entreprise/current_status.json') } let(:token_expired) { true } it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_network_error') diff --git a/spec/fixtures/files/api_entreprise/current_status.json b/spec/fixtures/files/api_entreprise/current_status.json new file mode 100644 index 000000000..8271a9d6b --- /dev/null +++ b/spec/fixtures/files/api_entreprise/current_status.json @@ -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" + } + ] +} diff --git a/spec/lib/api_entreprise/api_spec.rb b/spec/lib/api_entreprise/api_spec.rb index 6aba1818b..5eb3f5647 100644 --- a/spec/lib/api_entreprise/api_spec.rb +++ b/spec/lib/api_entreprise/api_spec.rb @@ -289,4 +289,18 @@ describe APIEntreprise::API do expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/) 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 diff --git a/spec/services/api_entreprise_service_spec.rb b/spec/services/api_entreprise_service_spec.rb index ba3d117af..93ec39539 100644 --- a/spec/services/api_entreprise_service_spec.rb +++ b/spec/services/api_entreprise_service_spec.rb @@ -1,4 +1,16 @@ 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 before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/) @@ -23,15 +35,7 @@ describe APIEntrepriseService do expect(subject[:siret]).to eq(siret) end - [ - 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 + it_behaves_like 'schedule fetch of all etablissement params' end context 'when etablissement api down' do @@ -52,4 +56,62 @@ describe APIEntrepriseService do 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 diff --git a/spec/views/users/dossiers/etablissement.html.haml_spec.rb b/spec/views/users/dossiers/etablissement.html.haml_spec.rb index 8457012d7..d5302bc96 100644 --- a/spec/views/users/dossiers/etablissement.html.haml_spec.rb +++ b/spec/views/users/dossiers/etablissement.html.haml_spec.rb @@ -27,4 +27,13 @@ describe 'users/dossiers/etablissement.html.haml', type: :view do it 'prépare le footer' do expect(footer).to have_selector('footer') 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