diff --git a/app/components/dsfr/input_component.rb b/app/components/dsfr/input_component.rb index feb1a40c2..39ddd0020 100644 --- a/app/components/dsfr/input_component.rb +++ b/app/components/dsfr/input_component.rb @@ -6,6 +6,8 @@ class Dsfr::InputComponent < ApplicationComponent delegate :object, to: :@form delegate :errors, to: :object + attr_reader :attribute + # use it to indicate detailed about the inputs, ex: https://www.systeme-de-design.gouv.fr/elements-d-interface/modeles-et-blocs-fonctionnels/demande-de-mot-de-passe # it uses aria-describedby on input and link it to yielded content renders_one :describedby diff --git a/app/components/dsfr/input_errorable.rb b/app/components/dsfr/input_errorable.rb index 2da8dee85..91fcfcde2 100644 --- a/app/components/dsfr/input_errorable.rb +++ b/app/components/dsfr/input_errorable.rb @@ -23,7 +23,7 @@ module Dsfr { "#{dsfr_group_classname}--error" => errors_on_attribute?, - "#{dsfr_group_classname}--valid" => !errors_on_attribute? && errors_on_another_attribute? + "#{dsfr_group_classname}--valid" => !errors_on_attribute? && errors_on_another_attribute? && object.public_send(attribute).present? } end @@ -51,9 +51,9 @@ module Dsfr def attribute_or_rich_body case @input_type when :rich_text_area - @attribute.to_s.sub(/\Arich_/, '').to_sym + attribute.to_s.sub(/\Arich_/, '').to_sym else - @attribute + attribute end end diff --git a/app/components/editable_champ/champ_label_component.rb b/app/components/editable_champ/champ_label_component.rb index fac9e4c28..3143ad276 100644 --- a/app/components/editable_champ/champ_label_component.rb +++ b/app/components/editable_champ/champ_label_component.rb @@ -3,6 +3,8 @@ class EditableChamp::ChampLabelComponent < ApplicationComponent include Dsfr::InputErrorable + attr_reader :attribute + def initialize(form:, champ:, seen_at: nil) @form, @champ, @seen_at = form, champ, seen_at @attribute = :value diff --git a/app/components/editable_champ/champ_label_content_component.rb b/app/components/editable_champ/champ_label_content_component.rb index d373b240f..94978c7b0 100644 --- a/app/components/editable_champ/champ_label_content_component.rb +++ b/app/components/editable_champ/champ_label_content_component.rb @@ -4,6 +4,8 @@ class EditableChamp::ChampLabelContentComponent < ApplicationComponent include ApplicationHelper include Dsfr::InputErrorable + attr_reader :attribute + def initialize(form:, champ:, seen_at: nil) @form, @champ, @seen_at = form, champ, seen_at @attribute = :value diff --git a/app/components/editable_champ/editable_champ_base_component.rb b/app/components/editable_champ/editable_champ_base_component.rb index 9d74d9698..5acb853c1 100644 --- a/app/components/editable_champ/editable_champ_base_component.rb +++ b/app/components/editable_champ/editable_champ_base_component.rb @@ -3,6 +3,13 @@ class EditableChamp::EditableChampBaseComponent < ApplicationComponent include Dsfr::InputErrorable + attr_reader :attribute + + def initialize(form:, champ:, seen_at: nil, opts: {}) + @form, @champ, @seen_at, @opts = form, champ, seen_at, opts + @attribute = :value + end + def dsfr_champ_container :div end @@ -14,9 +21,4 @@ class EditableChamp::EditableChampBaseComponent < ApplicationComponent def describedby_id @champ.describedby_id end - - def initialize(form:, champ:, seen_at: nil, opts: {}) - @form, @champ, @seen_at, @opts = form, champ, seen_at, opts - @attribute = :value - end end diff --git a/app/controllers/administrateurs/services_controller.rb b/app/controllers/administrateurs/services_controller.rb index 6ca2af356..7fc329efd 100644 --- a/app/controllers/administrateurs/services_controller.rb +++ b/app/controllers/administrateurs/services_controller.rb @@ -12,6 +12,12 @@ module Administrateurs def new @procedure = procedure @service = Service.new + + siret = current_administrateur.instructeur.last_agent_connect_information&.siret + if siret + @service.siret = siret + @prefilled = handle_siret_prefill + end end def create @@ -52,6 +58,19 @@ module Administrateurs end end + def prefill + @procedure = procedure + @service = Service.new(siret: params[:siret]) + + prefilled = handle_siret_prefill + + render turbo_stream: turbo_stream.replace( + "service_form", + partial: "administrateurs/services/form", + locals: { service: @service, prefilled:, procedure: @procedure } + ) + end + def add_to_procedure procedure = current_administrateur.procedures.find(procedure_params[:id]) service = services.find(procedure_params[:service_id]) @@ -108,5 +127,28 @@ module Administrateurs def procedure current_administrateur.procedures.find(params[:procedure_id]) end + + def handle_siret_prefill + @service.validate + + if !@service.errors.include?(:siret) + prefilled = case @service.prefill_from_siret + in [Dry::Monads::Result::Success, Dry::Monads::Result::Success] + :success + in [Dry::Monads::Result::Failure, Dry::Monads::Result::Success] | [Dry::Monads::Result::Success, Dry::Monads::Result::Failure] + :partial + else + :failure + end + end + + # On prefill from SIRET, we only want to display errors for the SIRET input + # so we have to remove other errors (ie. required attributes not yet filled) + siret_errors = @service.errors.where(:siret) + @service.errors.clear + siret_errors.each { @service.errors.import(_1) } + + prefilled + end end end diff --git a/app/controllers/recoveries_controller.rb b/app/controllers/recoveries_controller.rb index 6a34c3e55..0d38b4d00 100644 --- a/app/controllers/recoveries_controller.rb +++ b/app/controllers/recoveries_controller.rb @@ -68,7 +68,7 @@ class RecoveriesController < ApplicationController def structure_name # we know that the structure exists because # of the ensure_collectivite_territoriale guard - APIRechercheEntreprisesService.new.(siret:).value![:nom_complet] + APIRechercheEntreprisesService.new.call(siret:).value![:nom_complet] end def ensure_agent_connect_is_used diff --git a/app/javascript/controllers/autosave_controller.ts b/app/javascript/controllers/autosave_controller.ts index 0a3cc0570..96aca094d 100644 --- a/app/javascript/controllers/autosave_controller.ts +++ b/app/javascript/controllers/autosave_controller.ts @@ -252,7 +252,10 @@ export class AutosaveController extends ApplicationController { return httpRequest(form.action, { method: 'post', body: formData, - headers: { 'x-http-method-override': 'PATCH' }, + headers: { + 'x-http-method-override': + form.dataset.turboMethod?.toUpperCase() || 'PATCH' + }, signal: this.#abortController.signal, timeout: AUTOSAVE_TIMEOUT_DELAY }).turbo(); diff --git a/app/models/concerns/prefillable_from_service_public_concern.rb b/app/models/concerns/prefillable_from_service_public_concern.rb new file mode 100644 index 000000000..bcf4f8475 --- /dev/null +++ b/app/models/concerns/prefillable_from_service_public_concern.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +module PrefillableFromServicePublicConcern + extend ActiveSupport::Concern + + included do + def prefill_from_siret + future_sp = Concurrent::Future.execute { AnnuaireServicePublicService.new.call(siret:) } + future_api_ent = Concurrent::Future.execute { APIRechercheEntreprisesService.new.call(siret:) } + + result_sp = future_sp.value! + result_api_ent = future_api_ent.value! + + prefill_from_service_public(result_sp) + prefill_from_api_entreprise(result_api_ent) + + [result_sp, result_api_ent] + end + + private + + def prefill_from_service_public(result) + case result + in Dry::Monads::Success(data) + self.nom = data[:nom] if nom.blank? + self.email = data[:adresse_courriel] if email.blank? + self.telephone = data[:telephone]&.first&.dig("valeur") if telephone.blank? + self.horaires = denormalize_plage_ouverture(data[:plage_ouverture]) if horaires.blank? + self.adresse = APIGeoService.inline_service_public_address(data[:adresse]&.first) if adresse.blank? + else + # NOOP + end + end + + def prefill_from_api_entreprise(result) + case result + in Dry::Monads::Success(data) + self.type_organisme = detect_type_organisme(data) if type_organisme.blank? + self.nom = data[:nom_complet] if nom.blank? + self.adresse = data.dig(:siege, :geo_adresse) if adresse.blank? + else + # NOOP + end + end + + def denormalize_plage_ouverture(data) + return if data.blank? + + data.map do |range| + day_range = range.values_at('nom_jour_debut', 'nom_jour_fin').uniq.join(' au ') + + hours_range = (1..2).each_with_object([]) do |i, hours| + start_hour = range["valeur_heure_debut_#{i}"] + end_hour = range["valeur_heure_fin_#{i}"] + + if start_hour.present? && end_hour.present? + hours << "de #{format_time(start_hour)} à #{format_time(end_hour)}" + end + end + + result = day_range + result += " : #{hours_range.join(' et ')}" if hours_range.present? + result += " (#{range['commentaire']})" if range['commentaire'].present? + result + end.join("\n") + end + + def detect_type_organisme(data) + # Cf https://recherche-entreprises.api.gouv.fr/docs/#tag/Recherche-textuelle/paths/~1search/get + type = if data.dig(:complements, :collectivite_territoriale).present? + :collectivite_territoriale + elsif data.dig(:complements, :est_association) + :association + elsif data[:section_activite_principale] == "P" + :etablissement_enseignement + elsif data[:nom_complet].match?(/MINISTERE|MINISTERIEL/) + :administration_centrale + else # we can't differentiate between operateur d'état, administration centrale and service déconcentré de l'état, set the most frequent + :service_deconcentre_de_l_etat + end + + Service.type_organismes[type] + end + + def format_time(str_time) + Time.zone + .parse(str_time) + .strftime("%-H:%M") + end + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 67d6ac761..487bc15af 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Service < ApplicationRecord + include PrefillableFromServicePublicConcern + has_many :procedures belongs_to :administrateur, optional: false diff --git a/app/schemas/service-public.json b/app/schemas/service-public.json new file mode 100644 index 000000000..f5ceb71c5 --- /dev/null +++ b/app/schemas/service-public.json @@ -0,0 +1,76 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://demarches-simplifiees.fr/service-public.schema.json", + "title": "Service Public", + "type": "object", + "properties": { + "total_count": { + "type": "integer" + }, + "results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "plage_ouverture": { "type": ["string", "null"] }, + "site_internet": { "type": ["string", "null"] }, + "copyright": { "type": ["string", "null"] }, + "siren": { "type": ["string", "null"] }, + "ancien_code_pivot": { "type": ["string", "null"] }, + "reseau_social": { "type": ["string", "null"] }, + "texte_reference": { "type": ["string", "null"] }, + "partenaire": { "type": ["string", "null"] }, + "telecopie": { "type": ["string", "null"] }, + "nom": { "type": "string" }, + "siret": { "type": ["string", "null"] }, + "itm_identifiant": { "type": ["string", "null"] }, + "sigle": { "type": ["string", "null"] }, + "affectation_personne": { "type": ["string", "null"] }, + "date_modification": { "type": "string" }, + "adresse_courriel": { "type": ["string", "null"] }, + "service_disponible": { "type": ["string", "null"] }, + "organigramme": { "type": ["string", "null"] }, + "pivot": { "type": ["string", "null"] }, + "partenaire_identifiant": { "type": ["string", "null"] }, + "ancien_identifiant": { "type": ["string", "null"] }, + "id": { "type": "string" }, + "ancien_nom": { "type": ["string", "null"] }, + "commentaire_plage_ouverture": { "type": ["string", "null"] }, + "annuaire": { "type": ["string", "null"] }, + "tchat": { "type": ["string", "null"] }, + "hierarchie": { "type": ["string", "null"] }, + "categorie": { "type": "string" }, + "sve": { "type": ["string", "null"] }, + "telephone_accessible": { "type": ["string", "null"] }, + "application_mobile": { "type": ["string", "null"] }, + "version_type": { "type": "string" }, + "type_repertoire": { "type": ["string", "null"] }, + "telephone": { "type": ["string", "null"] }, + "version_etat_modification": { "type": ["string", "null"] }, + "date_creation": { "type": "string" }, + "partenaire_date_modification": { "type": ["string", "null"] }, + "mission": { "type": ["string", "null"] }, + "formulaire_contact": { "type": ["string", "null"] }, + "version_source": { "type": ["string", "null"] }, + "type_organisme": { "type": ["string", "null"] }, + "code_insee_commune": { "type": ["string", "null"] }, + "statut_de_diffusion": { "type": ["string", "null"] }, + "adresse": { "type": ["string", "null"] }, + "url_service_public": { "type": ["string", "null"] }, + "information_complementaire": { "type": ["string", "null"] }, + "date_diffusion": { "type": ["string", "null"] } + }, + "required": [ + "id", + "nom", + "categorie", + "adresse", + "adresse_courriel", + "telephone", + "plage_ouverture" + ] + } + } + }, + "required": ["total_count", "results"] +} diff --git a/app/services/annuaire_service_public_service.rb b/app/services/annuaire_service_public_service.rb new file mode 100644 index 000000000..7c5728fd8 --- /dev/null +++ b/app/services/annuaire_service_public_service.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +class AnnuaireServicePublicService + include Dry::Monads[:result] + + def call(siret:) + result = API::Client.new.call(url: url(siret), schema:, timeout: 1.second) + + case result + in Success(body:) + result = body[:results].first + + if result.present? + Success( + result.slice(:nom, :adresse, :adresse_courriel).merge( + telephone: maybe_json_parse(result[:telephone]), + plage_ouverture: maybe_json_parse(result[:plage_ouverture]), + adresse: maybe_json_parse(result[:adresse]) + ) + ) + else + Failure(API::Client::Error[:not_found, 404, false, "No result found for this SIRET."]) + end + in Failure(code:, reason:) if code.in?(401..403) + Sentry.capture_message("#{self.class.name}: #{reason} code: #{code}", extra: { siret: }) + Failure(API::Client::Error[:unauthorized, code, false, reason]) + in Failure(type: :schema, code:, reason:) + reason.errors[0].first + Sentry.capture_exception(reason, extra: { siret:, code: }) + + Failure(API::Client::Error[:schema, code, false, reason]) + else + result + end + end + + private + + def schema + JSONSchemer.schema(Rails.root.join('app/schemas/service-public.json')) + end + + def url(siret) + "https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:#{siret}" + end + + def maybe_json_parse(value) + return nil if value.blank? + + JSON.parse(value) + end +end diff --git a/app/services/api_geo_service.rb b/app/services/api_geo_service.rb index c12804c2a..a6d051e36 100644 --- a/app/services/api_geo_service.rb +++ b/app/services/api_geo_service.rb @@ -263,6 +263,21 @@ class APIGeoService end end + def inline_service_public_address(address_data) + return nil if address_data.blank? + + components = [ + address_data['numero_voie'], + address_data['complement1'], + address_data['complement2'], + address_data['service_distribution'], + address_data['code_postal'], + address_data['nom_commune'] + ].compact_blank + + components.join(' ') + end + private def code_metropole?(result) diff --git a/app/views/administrateurs/services/_form.html.haml b/app/views/administrateurs/services/_form.html.haml index 9c6040508..8a463a3d7 100644 --- a/app/views/administrateurs/services/_form.html.haml +++ b/app/views/administrateurs/services/_form.html.haml @@ -1,4 +1,26 @@ -= form_with model: [ :admin, service], local: true do |f| += form_with model: [:admin, service], id: "service_form" do |f| + + = render Dsfr::InputComponent.new(form: f, attribute: :siret, input_type: :text_field, + opts: { placeholder: "14 chiffres, sans espace", + onblur: token_list("Turbo.visit('#{prefill_admin_services_path(procedure_id: procedure.id)}?siret=' + this.value)" => service.new_record?) }) do |c| + - if service.etablissement_infos.blank? && local_assigns[:prefilled].nil? + - c.with_hint do + = "Indiquez le numéro de SIRET de l’organisme dont ce service dépend. Rechercher le SIRET sur " + = link_to("annuaire-entreprises.data.gouv.fr", annuaire_link, **external_link_attributes) + - if service.new_record? + %br + = "Nous préremplirons les informations de contact à partir de l’Annuaire Service Public correspondant." + + .fr-mb-2w + - if local_assigns[:prefilled] == :success + %p.fr-info-text Génial ! La plupart des informations du service ont été préremplies ci-dessous. Vérifiez-les et complétez-les le cas échéant. + - elsif local_assigns[:prefilled] == :partial + %p.fr-info-text + Nous avons prérempli certaines informations correspondant à ce SIRET. Complétez les autres manuellement. + - elsif local_assigns[:prefilled] == :failure + %p.fr-error-text + Une erreur a empêché le préremplissage des informations. + Vérifiez que le numéro de SIRET est correct et complétez les informations manuellement le cas échéant. = render Dsfr::InputComponent.new(form: f, attribute: :nom, input_type: :text_field) @@ -7,13 +29,9 @@ .fr-input-group = f.label :type_organisme, class: "fr-label" do Type d’organisme + = render EditableChamp::AsteriskMandatoryComponent.new - = f.select :type_organisme, Service.type_organismes.keys.map { |key| [ I18n.t("type_organisme.#{key}"), key] }, {}, class: 'fr-select' - - = render Dsfr::InputComponent.new(form: f, attribute: :siret, input_type: :text_field, opts: { placeholder: "14 chiffres, sans espace" }) do |c| - - c.with_hint do - = "Indiquez le numéro de SIRET de l’organisme dont ce service dépend. Rechercher le SIRET sur " - = link_to("annuaire-entreprises.data.gouv.fr", annuaire_link, **external_link_attributes) + = f.select :type_organisme, Service.type_organismes.keys.map { |key| [ I18n.t("type_organisme.#{key}"), key] }, { include_blank: true }, { class: "fr-select" , required: true } = render Dsfr::CalloutComponent.new(title: "Informations de contact") do |c| - c.with_body do @@ -31,7 +49,6 @@ = render Dsfr::InputComponent.new(form: f, attribute: :horaires, input_type: :text_area) = render Dsfr::InputComponent.new(form: f, attribute: :adresse, input_type: :text_area) - - if procedure_id.present? - = hidden_field_tag :procedure_id, procedure_id - - = render Procedure::FixedFooterComponent.new(procedure: @procedure, form: f) + - if local_assigns[:procedure].present? + = hidden_field_tag :procedure_id, procedure.id + = render Procedure::FixedFooterComponent.new(procedure: procedure, form: f) diff --git a/app/views/administrateurs/services/edit.html.haml b/app/views/administrateurs/services/edit.html.haml index 0b056372c..3cd11f6fc 100644 --- a/app/views/administrateurs/services/edit.html.haml +++ b/app/views/administrateurs/services/edit.html.haml @@ -23,4 +23,4 @@ %p.mt-3 Si vous souhaitez modifier uniquement les informations pour ce service, créez un nouveau service puis associez-le à la démarche = render partial: 'form', - locals: { service: @service, procedure_id: @procedure.id } + locals: { service: @service, procedure: @procedure } diff --git a/app/views/administrateurs/services/new.html.haml b/app/views/administrateurs/services/new.html.haml index 691b864e7..7477ad9b2 100644 --- a/app/views/administrateurs/services/new.html.haml +++ b/app/views/administrateurs/services/new.html.haml @@ -8,4 +8,4 @@ %h1 Nouveau Service = render partial: 'form', - locals: { service: @service, procedure_id: @procedure.id } + locals: { service: @service, procedure: @procedure, prefilled: @prefilled } diff --git a/config/locales/models/service/en.yml b/config/locales/models/service/en.yml index a28cd43a5..e9da428d0 100644 --- a/config/locales/models/service/en.yml +++ b/config/locales/models/service/en.yml @@ -14,6 +14,7 @@ en: service: attributes: siret: - format: "SIRET number %{message}" - length: "must contain exactly 14 digits" - checksum: "is invalid" + format: 'SIRET number %{message}' + length: 'must contain exactly 14 digits' + checksum: 'is invalid' + not_prefillable: 'Unable to pre-fill information for this SIRET, please fill it manually' diff --git a/config/locales/models/service/fr.yml b/config/locales/models/service/fr.yml index 1abe6afdb..40c35197c 100644 --- a/config/locales/models/service/fr.yml +++ b/config/locales/models/service/fr.yml @@ -34,9 +34,10 @@ fr: service: attributes: siret: - format: "Le numéro SIRET %{message}" - length: "doit comporter exactement 14 chiffres" - checksum: "est invalide" + format: 'Le numéro SIRET %{message}' + length: 'doit comporter exactement 14 chiffres' + checksum: 'est invalide' + not_prefillable: 'Impossible de préremplir les informations pour ce SIRET, veuillez les saisir manuellement' type_organisme: administration_centrale: 'Administration centrale' association: 'Association' diff --git a/config/routes.rb b/config/routes.rb index ed06d5b7b..ceda9034e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -737,6 +737,7 @@ Rails.application.routes.draw do resources :services, except: [:show] do collection do patch 'add_to_procedure' + get ':procedure_id/prefill' => :prefill, as: :prefill end end diff --git a/spec/controllers/administrateurs/services_controller_spec.rb b/spec/controllers/administrateurs/services_controller_spec.rb index 380d23787..e8bc20c5d 100644 --- a/spec/controllers/administrateurs/services_controller_spec.rb +++ b/spec/controllers/administrateurs/services_controller_spec.rb @@ -4,12 +4,112 @@ describe Administrateurs::ServicesController, type: :controller do let(:admin) { administrateurs(:default_admin) } let(:procedure) { create(:procedure, administrateur: admin) } + describe '#new' do + let(:admin) { administrateurs(:default_admin) } + let(:procedure) { create(:procedure, administrateur: admin) } + + before do + sign_in(admin.user) + end + + subject { get :new, params: { procedure_id: procedure.id } } + + context 'when admin has a SIRET from AgentConnect' do + let(:siret) { "20004021000060" } + + before do + agi = build(:agent_connect_information, siret:) + admin.instructeur.agent_connect_information << agi + end + + it 'prefills the SIRET and fetches service information' do + VCR.use_cassette("annuaire_service_public_success_#{siret}") do + subject + expect(assigns[:service].siret).to eq(siret) + expect(assigns[:service].nom).to eq("Communauté de communes - Lacs et Gorges du Verdon") + expect(assigns[:service].adresse).to eq("242 avenue Albert-1er 83630 Aups") + expect(assigns[:prefilled]).to eq(:success) + end + end + end + + context 'when admin has no SIRET from AgentConnect' do + it 'does not prefill the SIRET' do + subject + expect(assigns[:service].siret).to be_nil + expect(assigns[:prefilled]).to be_nil + end + end + end + + describe '#prefill' do + before do + sign_in(admin.user) + end + + subject { get :prefill, params:, xhr: true } + + context 'when prefilling from a SIRET' do + let(:params) do + { + procedure_id: procedure.id, + siret: "20004021000060" + } + end + + it "prefill from annuaire public" do + VCR.use_cassette('annuaire_service_public_success_20004021000060') do + subject + expect(response.body).to include('turbo-stream') + expect(assigns[:service].nom).to eq("Communauté de communes - Lacs et Gorges du Verdon") + expect(assigns[:service].adresse).to eq("242 avenue Albert-1er 83630 Aups") + end + end + end + + context 'when attempting to prefilling from invalid SIRET' do + let(:params) do + { + procedure_id: procedure.id, + siret: "20004021000000" + } + end + + it "render an error" do + subject + expect(response.body).to include('turbo-stream') + expect(assigns[:service].nom).to be_nil + expect(assigns[:service].errors.key?(:siret)).to be_present + end + end + + context 'when attempting to prefilling from not service public SIRET' do + let(:params) do + { + procedure_id: procedure.id, + siret: "41816609600051" + } + end + + it "render partial information" do + VCR.use_cassette('annuaire_service_public_success_41816609600051') do + subject + expect(response.body).to include('turbo-stream') + expect(assigns[:service].nom).to eq("OCTO-TECHNOLOGY") + expect(assigns[:service].horaires).to be_nil + expect(assigns[:service].errors.key?(:siret)).not_to be_present + end + end + end + end + describe '#create' do before do sign_in(admin.user) - post :create, params: params end + subject { post :create, params: } + context 'when submitting a new service' do let(:params) do { @@ -28,6 +128,7 @@ describe Administrateurs::ServicesController, type: :controller do end it do + subject expect(flash.alert).to be_nil expect(flash.notice).to eq('super service créé') expect(Service.last.nom).to eq('super service') @@ -47,9 +148,12 @@ describe Administrateurs::ServicesController, type: :controller do context 'when submitting an invalid service' do let(:params) { { service: { nom: 'super service' }, procedure_id: procedure.id } } - it { expect(flash.alert).not_to be_nil } - it { expect(response).to render_template(:new) } - it { expect(assigns(:service).nom).to eq('super service') } + it do + subject + expect(flash.alert).not_to be_nil + expect(response).to render_template(:new) + expect(assigns(:service).nom).to eq('super service') + end end end diff --git a/spec/fixtures/cassettes/annuaire_service_public_failure_20004021000000.yml b/spec/fixtures/cassettes/annuaire_service_public_failure_20004021000000.yml new file mode 100644 index 000000000..f38317634 --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_failure_20004021000000.yml @@ -0,0 +1,70 @@ +--- +http_interactions: +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:20004021000000 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches.gouv.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Mon, 07 Oct 2024 14:41:59 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '33' + X-Ratelimit-Remaining: + - '999978' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-08 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 0, "results": []}' + recorded_at: Mon, 07 Oct 2024 14:41:59 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/cassettes/annuaire_service_public_success_11004601800013.yml b/spec/fixtures/cassettes/annuaire_service_public_success_11004601800013.yml new file mode 100644 index 000000000..36a6adc39 --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_success_11004601800013.yml @@ -0,0 +1,116 @@ +--- +http_interactions: +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:11004601800013 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Tue, 15 Oct 2024 16:24:17 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '33' + X-Ratelimit-Remaining: + - '999918' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-16 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 0, "results": []}' + recorded_at: Tue, 15 Oct 2024 16:24:17 GMT +- request: + method: get + uri: https://recherche-entreprises.api.gouv.fr/search?q=11004601800013 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - nginx/1.27.1 + Date: + - Tue, 15 Oct 2024 16:24:17 GMT + Content-Type: + - application/json + Content-Length: + - '3289' + Vary: + - Accept-Encoding + - Accept-Encoding + Annuaire-Entreprises-Instance-Number: + - '02' + X-Frame-Options: + - DENY + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + Access-Control-Allow-Headers: + - Content-Type + Access-Control-Allow-Origin: + - "*" + body: + encoding: ASCII-8BIT + string: !binary |- + eyJyZXN1bHRzIjpbeyJzaXJlbiI6IjExMDA0NjAxOCIsIm5vbV9jb21wbGV0IjoiTUlOSVNURVJFIERFIExBIENVTFRVUkUiLCJub21fcmFpc29uX3NvY2lhbGUiOiJNSU5JU1RFUkUgREUgTEEgQ1VMVFVSRSIsInNpZ2xlIjpudWxsLCJub21icmVfZXRhYmxpc3NlbWVudHMiOjMsIm5vbWJyZV9ldGFibGlzc2VtZW50c19vdXZlcnRzIjoxLCJzaWVnZSI6eyJhY3Rpdml0ZV9wcmluY2lwYWxlIjoiODQuMTFaIiwiYWN0aXZpdGVfcHJpbmNpcGFsZV9yZWdpc3RyZV9tZXRpZXIiOm51bGwsImFubmVlX3RyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6IjIwMjIiLCJhZHJlc3NlIjoiMTgyIFJVRSBTQUlOVC1IT05PUkUgNzUwMDEgUEFSSVMiLCJjYXJhY3RlcmVfZW1wbG95ZXVyIjoiTiIsImNlZGV4IjpudWxsLCJjb2RlX3BheXNfZXRyYW5nZXIiOm51bGwsImNvZGVfcG9zdGFsIjoiNzUwMDEiLCJjb21tdW5lIjoiNzUxMDEiLCJjb21wbGVtZW50X2FkcmVzc2UiOm51bGwsImNvb3Jkb25uZWVzIjoiNDguODYyMzk4LDIuMzM4OTAzIiwiZGF0ZV9jcmVhdGlvbiI6IjE5ODMtMDMtMDEiLCJkYXRlX2RlYnV0X2FjdGl2aXRlIjoiMjAwOC0wMS0wMSIsImRhdGVfZmVybWV0dXJlIjpudWxsLCJkYXRlX21pc2VfYV9qb3VyIjpudWxsLCJkYXRlX21pc2VfYV9qb3VyX2luc2VlIjoiMjAyNC0wMy0zMFQxMTozMDowNiIsImRlcGFydGVtZW50IjoiNzUiLCJkaXN0cmlidXRpb25fc3BlY2lhbGUiOm51bGwsImVwY2kiOiIyMDAwNTQ3ODEiLCJlc3Rfc2llZ2UiOnRydWUsImV0YXRfYWRtaW5pc3RyYXRpZiI6IkEiLCJnZW9fYWRyZXNzZSI6IjE4MiBSdWUgU2FpbnQtSG9ub3LDqSA3NTAwMSBQYXJpcyIsImdlb19pZCI6Ijc1MTAxXzg2MzVfMDAxODIiLCJpbmRpY2VfcmVwZXRpdGlvbiI6bnVsbCwibGF0aXR1ZGUiOiI0OC44NjIzOTgiLCJsaWJlbGxlX2NlZGV4IjpudWxsLCJsaWJlbGxlX2NvbW11bmUiOiJQQVJJUyIsImxpYmVsbGVfY29tbXVuZV9ldHJhbmdlciI6bnVsbCwibGliZWxsZV9wYXlzX2V0cmFuZ2VyIjpudWxsLCJsaWJlbGxlX3ZvaWUiOiJTQUlOVC1IT05PUkUiLCJsaXN0ZV9lbnNlaWduZXMiOm51bGwsImxpc3RlX2ZpbmVzcyI6bnVsbCwibGlzdGVfaWRfYmlvIjpudWxsLCJsaXN0ZV9pZGNjIjpudWxsLCJsaXN0ZV9pZF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpudWxsLCJsaXN0ZV9yZ2UiOm51bGwsImxpc3RlX3VhaSI6bnVsbCwibG9uZ2l0dWRlIjoiMi4zMzg5MDMiLCJub21fY29tbWVyY2lhbCI6bnVsbCwibnVtZXJvX3ZvaWUiOiIxODIiLCJyZWdpb24iOiIxMSIsInNpcmV0IjoiMTEwMDQ2MDE4MDAwMTMiLCJzdGF0dXRfZGlmZnVzaW9uX2V0YWJsaXNzZW1lbnQiOiJPIiwidHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjoiMjIiLCJ0eXBlX3ZvaWUiOiJSVUUifSwiYWN0aXZpdGVfcHJpbmNpcGFsZSI6Ijg0LjExWiIsImNhdGVnb3JpZV9lbnRyZXByaXNlIjoiUE1FIiwiY2FyYWN0ZXJlX2VtcGxveWV1ciI6bnVsbCwiYW5uZWVfY2F0ZWdvcmllX2VudHJlcHJpc2UiOiIyMDIyIiwiZGF0ZV9jcmVhdGlvbiI6IjE5ODEtMDYtMjMiLCJkYXRlX2Zlcm1ldHVyZSI6bnVsbCwiZGF0ZV9taXNlX2Ffam91ciI6IjIwMjQtMTAtMTRUMTQ6NTk6NDkiLCJkYXRlX21pc2VfYV9qb3VyX2luc2VlIjoiMjAyNC0wOS0yN1QxMToxMjoyOSIsImRhdGVfbWlzZV9hX2pvdXJfcm5lIjpudWxsLCJkaXJpZ2VhbnRzIjpbXSwiZXRhdF9hZG1pbmlzdHJhdGlmIjoiQSIsIm5hdHVyZV9qdXJpZGlxdWUiOiI3MTEzIiwic2VjdGlvbl9hY3Rpdml0ZV9wcmluY2lwYWxlIjoiTyIsInRyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6IjIyIiwiYW5uZWVfdHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjoiMjAyMiIsInN0YXR1dF9kaWZmdXNpb24iOiJPIiwibWF0Y2hpbmdfZXRhYmxpc3NlbWVudHMiOlt7ImFjdGl2aXRlX3ByaW5jaXBhbGUiOiI4NC4xMVoiLCJhbmNpZW5fc2llZ2UiOmZhbHNlLCJhbm5lZV90cmFuY2hlX2VmZmVjdGlmX3NhbGFyaWUiOiIyMDIyIiwiYWRyZXNzZSI6IjE4MiBSVUUgU0FJTlQtSE9OT1JFIDc1MDAxIFBBUklTIiwiY2FyYWN0ZXJlX2VtcGxveWV1ciI6Ik4iLCJjb2RlX3Bvc3RhbCI6Ijc1MDAxIiwiY29tbXVuZSI6Ijc1MTAxIiwiZGF0ZV9jcmVhdGlvbiI6IjE5ODMtMDMtMDEiLCJkYXRlX2RlYnV0X2FjdGl2aXRlIjoiMjAwOC0wMS0wMSIsImRhdGVfZmVybWV0dXJlIjpudWxsLCJlcGNpIjoiMjAwMDU0NzgxIiwiZXN0X3NpZWdlIjp0cnVlLCJldGF0X2FkbWluaXN0cmF0aWYiOiJBIiwiZ2VvX2lkIjoiNzUxMDFfODYzNV8wMDE4MiIsImxhdGl0dWRlIjoiNDguODYyMzk4IiwibGliZWxsZV9jb21tdW5lIjoiUEFSSVMiLCJsaXN0ZV9lbnNlaWduZXMiOm51bGwsImxpc3RlX2ZpbmVzcyI6bnVsbCwibGlzdGVfaWRfYmlvIjpudWxsLCJsaXN0ZV9pZGNjIjpudWxsLCJsaXN0ZV9pZF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpudWxsLCJsaXN0ZV9yZ2UiOm51bGwsImxpc3RlX3VhaSI6bnVsbCwibG9uZ2l0dWRlIjoiMi4zMzg5MDMiLCJub21fY29tbWVyY2lhbCI6bnVsbCwicmVnaW9uIjoiMTEiLCJzaXJldCI6IjExMDA0NjAxODAwMDEzIiwic3RhdHV0X2RpZmZ1c2lvbl9ldGFibGlzc2VtZW50IjoiTyIsInRyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6IjIyIn1dLCJmaW5hbmNlcyI6bnVsbCwiY29tcGxlbWVudHMiOnsiY29sbGVjdGl2aXRlX3RlcnJpdG9yaWFsZSI6bnVsbCwiY29udmVudGlvbl9jb2xsZWN0aXZlX3JlbnNlaWduZWUiOmZhbHNlLCJsaXN0ZV9pZGNjIjpudWxsLCJlZ2Fwcm9fcmVuc2VpZ25lZSI6ZmFsc2UsImVzdF9hc3NvY2lhdGlvbiI6ZmFsc2UsImVzdF9iaW8iOmZhbHNlLCJlc3RfZW50cmVwcmVuZXVyX2luZGl2aWR1ZWwiOmZhbHNlLCJlc3RfZW50cmVwcmVuZXVyX3NwZWN0YWNsZSI6ZmFsc2UsImVzdF9lc3MiOmZhbHNlLCJlc3RfZmluZXNzIjpmYWxzZSwiZXN0X29yZ2FuaXNtZV9mb3JtYXRpb24iOnRydWUsImVzdF9xdWFsaW9waSI6ZmFsc2UsImxpc3RlX2lkX29yZ2FuaXNtZV9mb3JtYXRpb24iOlsiMTE3NTU2MDg5NzUiXSwiZXN0X3JnZSI6ZmFsc2UsImVzdF9zZXJ2aWNlX3B1YmxpYyI6dHJ1ZSwiZXN0X3NpYWUiOmZhbHNlLCJlc3Rfc29jaWV0ZV9taXNzaW9uIjpmYWxzZSwiZXN0X3VhaSI6ZmFsc2UsImlkZW50aWZpYW50X2Fzc29jaWF0aW9uIjpudWxsLCJzdGF0dXRfZW50cmVwcmVuZXVyX3NwZWN0YWNsZSI6bnVsbCwidHlwZV9zaWFlIjpudWxsfX1dLCJ0b3RhbF9yZXN1bHRzIjoxLCJwYWdlIjoxLCJwZXJfcGFnZSI6MTAsInRvdGFsX3BhZ2VzIjoxfQ== + recorded_at: Tue, 15 Oct 2024 16:24:17 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/cassettes/annuaire_service_public_success_19750664500013.yml b/spec/fixtures/cassettes/annuaire_service_public_success_19750664500013.yml new file mode 100644 index 000000000..66250c90b --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_success_19750664500013.yml @@ -0,0 +1,120 @@ +--- +http_interactions: +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:19750664500013 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Tue, 15 Oct 2024 14:57:11 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '33' + X-Ratelimit-Remaining: + - '999997' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-16 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 0, "results": []}' + recorded_at: Tue, 15 Oct 2024 14:57:11 GMT +- request: + method: get + uri: https://recherche-entreprises.api.gouv.fr/search?q=19750664500013 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - nginx/1.27.1 + Date: + - Tue, 15 Oct 2024 14:57:12 GMT + Content-Type: + - application/json + Content-Length: + - '3310' + Vary: + - Accept-Encoding + - Accept-Encoding + Annuaire-Entreprises-Instance-Number: + - '02' + X-Frame-Options: + - DENY + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + Access-Control-Allow-Headers: + - Content-Type + Access-Control-Allow-Origin: + - "*" + body: + encoding: ASCII-8BIT + string: '{"results":[{"siren":"197506645","nom_complet":"LYCEE GENERAL ET TECHNOLOGIQUE + RACINE","nom_raison_sociale":"LYCEE GENERAL ET TECHNOLOGIQUE RACINE","sigle":null,"nombre_etablissements":1,"nombre_etablissements_ouverts":1,"siege":{"activite_principale":"85.31Z","activite_principale_registre_metier":null,"annee_tranche_effectif_salarie":"2022","adresse":"20 + RUE DU ROCHER 75008 PARIS","caractere_employeur":"N","cedex":null,"code_pays_etranger":null,"code_postal":"75008","commune":"75108","complement_adresse":null,"coordonnees":"48.876451,2.3223","date_creation":"1983-03-01","date_debut_activite":"2008-01-01","date_fermeture":null,"date_mise_a_jour":null,"date_mise_a_jour_insee":"2024-03-30T03:25:45","departement":"75","distribution_speciale":null,"epci":"200054781","est_siege":true,"etat_administratif":"A","geo_adresse":"20 + Rue du Rocher 75008 Paris","geo_id":"75108_8291_00020","indice_repetition":null,"latitude":"48.876451","libelle_cedex":null,"libelle_commune":"PARIS","libelle_commune_etranger":null,"libelle_pays_etranger":null,"libelle_voie":"DU + ROCHER","liste_enseignes":null,"liste_finess":null,"liste_id_bio":null,"liste_idcc":["9999"],"liste_id_organisme_formation":null,"liste_rge":null,"liste_uai":["0750664P"],"longitude":"2.3223","nom_commercial":null,"numero_voie":"20","region":"11","siret":"19750664500013","statut_diffusion_etablissement":"O","tranche_effectif_salarie":"22","type_voie":"RUE"},"activite_principale":"85.31Z","categorie_entreprise":"PME","caractere_employeur":null,"annee_categorie_entreprise":"2022","date_creation":"1965-05-01","date_fermeture":null,"date_mise_a_jour":"2024-10-14T15:00:03","date_mise_a_jour_insee":"2024-03-22T14:26:06","date_mise_a_jour_rne":null,"dirigeants":[],"etat_administratif":"A","nature_juridique":"7331","section_activite_principale":"P","tranche_effectif_salarie":"22","annee_tranche_effectif_salarie":"2022","statut_diffusion":"O","matching_etablissements":[{"activite_principale":"85.31Z","ancien_siege":false,"annee_tranche_effectif_salarie":"2022","adresse":"20 + RUE DU ROCHER 75008 PARIS","caractere_employeur":"N","code_postal":"75008","commune":"75108","date_creation":"1983-03-01","date_debut_activite":"2008-01-01","date_fermeture":null,"epci":"200054781","est_siege":true,"etat_administratif":"A","geo_id":"75108_8291_00020","latitude":"48.876451","libelle_commune":"PARIS","liste_enseignes":null,"liste_finess":null,"liste_id_bio":null,"liste_idcc":["9999"],"liste_id_organisme_formation":null,"liste_rge":null,"liste_uai":["0750664P"],"longitude":"2.3223","nom_commercial":null,"region":"11","siret":"19750664500013","statut_diffusion_etablissement":"O","tranche_effectif_salarie":"22"}],"finances":null,"complements":{"collectivite_territoriale":null,"convention_collective_renseignee":true,"liste_idcc":["9999"],"egapro_renseignee":false,"est_association":false,"est_bio":false,"est_entrepreneur_individuel":false,"est_entrepreneur_spectacle":false,"est_ess":false,"est_finess":false,"est_organisme_formation":false,"est_qualiopi":false,"liste_id_organisme_formation":null,"est_rge":false,"est_service_public":true,"est_siae":false,"est_societe_mission":false,"est_uai":true,"identifiant_association":null,"statut_entrepreneur_spectacle":null,"type_siae":null}}],"total_results":1,"page":1,"per_page":10,"total_pages":1}' + recorded_at: Tue, 15 Oct 2024 14:57:11 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/cassettes/annuaire_service_public_success_20004021000060.yml b/spec/fixtures/cassettes/annuaire_service_public_success_20004021000060.yml new file mode 100644 index 000000000..cbeeede03 --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_success_20004021000060.yml @@ -0,0 +1,146 @@ +--- +http_interactions: +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:20004021000060 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches.gouv.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Mon, 07 Oct 2024 14:41:57 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '2573' + X-Ratelimit-Remaining: + - '999979' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-08 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 1, "results": [{"plage_ouverture": "[{\"nom_jour_debut\": + \"Lundi\", \"nom_jour_fin\": \"Jeudi\", \"valeur_heure_debut_1\": \"08:00:00\", + \"valeur_heure_fin_1\": \"12:00:00\", \"valeur_heure_debut_2\": \"13:30:00\", + \"valeur_heure_fin_2\": \"17:30:00\", \"commentaire\": \"\"}, {\"nom_jour_debut\": + \"Vendredi\", \"nom_jour_fin\": \"Vendredi\", \"valeur_heure_debut_1\": \"08:00:00\", + \"valeur_heure_fin_1\": \"12:00:00\", \"valeur_heure_debut_2\": \"\", \"valeur_heure_fin_2\": + \"\", \"commentaire\": \"\"}]", "site_internet": "[{\"libelle\": \"\", \"valeur\": + \"https://www.cc-lacsgorgesverdon.fr/\"}]", "copyright": "Direction de l''information + l\u00e9gale et administrative (Premier ministre)", "siren": "200040210", "ancien_code_pivot": + "epci-83007-01", "reseau_social": null, "texte_reference": null, "partenaire": + null, "telecopie": null, "nom": "Communaut\u00e9 de communes - Lacs et Gorges + du Verdon", "siret": "20004021000060", "itm_identifiant": "999974", "sigle": + null, "affectation_personne": null, "date_modification": "31/01/2024 14:25:10", + "adresse_courriel": "redacted@email.fr", "service_disponible": null, "organigramme": + null, "pivot": "[{\"type_service_local\": \"epci\", \"code_insee_commune\": + [\"83007\"]}]", "partenaire_identifiant": null, "ancien_identifiant": null, + "id": "3b9ce22d-f7bd-46d9-82d1-8b44c8d08e39", "ancien_nom": null, "commentaire_plage_ouverture": + null, "annuaire": null, "tchat": null, "hierarchie": null, "categorie": "SL", + "sve": null, "telephone_accessible": null, "application_mobile": null, "version_type": + "Publiable", "type_repertoire": null, "telephone": "[{\"valeur\": \"04 94 + 70 00 00\", \"description\": \"\"}]", "version_etat_modification": null, "date_creation": + "11/05/2017 11:28:41", "partenaire_date_modification": null, "mission": null, + "formulaire_contact": "https://www.cc-lacsgorgesverdon.fr/contacts-comcom", + "version_source": null, "type_organisme": null, "code_insee_commune": "83007", + "statut_de_diffusion": "true", "adresse": "[{\"type_adresse\": \"Adresse\", + \"complement1\": \"\", \"complement2\": \"\", \"numero_voie\": \"242 avenue + Albert-1er\", \"service_distribution\": \"\", \"code_postal\": \"83630\", + \"nom_commune\": \"Aups\", \"pays\": \"\", \"continent\": \"\", \"longitude\": + \"6.22516\", \"latitude\": \"43.627448\", \"accessibilite\": \"ACC\", \"note_accessibilite\": + \"ascenseur\"}]", "url_service_public": "https://lannuaire.service-public.fr/provence-alpes-cote-d-azur/var/3b9ce22d-f7bd-46d9-82d1-8b44c8d08e39", + "information_complementaire": null, "date_diffusion": null}]}' + recorded_at: Mon, 07 Oct 2024 14:41:57 GMT +- request: + method: get + uri: https://recherche-entreprises.api.gouv.fr/search?q=20004021000060 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - nginx/1.27.1 + Date: + - Tue, 15 Oct 2024 13:53:25 GMT + Content-Type: + - application/json + Content-Length: + - '6715' + Vary: + - Accept-Encoding + - Accept-Encoding + Annuaire-Entreprises-Instance-Number: + - '02' + X-Frame-Options: + - DENY + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + Access-Control-Allow-Headers: + - Content-Type + Access-Control-Allow-Origin: + - "*" + body: + encoding: ASCII-8BIT + string: !binary |- + eyJyZXN1bHRzIjpbeyJzaXJlbiI6IjIwMDA0MDIxMCIsIm5vbV9jb21wbGV0IjoiQ09NTVVOQVVURSBERSBDT01NVU5FUyBMQUNTIEVUIEdPUkdFUyBEVSBWRVJET04gKENDTEdWKSIsIm5vbV9yYWlzb25fc29jaWFsZSI6IkNPTU1VTkFVVEUgREUgQ09NTVVORVMgTEFDUyBFVCBHT1JHRVMgRFUgVkVSRE9OIiwic2lnbGUiOiJDQ0xHViIsIm5vbWJyZV9ldGFibGlzc2VtZW50cyI6Nywibm9tYnJlX2V0YWJsaXNzZW1lbnRzX291dmVydHMiOjYsInNpZWdlIjp7ImFjdGl2aXRlX3ByaW5jaXBhbGUiOiI4NC4xMVoiLCJhY3Rpdml0ZV9wcmluY2lwYWxlX3JlZ2lzdHJlX21ldGllciI6bnVsbCwiYW5uZWVfdHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjpudWxsLCJhZHJlc3NlIjoiMjQyIEFWRU5VRSBBTEJFUlQgMUVSIDgzNjMwIEFVUFMiLCJjYXJhY3RlcmVfZW1wbG95ZXVyIjoiTyIsImNlZGV4IjpudWxsLCJjb2RlX3BheXNfZXRyYW5nZXIiOm51bGwsImNvZGVfcG9zdGFsIjoiODM2MzAiLCJjb21tdW5lIjoiODMwMDciLCJjb21wbGVtZW50X2FkcmVzc2UiOm51bGwsImNvb3Jkb25uZWVzIjoiNDMuNjMwNTI0LDYuMjIxMjE4IiwiZGF0ZV9jcmVhdGlvbiI6IjIwMjMtMDQtMTMiLCJkYXRlX2RlYnV0X2FjdGl2aXRlIjoiMjAyMy0wNC0xMyIsImRhdGVfZmVybWV0dXJlIjpudWxsLCJkYXRlX21pc2VfYV9qb3VyIjpudWxsLCJkYXRlX21pc2VfYV9qb3VyX2luc2VlIjoiMjAyNC0wMy0zMFQwOTozMzo1MCIsImRlcGFydGVtZW50IjoiODMiLCJkaXN0cmlidXRpb25fc3BlY2lhbGUiOm51bGwsImVwY2kiOiIyMDAwNDAyMTAiLCJlc3Rfc2llZ2UiOnRydWUsImV0YXRfYWRtaW5pc3RyYXRpZiI6IkEiLCJnZW9fYWRyZXNzZSI6IjI0MiBBdmVudWUgQWxiZXJ0IDFlciA4MzYzMCBBdXBzIiwiZ2VvX2lkIjoiODMwMDdfMDAyMF8wMDI0MiIsImluZGljZV9yZXBldGl0aW9uIjpudWxsLCJsYXRpdHVkZSI6IjQzLjYzMDUyNCIsImxpYmVsbGVfY2VkZXgiOm51bGwsImxpYmVsbGVfY29tbXVuZSI6IkFVUFMiLCJsaWJlbGxlX2NvbW11bmVfZXRyYW5nZXIiOm51bGwsImxpYmVsbGVfcGF5c19ldHJhbmdlciI6bnVsbCwibGliZWxsZV92b2llIjoiQUxCRVJUIDFFUiIsImxpc3RlX2Vuc2VpZ25lcyI6bnVsbCwibGlzdGVfZmluZXNzIjpudWxsLCJsaXN0ZV9pZF9iaW8iOm51bGwsImxpc3RlX2lkY2MiOlsiNTAyMSJdLCJsaXN0ZV9pZF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpudWxsLCJsaXN0ZV9yZ2UiOm51bGwsImxpc3RlX3VhaSI6bnVsbCwibG9uZ2l0dWRlIjoiNi4yMjEyMTgiLCJub21fY29tbWVyY2lhbCI6bnVsbCwibnVtZXJvX3ZvaWUiOiIyNDIiLCJyZWdpb24iOiI5MyIsInNpcmV0IjoiMjAwMDQwMjEwMDAwNjAiLCJzdGF0dXRfZGlmZnVzaW9uX2V0YWJsaXNzZW1lbnQiOiJPIiwidHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjpudWxsLCJ0eXBlX3ZvaWUiOiJBVkVOVUUifSwiYWN0aXZpdGVfcHJpbmNpcGFsZSI6Ijg0LjExWiIsImNhdGVnb3JpZV9lbnRyZXByaXNlIjoiUE1FIiwiY2FyYWN0ZXJlX2VtcGxveWV1ciI6bnVsbCwiYW5uZWVfY2F0ZWdvcmllX2VudHJlcHJpc2UiOiIyMDIyIiwiZGF0ZV9jcmVhdGlvbiI6IjIwMTQtMDEtMDEiLCJkYXRlX2Zlcm1ldHVyZSI6bnVsbCwiZGF0ZV9taXNlX2Ffam91ciI6IjIwMjQtMTAtMTRUMTU6MDA6MDciLCJkYXRlX21pc2VfYV9qb3VyX2luc2VlIjoiMjAyNC0wMy0yMlQxNDoyNjowNiIsImRhdGVfbWlzZV9hX2pvdXJfcm5lIjpudWxsLCJkaXJpZ2VhbnRzIjpbXSwiZXRhdF9hZG1pbmlzdHJhdGlmIjoiQSIsIm5hdHVyZV9qdXJpZGlxdWUiOiI3MzQ2Iiwic2VjdGlvbl9hY3Rpdml0ZV9wcmluY2lwYWxlIjoiTyIsInRyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6IjIxIiwiYW5uZWVfdHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjoiMjAyMiIsInN0YXR1dF9kaWZmdXNpb24iOiJPIiwibWF0Y2hpbmdfZXRhYmxpc3NlbWVudHMiOlt7ImFjdGl2aXRlX3ByaW5jaXBhbGUiOiI4NC4xMVoiLCJhbmNpZW5fc2llZ2UiOmZhbHNlLCJhbm5lZV90cmFuY2hlX2VmZmVjdGlmX3NhbGFyaWUiOm51bGwsImFkcmVzc2UiOiIyNDIgQVZFTlVFIEFMQkVSVCAxRVIgODM2MzAgQVVQUyIsImNhcmFjdGVyZV9lbXBsb3lldXIiOiJPIiwiY29kZV9wb3N0YWwiOiI4MzYzMCIsImNvbW11bmUiOiI4MzAwNyIsImRhdGVfY3JlYXRpb24iOiIyMDIzLTA0LTEzIiwiZGF0ZV9kZWJ1dF9hY3Rpdml0ZSI6IjIwMjMtMDQtMTMiLCJkYXRlX2Zlcm1ldHVyZSI6bnVsbCwiZXBjaSI6IjIwMDA0MDIxMCIsImVzdF9zaWVnZSI6dHJ1ZSwiZXRhdF9hZG1pbmlzdHJhdGlmIjoiQSIsImdlb19pZCI6IjgzMDA3XzAwMjBfMDAyNDIiLCJsYXRpdHVkZSI6IjQzLjYzMDUyNCIsImxpYmVsbGVfY29tbXVuZSI6IkFVUFMiLCJsaXN0ZV9lbnNlaWduZXMiOm51bGwsImxpc3RlX2ZpbmVzcyI6bnVsbCwibGlzdGVfaWRfYmlvIjpudWxsLCJsaXN0ZV9pZGNjIjpbIjUwMjEiXSwibGlzdGVfaWRfb3JnYW5pc21lX2Zvcm1hdGlvbiI6bnVsbCwibGlzdGVfcmdlIjpudWxsLCJsaXN0ZV91YWkiOm51bGwsImxvbmdpdHVkZSI6IjYuMjIxMjE4Iiwibm9tX2NvbW1lcmNpYWwiOm51bGwsInJlZ2lvbiI6IjkzIiwic2lyZXQiOiIyMDAwNDAyMTAwMDA2MCIsInN0YXR1dF9kaWZmdXNpb25fZXRhYmxpc3NlbWVudCI6Ik8iLCJ0cmFuY2hlX2VmZmVjdGlmX3NhbGFyaWUiOm51bGx9XSwiZmluYW5jZXMiOm51bGwsImNvbXBsZW1lbnRzIjp7ImNvbGxlY3Rpdml0ZV90ZXJyaXRvcmlhbGUiOnsiY29kZSI6IjIwMDA0MDIxMCIsImNvZGVfaW5zZWUiOm51bGwsImVsdXMiOlt7Im5vbSI6IkRBR1VFVCIsInByZW5vbXMiOiJDYXRoZXJpbmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU3LTEyIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJGIn0seyJub20iOiJNT1JERUxFVCIsInByZW5vbXMiOiJDaGFybGVzLUFudG9pbmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTUyLTAxIiwiZm9uY3Rpb24iOiIzZW1lIFZpY2UtcHLDqXNpZGVudCBkdSBjb25zZWlsIGNvbW11bmF1dGFpcmUiLCJzZXhlIjoiTSJ9LHsibm9tIjoiQ09OU1RBTlMiLCJwcmVub21zIjoiU2VyZ2UiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTY3LTAyIiwiZm9uY3Rpb24iOiI2ZW1lIFZpY2UtcHLDqXNpZGVudCBkdSBjb25zZWlsIGNvbW11bmF1dGFpcmUiLCJzZXhlIjoiTSJ9LHsibm9tIjoiQk9OQVZFTlRVUkUiLCJwcmVub21zIjoiTWFyaWUtRnJhbsOnb2lzZSIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NjQtMDQiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6IkYifSx7Im5vbSI6IkZBVVJFIiwicHJlbm9tcyI6IkFudG9pbmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU1LTEwIiwiZm9uY3Rpb24iOiIyZW1lIFZpY2UtcHLDqXNpZGVudCBkdSBjb25zZWlsIGNvbW11bmF1dGFpcmUiLCJzZXhlIjoiTSJ9LHsibm9tIjoiUEFOVEVMIiwicHJlbm9tcyI6IkJlcm5hcmQiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTUwLTA4IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJST1VYIiwicHJlbm9tcyI6Ik1hcmzDqG5lIiwiYW5uZWVfZGVfbmFpc3NhbmNlIjoiMTk3My0wMyIsImZvbmN0aW9uIjpudWxsLCJzZXhlIjoiRiJ9LHsibm9tIjoiVEVSUkFTU09OIiwicHJlbm9tcyI6Ik1hcmllIENocmlzdGluZSIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NTYtMDEiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6IkYifSx7Im5vbSI6IlZJTkNFTlRFTExJIiwicHJlbm9tcyI6IlBhdHJpY2siLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTUxLTEwIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJBTkdMSU9OSU4iLCJwcmVub21zIjoiSm9hbm5lbCIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NzAtMDYiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6Ik0ifSx7Im5vbSI6IlJPVVgiLCJwcmVub21zIjoiSmVhbi1QYXVsIiwiYW5uZWVfZGVfbmFpc3NhbmNlIjoiMTk1My0wOSIsImZvbmN0aW9uIjpudWxsLCJzZXhlIjoiTSJ9LHsibm9tIjoiUk9VVklFUiIsInByZW5vbXMiOiJBcm1hbmQiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTYxLTAzIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJCRUxMSU5JIiwicHJlbm9tcyI6Ik5hbnMiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTg5LTA1IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJDQVJMRVRUSSIsInByZW5vbXMiOiJSYXltb25kZSIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NDYtMTIiLCJmb25jdGlvbiI6IjFlciBWaWNlLXByw6lzaWRlbnQgZHUgY29uc2VpbCBjb21tdW5hdXRhaXJlIiwic2V4ZSI6IkYifSx7Im5vbSI6IlJJQk9VTEVUIiwicHJlbm9tcyI6IkdpbGJlcnQiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU0LTExIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJCT05ORVQiLCJwcmVub21zIjoiUmVuw6kiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU1LTAyIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJEQVJSSUdPTCIsInByZW5vbXMiOiJHw6lyYXJkIiwiYW5uZWVfZGVfbmFpc3NhbmNlIjoiMTk1MC0xMiIsImZvbmN0aW9uIjpudWxsLCJzZXhlIjoiTSJ9LHsibm9tIjoiRklMSVBQSSIsInByZW5vbXMiOiJBbGFpbiIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NTAtMTEiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6Ik0ifSx7Im5vbSI6IkpFQU5ORVJFVCIsInByZW5vbXMiOiJSZW7DqWUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU4LTA4IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJGIn0seyJub20iOiJMSU9OIiwicHJlbm9tcyI6IkplYW4gUGllcnJlIiwiYW5uZWVfZGVfbmFpc3NhbmNlIjoiMTk1MS0wMyIsImZvbmN0aW9uIjpudWxsLCJzZXhlIjoiTSJ9LHsibm9tIjoiTUFUSElFVSIsInByZW5vbXMiOiJGcmFuY2siLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTc1LTEwIiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJHVUlHVUVTIiwicHJlbm9tcyI6IkRlbmlzZSIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NTktMDEiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6IkYifSx7Im5vbSI6IkJSSUVVR05FIiwicHJlbm9tcyI6IkZhYmllbiIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NTctMTIiLCJmb25jdGlvbiI6IjRlbWUgVmljZS1wcsOpc2lkZW50IGR1IGNvbnNlaWwgY29tbXVuYXV0YWlyZSIsInNleGUiOiJNIn0seyJub20iOiJHQUdMSUFOTyIsInByZW5vbXMiOiJDaHJpc3RpYW4iLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTQ5LTA3IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJMQVZBTCIsInByZW5vbXMiOiJTdMOpcGhhbmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU5LTA4IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJNVVJBVC1EQVZJRCIsInByZW5vbXMiOiJQaGlsaXBwZSIsImFubmVlX2RlX25haXNzYW5jZSI6IjE5NDgtMTAiLCJmb25jdGlvbiI6bnVsbCwic2V4ZSI6Ik0ifSx7Im5vbSI6IkJBTEJJUyIsInByZW5vbXMiOiJSb2xsYW5kIiwiYW5uZWVfZGVfbmFpc3NhbmNlIjoiMTk1Ni0wNiIsImZvbmN0aW9uIjoiUHLDqXNpZGVudCBkdSBjb25zZWlsIGNvbW11bmF1dGFpcmUiLCJzZXhlIjoiTSJ9LHsibm9tIjoiQkFTU0UiLCJwcmVub21zIjoiSmVhbi1DbGF1ZGUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTU3LTA4IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJNIn0seyJub20iOiJCT1RUQUNDSEkiLCJwcmVub21zIjoiTHlkaWUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTY4LTA5IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJGIn0seyJub20iOiJDT05TVEFOUyIsInByZW5vbXMiOiJQaWVycmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTUwLTExIiwiZm9uY3Rpb24iOiI1ZW1lIFZpY2UtcHLDqXNpZGVudCBkdSBjb25zZWlsIGNvbW11bmF1dGFpcmUiLCJzZXhlIjoiTSJ9LHsibm9tIjoiTU9NQlJJQUwtRkFZQVVCT1NUIiwicHJlbm9tcyI6Ik1hcnRpbmUiLCJhbm5lZV9kZV9uYWlzc2FuY2UiOiIxOTQ2LTA4IiwiZm9uY3Rpb24iOm51bGwsInNleGUiOiJGIn1dLCJuaXZlYXUiOiJlcGNpIn0sImNvbnZlbnRpb25fY29sbGVjdGl2ZV9yZW5zZWlnbmVlIjp0cnVlLCJsaXN0ZV9pZGNjIjpbIjUwMjEiXSwiZWdhcHJvX3JlbnNlaWduZWUiOmZhbHNlLCJlc3RfYXNzb2NpYXRpb24iOmZhbHNlLCJlc3RfYmlvIjpmYWxzZSwiZXN0X2VudHJlcHJlbmV1cl9pbmRpdmlkdWVsIjpmYWxzZSwiZXN0X2VudHJlcHJlbmV1cl9zcGVjdGFjbGUiOmZhbHNlLCJlc3RfZXNzIjpmYWxzZSwiZXN0X2ZpbmVzcyI6ZmFsc2UsImVzdF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpmYWxzZSwiZXN0X3F1YWxpb3BpIjpmYWxzZSwibGlzdGVfaWRfb3JnYW5pc21lX2Zvcm1hdGlvbiI6bnVsbCwiZXN0X3JnZSI6ZmFsc2UsImVzdF9zZXJ2aWNlX3B1YmxpYyI6dHJ1ZSwiZXN0X3NpYWUiOmZhbHNlLCJlc3Rfc29jaWV0ZV9taXNzaW9uIjpmYWxzZSwiZXN0X3VhaSI6ZmFsc2UsImlkZW50aWZpYW50X2Fzc29jaWF0aW9uIjpudWxsLCJzdGF0dXRfZW50cmVwcmVuZXVyX3NwZWN0YWNsZSI6bnVsbCwidHlwZV9zaWFlIjpudWxsfX1dLCJ0b3RhbF9yZXN1bHRzIjoxLCJwYWdlIjoxLCJwZXJfcGFnZSI6MTAsInRvdGFsX3BhZ2VzIjoxfQ== + recorded_at: Tue, 15 Oct 2024 13:53:25 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/cassettes/annuaire_service_public_success_35600082800018.yml b/spec/fixtures/cassettes/annuaire_service_public_success_35600082800018.yml new file mode 100644 index 000000000..6414d37be --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_success_35600082800018.yml @@ -0,0 +1,122 @@ +--- +http_interactions: +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:35600082800018 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Tue, 15 Oct 2024 16:24:16 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '33' + X-Ratelimit-Remaining: + - '999919' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-16 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 0, "results": []}' + recorded_at: Tue, 15 Oct 2024 16:24:16 GMT +- request: + method: get + uri: https://recherche-entreprises.api.gouv.fr/search?q=35600082800018 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - nginx/1.27.1 + Date: + - Tue, 15 Oct 2024 16:24:16 GMT + Content-Type: + - application/json + Content-Length: + - '3374' + Vary: + - Accept-Encoding + - Accept-Encoding + - Accept-Encoding + Annuaire-Entreprises-Instance-Number: + - '01' + - '02' + X-Frame-Options: + - DENY + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + Access-Control-Allow-Headers: + - Content-Type + Access-Control-Allow-Origin: + - "*" + body: + encoding: ASCII-8BIT + string: '{"results":[{"siren":"356000828","nom_complet":"LA POSTE (REGION RHONE + ALPES)","nom_raison_sociale":"LA POSTE","sigle":null,"nombre_etablissements":2948,"nombre_etablissements_ouverts":0,"siege":{"activite_principale":"53.10Z","activite_principale_registre_metier":null,"annee_tranche_effectif_salarie":null,"adresse":"4 + QUAI DU POINT DU JOUR 92100 BOULOGNE-BILLANCOURT","caractere_employeur":"N","cedex":null,"code_pays_etranger":null,"code_postal":"92100","commune":"92012","complement_adresse":null,"coordonnees":"48.832893,2.259972","date_creation":"1991-01-01","date_debut_activite":"2011-12-31","date_fermeture":"2011-12-31","date_mise_a_jour":null,"date_mise_a_jour_insee":"2024-03-22T15:40:57","departement":"92","distribution_speciale":null,"epci":"200054781","est_siege":true,"etat_administratif":"F","geo_adresse":"4 + Quai du Point du Jour 92100 Boulogne-Billancourt","geo_id":"92012_7231_00004","indice_repetition":null,"latitude":"48.832893","libelle_cedex":null,"libelle_commune":"BOULOGNE-BILLANCOURT","libelle_commune_etranger":null,"libelle_pays_etranger":null,"libelle_voie":"DU + POINT DU JOUR","liste_enseignes":null,"liste_finess":null,"liste_id_bio":null,"liste_idcc":null,"liste_id_organisme_formation":null,"liste_rge":null,"liste_uai":null,"longitude":"2.259972","nom_commercial":null,"numero_voie":"4","region":"11","siret":"35600082800018","statut_diffusion_etablissement":"O","tranche_effectif_salarie":null,"type_voie":"QUAI"},"activite_principale":"53.10Z","categorie_entreprise":null,"caractere_employeur":null,"annee_categorie_entreprise":null,"date_creation":"1991-01-01","date_fermeture":"2011-12-31","date_mise_a_jour":"2024-10-14T15:38:40","date_mise_a_jour_insee":"2024-03-22T14:26:06","date_mise_a_jour_rne":null,"dirigeants":[],"etat_administratif":"C","nature_juridique":"4130","section_activite_principale":"H","tranche_effectif_salarie":null,"annee_tranche_effectif_salarie":null,"statut_diffusion":"O","matching_etablissements":[{"activite_principale":"53.10Z","ancien_siege":false,"annee_tranche_effectif_salarie":null,"adresse":"4 + QUAI DU POINT DU JOUR 92100 BOULOGNE-BILLANCOURT","caractere_employeur":"N","code_postal":"92100","commune":"92012","date_creation":"1991-01-01","date_debut_activite":"2011-12-31","date_fermeture":"2011-12-31","epci":"200054781","est_siege":true,"etat_administratif":"F","geo_id":"92012_7231_00004","latitude":"48.832893","libelle_commune":"BOULOGNE-BILLANCOURT","liste_enseignes":null,"liste_finess":null,"liste_id_bio":null,"liste_idcc":null,"liste_id_organisme_formation":null,"liste_rge":null,"liste_uai":null,"longitude":"2.259972","nom_commercial":null,"region":"11","siret":"35600082800018","statut_diffusion_etablissement":"O","tranche_effectif_salarie":null}],"finances":null,"complements":{"collectivite_territoriale":null,"convention_collective_renseignee":false,"liste_idcc":null,"egapro_renseignee":false,"est_association":false,"est_bio":false,"est_entrepreneur_individuel":false,"est_entrepreneur_spectacle":false,"est_ess":false,"est_finess":false,"est_organisme_formation":false,"est_qualiopi":false,"liste_id_organisme_formation":null,"est_rge":false,"est_service_public":true,"est_siae":false,"est_societe_mission":false,"est_uai":false,"identifiant_association":null,"statut_entrepreneur_spectacle":null,"type_siae":null}}],"total_results":1,"page":1,"per_page":10,"total_pages":1}' + recorded_at: Tue, 15 Oct 2024 16:24:16 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/cassettes/annuaire_service_public_success_41816609600051.yml b/spec/fixtures/cassettes/annuaire_service_public_success_41816609600051.yml new file mode 100644 index 000000000..dc50ca6b5 --- /dev/null +++ b/spec/fixtures/cassettes/annuaire_service_public_success_41816609600051.yml @@ -0,0 +1,119 @@ +--- +http_interactions: +- request: + method: get + uri: https://recherche-entreprises.api.gouv.fr/search?q=41816609600051 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - nginx/1.27.1 + Date: + - Thu, 17 Oct 2024 07:51:06 GMT + Content-Type: + - application/json + Content-Length: + - '3471' + Vary: + - Accept-Encoding + - Accept-Encoding + - Accept-Encoding + Annuaire-Entreprises-Instance-Number: + - '02' + X-Frame-Options: + - DENY + X-Content-Type-Options: + - nosniff + Strict-Transport-Security: + - max-age=31536000 + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + Access-Control-Allow-Headers: + - Content-Type + Access-Control-Allow-Origin: + - "*" + body: + encoding: ASCII-8BIT + string: !binary |- + eyJyZXN1bHRzIjpbeyJzaXJlbiI6IjQxODE2NjA5NiIsIm5vbV9jb21wbGV0IjoiT0NUTy1URUNITk9MT0dZIiwibm9tX3JhaXNvbl9zb2NpYWxlIjoiT0NUTy1URUNITk9MT0dZIiwic2lnbGUiOm51bGwsIm5vbWJyZV9ldGFibGlzc2VtZW50cyI6Nywibm9tYnJlX2V0YWJsaXNzZW1lbnRzX291dmVydHMiOjEsInNpZWdlIjp7ImFjdGl2aXRlX3ByaW5jaXBhbGUiOiI2Mi4wMkEiLCJhY3Rpdml0ZV9wcmluY2lwYWxlX3JlZ2lzdHJlX21ldGllciI6bnVsbCwiYW5uZWVfdHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjoiMjAyMiIsImFkcmVzc2UiOiIzNCBBVkVOVUUgREUgTCdPUEVSQSA3NTAwMiBQQVJJUyIsImNhcmFjdGVyZV9lbXBsb3lldXIiOiJPIiwiY2VkZXgiOm51bGwsImNvZGVfcGF5c19ldHJhbmdlciI6bnVsbCwiY29kZV9wb3N0YWwiOiI3NTAwMiIsImNvbW11bmUiOiI3NTEwMiIsImNvbXBsZW1lbnRfYWRyZXNzZSI6bnVsbCwiY29vcmRvbm5lZXMiOiI0OC44Njg2NjIsMi4zMzMzODIiLCJkYXRlX2NyZWF0aW9uIjoiMjAxNi0xMS0yOCIsImRhdGVfZGVidXRfYWN0aXZpdGUiOiIyMDE2LTExLTI4IiwiZGF0ZV9mZXJtZXR1cmUiOm51bGwsImRhdGVfbWlzZV9hX2pvdXIiOm51bGwsImRhdGVfbWlzZV9hX2pvdXJfaW5zZWUiOiIyMDI0LTA1LTMxVDA1OjI5OjU4IiwiZGVwYXJ0ZW1lbnQiOiI3NSIsImRpc3RyaWJ1dGlvbl9zcGVjaWFsZSI6bnVsbCwiZXBjaSI6IjIwMDA1NDc4MSIsImVzdF9zaWVnZSI6dHJ1ZSwiZXRhdF9hZG1pbmlzdHJhdGlmIjoiQSIsImdlb19hZHJlc3NlIjoiMzQgQXZlbnVlIGRlIGwnT3DDqXJhIDc1MDAyIFBhcmlzIiwiZ2VvX2lkIjoiNzUxMDJfNjkwNF8wMDAzNCIsImluZGljZV9yZXBldGl0aW9uIjpudWxsLCJsYXRpdHVkZSI6IjQ4Ljg2ODY2MiIsImxpYmVsbGVfY2VkZXgiOm51bGwsImxpYmVsbGVfY29tbXVuZSI6IlBBUklTIiwibGliZWxsZV9jb21tdW5lX2V0cmFuZ2VyIjpudWxsLCJsaWJlbGxlX3BheXNfZXRyYW5nZXIiOm51bGwsImxpYmVsbGVfdm9pZSI6IkRFIEwnT1BFUkEiLCJsaXN0ZV9lbnNlaWduZXMiOm51bGwsImxpc3RlX2ZpbmVzcyI6bnVsbCwibGlzdGVfaWRfYmlvIjpudWxsLCJsaXN0ZV9pZGNjIjpbIjE0ODYiXSwibGlzdGVfaWRfb3JnYW5pc21lX2Zvcm1hdGlvbiI6bnVsbCwibGlzdGVfcmdlIjpudWxsLCJsaXN0ZV91YWkiOm51bGwsImxvbmdpdHVkZSI6IjIuMzMzMzgyIiwibm9tX2NvbW1lcmNpYWwiOm51bGwsIm51bWVyb192b2llIjoiMzQiLCJyZWdpb24iOiIxMSIsInNpcmV0IjoiNDE4MTY2MDk2MDAwNjkiLCJzdGF0dXRfZGlmZnVzaW9uX2V0YWJsaXNzZW1lbnQiOiJPIiwidHJhbmNoZV9lZmZlY3RpZl9zYWxhcmllIjoiNDEiLCJ0eXBlX3ZvaWUiOiJBVkVOVUUifSwiYWN0aXZpdGVfcHJpbmNpcGFsZSI6IjYyLjAyQSIsImNhdGVnb3JpZV9lbnRyZXByaXNlIjoiR0UiLCJjYXJhY3RlcmVfZW1wbG95ZXVyIjpudWxsLCJhbm5lZV9jYXRlZ29yaWVfZW50cmVwcmlzZSI6IjIwMjIiLCJkYXRlX2NyZWF0aW9uIjoiMTk5OC0wNC0wMSIsImRhdGVfZmVybWV0dXJlIjpudWxsLCJkYXRlX21pc2VfYV9qb3VyIjoiMjAyNC0xMC0xNlQxMzowODowMyIsImRhdGVfbWlzZV9hX2pvdXJfaW5zZWUiOiIyMDI0LTA1LTMxVDA1OjI5OjU4IiwiZGF0ZV9taXNlX2Ffam91cl9ybmUiOiIyMDI0LTA1LTE5VDE2OjQ5OjMzIiwiZGlyaWdlYW50cyI6W3sic2lyZW4iOm51bGwsImRlbm9taW5hdGlvbiI6IktQTUciLCJxdWFsaXRlIjoiQ29tbWlzc2FpcmUgYXV4IGNvbXB0ZXMgdGl0dWxhaXJlIiwidHlwZV9kaXJpZ2VhbnQiOiJwZXJzb25uZSBtb3JhbGUifV0sImV0YXRfYWRtaW5pc3RyYXRpZiI6IkEiLCJuYXR1cmVfanVyaWRpcXVlIjoiNTcxMCIsInNlY3Rpb25fYWN0aXZpdGVfcHJpbmNpcGFsZSI6IkoiLCJ0cmFuY2hlX2VmZmVjdGlmX3NhbGFyaWUiOiI0MSIsImFubmVlX3RyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6IjIwMjIiLCJzdGF0dXRfZGlmZnVzaW9uIjoiTyIsIm1hdGNoaW5nX2V0YWJsaXNzZW1lbnRzIjpbeyJhY3Rpdml0ZV9wcmluY2lwYWxlIjoiNjIuMDJBIiwiYW5jaWVuX3NpZWdlIjp0cnVlLCJhbm5lZV90cmFuY2hlX2VmZmVjdGlmX3NhbGFyaWUiOm51bGwsImFkcmVzc2UiOiI1MCBBVkVOVUUgREVTIENIQU1QUyBFTFlTRUVTIDc1MDA4IFBBUklTIiwiY2FyYWN0ZXJlX2VtcGxveWV1ciI6Ik8iLCJjb2RlX3Bvc3RhbCI6Ijc1MDA4IiwiY29tbXVuZSI6Ijc1MTA4IiwiZGF0ZV9jcmVhdGlvbiI6IjIwMDUtMDItMTciLCJkYXRlX2RlYnV0X2FjdGl2aXRlIjoiMjAxNi0xMS0yOCIsImRhdGVfZmVybWV0dXJlIjoiMjAxNi0xMS0yOCIsImVwY2kiOiIyMDAwNTQ3ODEiLCJlc3Rfc2llZ2UiOmZhbHNlLCJldGF0X2FkbWluaXN0cmF0aWYiOiJGIiwiZ2VvX2lkIjoiNzUxMDhfMTczM18wMDA1MCIsImxhdGl0dWRlIjoiNDguODcwMzcxIiwibGliZWxsZV9jb21tdW5lIjoiUEFSSVMiLCJsaXN0ZV9lbnNlaWduZXMiOm51bGwsImxpc3RlX2ZpbmVzcyI6bnVsbCwibGlzdGVfaWRfYmlvIjpudWxsLCJsaXN0ZV9pZGNjIjpudWxsLCJsaXN0ZV9pZF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpudWxsLCJsaXN0ZV9yZ2UiOm51bGwsImxpc3RlX3VhaSI6bnVsbCwibG9uZ2l0dWRlIjoiMi4zMDY4OTkiLCJub21fY29tbWVyY2lhbCI6bnVsbCwicmVnaW9uIjoiMTEiLCJzaXJldCI6IjQxODE2NjA5NjAwMDUxIiwic3RhdHV0X2RpZmZ1c2lvbl9ldGFibGlzc2VtZW50IjoiTyIsInRyYW5jaGVfZWZmZWN0aWZfc2FsYXJpZSI6bnVsbH1dLCJmaW5hbmNlcyI6eyIyMDIzIjp7ImNhIjoxNDYxMzk4MDksInJlc3VsdGF0X25ldCI6MTA2MjY2Mzh9fSwiY29tcGxlbWVudHMiOnsiY29sbGVjdGl2aXRlX3RlcnJpdG9yaWFsZSI6bnVsbCwiY29udmVudGlvbl9jb2xsZWN0aXZlX3JlbnNlaWduZWUiOnRydWUsImxpc3RlX2lkY2MiOlsiMTQ4NiJdLCJlZ2Fwcm9fcmVuc2VpZ25lZSI6dHJ1ZSwiZXN0X2Fzc29jaWF0aW9uIjpmYWxzZSwiZXN0X2JpbyI6ZmFsc2UsImVzdF9lbnRyZXByZW5ldXJfaW5kaXZpZHVlbCI6ZmFsc2UsImVzdF9lbnRyZXByZW5ldXJfc3BlY3RhY2xlIjpmYWxzZSwiZXN0X2VzcyI6ZmFsc2UsImVzdF9maW5lc3MiOmZhbHNlLCJlc3Rfb3JnYW5pc21lX2Zvcm1hdGlvbiI6dHJ1ZSwiZXN0X3F1YWxpb3BpIjp0cnVlLCJsaXN0ZV9pZF9vcmdhbmlzbWVfZm9ybWF0aW9uIjpbIjExNzU0ODkzNjc1Il0sImVzdF9yZ2UiOmZhbHNlLCJlc3Rfc2VydmljZV9wdWJsaWMiOmZhbHNlLCJlc3Rfc2lhZSI6ZmFsc2UsImVzdF9zb2NpZXRlX21pc3Npb24iOmZhbHNlLCJlc3RfdWFpIjpmYWxzZSwiaWRlbnRpZmlhbnRfYXNzb2NpYXRpb24iOm51bGwsInN0YXR1dF9lbnRyZXByZW5ldXJfc3BlY3RhY2xlIjpudWxsLCJ0eXBlX3NpYWUiOm51bGx9fV0sInRvdGFsX3Jlc3VsdHMiOjEsInBhZ2UiOjEsInBlcl9wYWdlIjoxMCwidG90YWxfcGFnZXMiOjF9 + recorded_at: Thu, 17 Oct 2024 07:51:06 GMT +- request: + method: get + uri: https://api-lannuaire.service-public.fr/api/explore/v2.1/catalog/datasets/api-lannuaire-administration/records?where=siret:41816609600051 + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Server: + - openresty + Date: + - Thu, 17 Oct 2024 07:51:06 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '33' + X-Ratelimit-Remaining: + - '999989' + X-Ratelimit-Limit: + - '1000000' + X-Ratelimit-Reset: + - '2024-10-18 00:00:00+00:00' + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Vary: + - Accept-Language, Cookie, Host + Content-Language: + - fr-fr + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Methods: + - POST, GET, OPTIONS + Access-Control-Max-Age: + - '1000' + Access-Control-Allow-Headers: + - Authorization, X-Requested-With, Origin, ODS-API-Analytics-App, ODS-API-Analytics-Embed-Type, + ODS-API-Analytics-Embed-Referrer, ODS-Widgets-Version, Accept + Access-Control-Expose-Headers: + - ODS-Explore-API-Deprecation, Link, X-RateLimit-Remaining, X-RateLimit-Limit, + X-RateLimit-Reset, X-RateLimit-dataset-Remaining, X-RateLimit-dataset-Limit, + X-RateLimit-dataset-Reset + Strict-Transport-Security: + - max-age=31536000 + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + Referrer-Policy: + - strict-origin-when-cross-origin + Permissions-Policy: + - midi=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=() + Content-Security-Policy: + - upgrade-insecure-requests; + X-Ua-Compatible: + - IE=edge + body: + encoding: ASCII-8BIT + string: '{"total_count": 0, "results": []}' + recorded_at: Thu, 17 Oct 2024 07:51:06 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/models/concerns/prefillable_from_service_public_concern_spec.rb b/spec/models/concerns/prefillable_from_service_public_concern_spec.rb new file mode 100644 index 000000000..4580ac689 --- /dev/null +++ b/spec/models/concerns/prefillable_from_service_public_concern_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PrefillableFromServicePublicConcern, type: :model do + let(:siret) { '20004021000060' } + let(:service) { build(:service, siret:) } + + describe '#prefill_from_siret' do + let(:service) { Service.new(siret:) } + subject { service.prefill_from_siret } + context 'when API call is successful with collectivite' do + it 'prefills service attributes' do + VCR.use_cassette('annuaire_service_public_success_20004021000060') do + expect(subject.all?(&:success?)).to be_truthy + + expect(service.nom).to eq("Communauté de communes - Lacs et Gorges du Verdon") + expect(service).to be_collectivite_territoriale + expect(service.email).to eq("redacted@email.fr") + expect(service.telephone).to eq("04 94 70 00 00") + expect(service.horaires).to eq("Lundi au Jeudi : de 8:00 à 12:00 et de 13:30 à 17:30\nVendredi : de 8:00 à 12:00") + expect(service.adresse).to eq("242 avenue Albert-1er 83630 Aups") + end + end + + it 'does not overwrite existing attributes' do + service.nom = "Existing Name" + service.email = "existing@email.com" + + VCR.use_cassette('annuaire_service_public_success_20004021000060') do + service.prefill_from_siret + + expect(service.nom).to eq("Existing Name") + expect(service.email).to eq("existing@email.com") + end + end + end + + context 'when API call do not find siret' do + let(:siret) { '20004021000000' } + it 'returns a failure result' do + VCR.use_cassette('annuaire_service_public_failure_20004021000000') do + expect(subject.all?(&:failure?)).to be_truthy + end + end + end + + context 'when SIRET is enseignement' do + let(:siret) { '19750664500013' } + it 'prefills for enseignement' do + VCR.use_cassette('annuaire_service_public_success_19750664500013') do + expect(subject.one?(&:success?)).to be_truthy + expect(service.nom).to eq("LYCEE GENERAL ET TECHNOLOGIQUE RACINE") + expect(service).to be_etablissement_enseignement + expect(service.adresse).to eq("20 Rue du Rocher 75008 Paris") + expect(service.horaires).to be_nil + end + end + end + + context 'when SIRET is a ministere' do + let(:siret) { '11004601800013' } + it 'prefills for administration centrale' do + VCR.use_cassette('annuaire_service_public_success_11004601800013') do + expect(subject.one?(&:success?)).to be_truthy + expect(service.nom).to eq("MINISTERE DE LA CULTURE") + expect(service).to be_administration_centrale + expect(service.adresse).to eq("182 Rue Saint-Honoré 75001 Paris") + expect(service.horaires).to be_nil + end + end + end + + context 'when SIRET is La Poste' do + let(:siret) { '35600082800018' } + it 'prefills for administration centrale' do + VCR.use_cassette('annuaire_service_public_success_35600082800018') do + expect(subject.one?(&:success?)).to be_truthy + expect(service.nom).to eq("LA POSTE (REGION RHONE ALPES)") + expect(service).to be_service_deconcentre_de_l_etat + expect(service.adresse).to eq("4 Quai du Point du Jour 92100 Boulogne-Billancourt") + expect(service.horaires).to be_nil + end + end + end + end + + describe '#denormalize_plage_ouverture' do + it 'correctly formats opening hours with one time range' do + data = [ + { + "nom_jour_debut" => "Lundi", + "nom_jour_fin" => "Vendredi", + "valeur_heure_debut_1" => "09:00:00", + "valeur_heure_fin_1" => "17:00:00" + } + ] + expect(service.send(:denormalize_plage_ouverture, data)).to eq("Lundi au Vendredi : de 9:00 à 17:00") + end + + it 'correctly formats opening hours with two time ranges' do + data = [ + { + "nom_jour_debut" => "Lundi", + "nom_jour_fin" => "Jeudi", + "valeur_heure_debut_1" => "08:00:00", + "valeur_heure_fin_1" => "12:00:00", + "valeur_heure_debut_2" => "13:30:00", + "valeur_heure_fin_2" => "17:30:00" + }, { + "nom_jour_debut" => "Vendredi", + "nom_jour_fin" => "Vendredi", + "valeur_heure_debut_1" => "08:00:00", + "valeur_heure_fin_1" => "12:00:00" + } + ] + expect(service.send(:denormalize_plage_ouverture, data)).to eq("Lundi au Jeudi : de 8:00 à 12:00 et de 13:30 à 17:30\nVendredi : de 8:00 à 12:00") + end + + it 'includes comments when present' do + data = [ + { + "nom_jour_debut" => "Lundi", + "nom_jour_fin" => "Vendredi", + "valeur_heure_debut_1" => "09:00:00", + "valeur_heure_fin_1" => "17:00:00", + "commentaire" => "Fermé les jours fériés" + } + ] + expect(service.send(:denormalize_plage_ouverture, data)).to eq("Lundi au Vendredi : de 9:00 à 17:00 (Fermé les jours fériés)") + end + end +end