Merge pull request #6464 from betagouv/show_avalaible_sources
montre les sources disponibles pour un jeton api particulier
This commit is contained in:
commit
47e3c0067c
14 changed files with 231 additions and 2 deletions
26
app/assets/stylesheets/sources_particulier_form.scss
Normal file
26
app/assets/stylesheets/sources_particulier_form.scss
Normal file
|
@ -0,0 +1,26 @@
|
|||
@import "constants";
|
||||
|
||||
#sources-particulier-form {
|
||||
h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 2 * $default-padding;
|
||||
}
|
||||
|
||||
.explication {
|
||||
padding: $default-padding;
|
||||
|
||||
ul {
|
||||
list-style-type: circle;
|
||||
list-style-position: inside;
|
||||
padding-left: $default-padding;
|
||||
margin-bottom: $default-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.form input[type="checkbox"] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ module NewAdministrateur
|
|||
@procedure.api_particulier_scopes = scopes
|
||||
@procedure.save!
|
||||
|
||||
redirect_to admin_procedure_api_particulier_jeton_path(procedure_id: @procedure.id),
|
||||
redirect_to admin_procedure_api_particulier_sources_path(procedure_id: @procedure.id),
|
||||
notice: t('.token_ok')
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
module NewAdministrateur
|
||||
class SourcesParticulierController < AdministrateurController
|
||||
before_action :retrieve_procedure
|
||||
|
||||
def show
|
||||
sources_service = APIParticulier::Services::SourcesService.new(@procedure)
|
||||
@available_sources = sources_service.available_sources
|
||||
end
|
||||
|
||||
def update
|
||||
end
|
||||
end
|
||||
end
|
42
app/lib/api_particulier/services/sources_service.rb
Normal file
42
app/lib/api_particulier/services/sources_service.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
module APIParticulier
|
||||
module Services
|
||||
class SourcesService
|
||||
def initialize(procedure)
|
||||
@procedure = procedure
|
||||
end
|
||||
|
||||
def available_sources
|
||||
@procedure.api_particulier_scopes
|
||||
.map { |provider_and_scope| raw_scopes[provider_and_scope] }
|
||||
.map { |provider, scope| extract_sources(provider, scope) }
|
||||
.reduce({}) { |acc, el| acc.deep_merge(el) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def extract_sources(provider, scope)
|
||||
{ provider => { scope => providers[provider][scope] } }
|
||||
end
|
||||
|
||||
def raw_scopes
|
||||
{
|
||||
'cnaf_allocataires' => ['cnaf', 'allocataires'],
|
||||
'cnaf_enfants' => ['cnaf', 'enfants'],
|
||||
'cnaf_adresse' => ['cnaf', 'adresse'],
|
||||
'cnaf_quotient_familial' => ['cnaf', 'quotient_familial']
|
||||
}
|
||||
end
|
||||
|
||||
def providers
|
||||
{
|
||||
'cnaf' => {
|
||||
'allocataires' => ['noms_prenoms', 'date_de_naissance', 'sexe'],
|
||||
'enfants' => ['noms_prenoms', 'date_de_naissance', 'sexe'],
|
||||
'adresse' => ['identite', 'complement_d_identite', 'complement_d_identite_geo', 'numero_et_rue', 'lieu_dit', 'code_postal_et_ville', 'pays'],
|
||||
'quotient_familial' => ['quotient_familial', 'annee', 'mois']
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@
|
|||
# allow_expert_review :boolean default(TRUE), not null
|
||||
# api_entreprise_token :string
|
||||
# api_particulier_scopes :text default([]), is an Array
|
||||
# api_particulier_sources :jsonb
|
||||
# ask_birthday :boolean default(FALSE), not null
|
||||
# auto_archive_on :date
|
||||
# cadre_juridique :string
|
||||
|
|
|
@ -18,3 +18,17 @@
|
|||
%p.card-admin-title
|
||||
= Procedure.human_attribute_name(:jeton_api_particulier)
|
||||
%p.button= t('views.shared.actions.edit')
|
||||
|
||||
- if @procedure.api_particulier_scopes.present?
|
||||
= link_to admin_procedure_api_particulier_sources_path, class: 'card-admin' do
|
||||
- if @procedure.api_particulier_token.blank?
|
||||
%div
|
||||
%span.icon.clock
|
||||
%p.card-admin-status-todo= t('.needs_configuration')
|
||||
- else
|
||||
%div
|
||||
%span.icon.accept
|
||||
%p.card-admin-status-accept= t('.already_configured')
|
||||
%div
|
||||
%p.card-admin-title= t('new_administrateur.sources_particulier.show.data_sources')
|
||||
%p.button= t('views.shared.actions.edit')
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
= render partial: 'new_administrateur/breadcrumbs',
|
||||
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||
link_to(Procedure.human_attribute_name(:jeton_api_particulier), admin_procedure_api_particulier_path(@procedure)),
|
||||
t('.data_sources')] }
|
||||
|
||||
.container
|
||||
%h1.page-title= t('.title')
|
||||
|
||||
.container#sources-particulier-form.mb-2
|
||||
= form_with model: @procedure, url: admin_procedure_api_particulier_sources_path, local: true, html: { class: 'form' } do |f|
|
||||
.explication= t('.explication_html')
|
||||
|
||||
- @available_sources.each do |provider_key, scopes|
|
||||
%h2.header-section= t("api_particulier.providers.#{provider_key}.libelle")
|
||||
|
||||
- scopes.each do |scope_key, sources|
|
||||
%h3.explication-libelle= t("api_particulier.providers.#{provider_key}.scopes.#{scope_key}.libelle")
|
||||
%ul.procedure-admin-api-particulier-sources
|
||||
- sources.each do |source_key, enabled_hash|
|
||||
- enabled = (@procedure.api_particulier_sources.dig(provider_key, scope_key)&.include?(source_key)).present?
|
||||
%li
|
||||
%label
|
||||
= check_box_tag "api_particulier_sources[#{provider_key}][#{scope_key}][]", "#{source_key}", enabled
|
||||
#{t("api_particulier.providers.#{provider_key}.scopes.#{scope_key}.#{source_key}")}
|
||||
|
||||
.text-right
|
||||
= f.button t('views.shared.actions.save'), class: 'button primary send'
|
30
config/locales/api_particulier.fr.yml
Normal file
30
config/locales/api_particulier.fr.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
fr:
|
||||
api_particulier:
|
||||
providers:
|
||||
cnaf:
|
||||
libelle: Caisse d’allocations familiales (CAF)
|
||||
scopes:
|
||||
personne: &personne
|
||||
noms_prenoms: noms et prénoms
|
||||
date_de_naissance: date de naissance
|
||||
sexe: genre
|
||||
allocataires:
|
||||
libelle: allocataires
|
||||
<<: *personne
|
||||
enfants:
|
||||
libelle: enfants
|
||||
<<: *personne
|
||||
adresse:
|
||||
libelle: adresse
|
||||
identite: identité
|
||||
complement_d_identite: complément d’identité
|
||||
complement_d_identite_geo: complément d’identité géographique
|
||||
numero_et_rue: numéro et rue
|
||||
lieu_dit: lieu-dit
|
||||
code_postal_et_ville: code postal et ville
|
||||
pays: pays
|
||||
quotient_familial:
|
||||
libelle: quotient familial
|
||||
quotient_familial: quotient familial
|
||||
mois: mois
|
||||
annee: année
|
|
@ -395,3 +395,13 @@ fr:
|
|||
api_particulier:
|
||||
already_configured: "Déjà rempli"
|
||||
needs_configuration: "À remplir"
|
||||
sources_particulier:
|
||||
show:
|
||||
title: "Définir les sources de données"
|
||||
data_sources: "Sources de données"
|
||||
explication_html: "<p>API Particulier facilite l’accès des administrations aux données familiales (CAF) pour simplifier les démarches administratives mises en œuvre par les collectivités et les administrations.<br> Cela permet aux administrations d’accéder à des informations certifiées à la source et ainsi : </p> <ul> <li>de s’affranchir des pièces justificatives lors des démarches en ligne,</li> <li>de réduire le nombre d’erreurs de saisie,</li> <li>d’écarter le risque de fraude documentaire.</li> </ul> <p> <strong>Important :</strong> les disposition de l'article <a href='https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000031366350&idArticle=LEGIARTI000031367412&dateTexte=&categorieLien=cid'>L144-8</a> n’autorisent que l’échange des informations strictement nécessaires pour traiter une démarche.<br /><br />En conséquence, ne sélectionnez ici que les données auxquelles vous aurez accès d’un point de vue légal.</p>"
|
||||
procedures:
|
||||
show:
|
||||
ready: "Validé"
|
||||
needs_configuration: "À configurer"
|
||||
configure_api_particulier_token: "Configurer le jeton API particulier"
|
||||
|
|
|
@ -401,6 +401,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resource 'api_particulier', only: [] do
|
||||
resource 'jeton', only: [:show, :update], controller: 'jeton_particulier'
|
||||
resource 'sources', only: [:show, :update], controller: 'sources_particulier'
|
||||
end
|
||||
|
||||
put 'clone'
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class AddAPIParticulierSourcesToProcedure < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :procedures, :api_particulier_sources, :jsonb, :default => {}
|
||||
add_index :procedures, :api_particulier_sources, using: :gin
|
||||
end
|
||||
end
|
|
@ -10,7 +10,8 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_09_08_162000) do
|
||||
ActiveRecord::Schema.define(version: 2021_09_08_170019) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "unaccent"
|
||||
|
@ -619,6 +620,8 @@ ActiveRecord::Schema.define(version: 2021_09_08_162000) do
|
|||
t.boolean "experts_require_administrateur_invitation", default: false
|
||||
t.string "encrypted_api_particulier_token"
|
||||
t.text "api_particulier_scopes", default: [], array: true
|
||||
t.jsonb "api_particulier_sources", default: {}
|
||||
t.index ["api_particulier_sources"], name: "index_procedures_on_api_particulier_sources", using: :gin
|
||||
t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state"
|
||||
t.index ["draft_revision_id"], name: "index_procedures_on_draft_revision_id"
|
||||
t.index ["hidden_at"], name: "index_procedures_on_hidden_at"
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
describe NewAdministrateur::SourcesParticulierController, type: :controller do
|
||||
let(:admin) { create(:administrateur) }
|
||||
|
||||
before { sign_in(admin.user) }
|
||||
|
||||
describe "#show" do
|
||||
let(:procedure) { create(:procedure, administrateur: admin, api_particulier_scopes: ['cnaf_enfants'], api_particulier_sources: { cnaf: { enfants: ['noms_prenoms'] } }) }
|
||||
|
||||
render_views
|
||||
|
||||
subject { get :show, params: { procedure_id: procedure.id } }
|
||||
|
||||
it 'renders the sources form' do
|
||||
expect(subject.body).to include(I18n.t('api_particulier.providers.cnaf.scopes.enfants.date_de_naissance'))
|
||||
expect(subject.body).to have_selector("input#api_particulier_sources_cnaf_enfants_[value=noms_prenoms][checked=checked]")
|
||||
|
||||
expect(subject.body).to have_selector("input#api_particulier_sources_cnaf_enfants_[value=date_de_naissance]")
|
||||
expect(subject.body).not_to have_selector("input#api_particulier_sources_cnaf_enfants_[value=date_de_naissance][checked=checked]")
|
||||
end
|
||||
end
|
||||
end
|
34
spec/lib/api_particulier/services/sources_service_spec.rb
Normal file
34
spec/lib/api_particulier/services/sources_service_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
describe APIParticulier::Services::SourcesService do
|
||||
describe "#sources" do
|
||||
let(:service) { described_class.new(procedure) }
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:api_particulier_scopes) { [] }
|
||||
let(:api_particulier_sources) { {} }
|
||||
|
||||
before do
|
||||
procedure.update(api_particulier_scopes: api_particulier_scopes)
|
||||
procedure.update(api_particulier_sources: api_particulier_sources)
|
||||
end
|
||||
|
||||
subject { service.available_sources }
|
||||
|
||||
context 'when the procedure doesn’t have any available scopes' do
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
|
||||
context 'when a procedure has a cnaf_allocataires and a cnaf_adresse scopes' do
|
||||
let(:api_particulier_scopes) { ['cnaf_allocataires', 'cnaf_enfants'] }
|
||||
|
||||
let(:cnaf_allocataires_and_enfants) do
|
||||
{
|
||||
'cnaf' => {
|
||||
'allocataires' => ['noms_prenoms', 'date_de_naissance', 'sexe'],
|
||||
'enfants' => ['noms_prenoms', 'date_de_naissance', 'sexe']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to match(cnaf_allocataires_and_enfants) }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue