[API Particulier] (4/4) Support du statut étudiant (#6754)
[API Particulier] (4/4) Support du statut étudiant
This commit is contained in:
commit
818e0472dd
41 changed files with 889 additions and 43 deletions
|
@ -359,7 +359,8 @@
|
|||
|
||||
.cnaf-inputs,
|
||||
.dgfip-inputs,
|
||||
.pole-emploi-inputs {
|
||||
.pole-emploi-inputs,
|
||||
.mesri-inputs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
|
30
app/assets/stylesheets/mesri.scss
Normal file
30
app/assets/stylesheets/mesri.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
@import "constants";
|
||||
@import "colors";
|
||||
|
||||
table.mesri {
|
||||
margin: 2 * $default-padding 0 $default-padding $default-padding;
|
||||
width: 100%;
|
||||
|
||||
caption {
|
||||
font-weight: bold;
|
||||
margin-left: - $default-padding;
|
||||
margin-bottom: $default-spacer;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
font-weight: normal;
|
||||
padding: $default-spacer;
|
||||
}
|
||||
|
||||
th.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
th {
|
||||
border-bottom: 1px solid $grey;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -348,8 +348,8 @@ module Users
|
|||
def champs_params
|
||||
params.permit(dossier: {
|
||||
champs_attributes: [
|
||||
:id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :piece_justificative_file, :departement, :code_departement, value: [],
|
||||
champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :piece_justificative_file, :departement, :code_departement, value: []]
|
||||
:id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :departement, :code_departement, value: [],
|
||||
champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :departement, :code_departement, value: []]
|
||||
]
|
||||
})
|
||||
end
|
||||
|
|
|
@ -1983,6 +1983,11 @@ enum TypeDeChamp {
|
|||
"""
|
||||
linked_drop_down_list
|
||||
|
||||
"""
|
||||
Données du Ministère de l'Enseignement Supérieur, de la Recherche et de l'Innovation
|
||||
"""
|
||||
mesri
|
||||
|
||||
"""
|
||||
Choix multiples
|
||||
"""
|
||||
|
|
|
@ -4,7 +4,8 @@ class APIParticulier::API
|
|||
INTROSPECT_RESOURCE_NAME = "introspect"
|
||||
COMPOSITION_FAMILIALE_RESOURCE_NAME = "v2/composition-familiale"
|
||||
AVIS_IMPOSITION_RESOURCE_NAME = "v2/avis-imposition"
|
||||
SITUATION_POLE_EMPLOI = "v2/situations-pole-emploi"
|
||||
SITUATION_POLE_EMPLOI_RESOURCE_NAME = "v2/situations-pole-emploi"
|
||||
ETUDIANTS_RESOURCE_NAME = "v2/etudiants"
|
||||
|
||||
TIMEOUT = 20
|
||||
|
||||
|
@ -31,7 +32,17 @@ class APIParticulier::API
|
|||
end
|
||||
|
||||
def situation_pole_emploi(identifiant)
|
||||
get(SITUATION_POLE_EMPLOI, identifiant: identifiant)
|
||||
get(SITUATION_POLE_EMPLOI_RESOURCE_NAME, identifiant: identifiant)
|
||||
end
|
||||
|
||||
def etudiants(ine)
|
||||
# NOTE: Paramètres d'appel mutuellement exclusifs,
|
||||
# l'appel par INE est réservé aux acteurs de la sphère de l'enseignement
|
||||
# - INE, l'Identifiant National Étudiant
|
||||
# - état civil, constitué du nom, prénom, date de naissance, sexe et lieu de naissance
|
||||
|
||||
# TODO: ajouter le support de l'état civil
|
||||
get(ETUDIANTS_RESOURCE_NAME, ine: ine)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
48
app/lib/api_particulier/mesri_adapter.rb
Normal file
48
app/lib/api_particulier/mesri_adapter.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
class APIParticulier::MesriAdapter
|
||||
class InvalidSchemaError < ::StandardError
|
||||
def initialize(errors)
|
||||
super(errors.map(&:to_json).join("\n"))
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(api_particulier_token, ine, requested_sources)
|
||||
@api = APIParticulier::API.new(api_particulier_token)
|
||||
@ine = ine
|
||||
@requested_sources = requested_sources
|
||||
end
|
||||
|
||||
def to_params
|
||||
@api.etudiants(@ine)
|
||||
.tap { |d| ensure_valid_schema!(d) }
|
||||
.then { |d| extract_requested_sources(d) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_valid_schema!(data)
|
||||
if !schemer.valid?(data)
|
||||
errors = schemer.validate(data).to_a
|
||||
raise InvalidSchemaError.new(errors)
|
||||
end
|
||||
end
|
||||
|
||||
def schemer
|
||||
@schemer ||= JSONSchemer.schema(Rails.root.join('app/schemas/etudiants.json'))
|
||||
end
|
||||
|
||||
def extract_requested_sources(data)
|
||||
@requested_sources['mesri']&.map do |(scope, sources)|
|
||||
case scope
|
||||
when 'inscriptions'
|
||||
{ scope => data[scope].filter_map { |d| d.slice(*sources) if d.key?('dateDebutInscription') } }
|
||||
when 'admissions'
|
||||
{ scope => data['inscriptions'].filter_map { |d| d.slice(*sources) if d.key?('dateDebutAdmission') } }
|
||||
when 'etablissements'
|
||||
{ scope => data['inscriptions'].map { |d| d['etablissement'].slice(*sources) }.uniq }
|
||||
else
|
||||
{ scope => data.slice(*sources) }
|
||||
end
|
||||
end
|
||||
&.flatten&.reduce(&:deep_merge) || {}
|
||||
end
|
||||
end
|
|
@ -8,6 +8,7 @@ module APIParticulier
|
|||
def available_sources
|
||||
@procedure.api_particulier_scopes
|
||||
.filter_map { |provider_and_scope| raw_scopes[provider_and_scope] }
|
||||
.uniq # remove provider/scope tuples duplicates (e.g. mesri inscriptions)
|
||||
.map { |provider, scope| extract_sources(provider, scope) }
|
||||
.reduce({}) { |acc, el| acc.deep_merge(el) { |_, this_val, other_val| this_val + other_val } }
|
||||
end
|
||||
|
@ -80,7 +81,13 @@ module APIParticulier
|
|||
'pole_emploi_identite' => ['pole_emploi', 'identite'],
|
||||
'pole_emploi_adresse' => ['pole_emploi', 'adresse'],
|
||||
'pole_emploi_contact' => ['pole_emploi', 'contact'],
|
||||
'pole_emploi_inscription' => ['pole_emploi', 'inscription']
|
||||
'pole_emploi_inscription' => ['pole_emploi', 'inscription'],
|
||||
'mesri_identifiant' => ['mesri', 'identifiant'],
|
||||
'mesri_identite' => ['mesri', 'identite'],
|
||||
'mesri_inscription_etudiant' => ['mesri', 'inscriptions'],
|
||||
'mesri_inscription_autre' => ['mesri', 'inscriptions'],
|
||||
'mesri_admission' => ['mesri', 'admissions'],
|
||||
'mesri_etablissements' => ['mesri', 'etablissements']
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -123,6 +130,13 @@ module APIParticulier
|
|||
'adresse' => ['INSEECommune', 'codePostal', 'localite', 'ligneVoie', 'ligneComplementDestinataire', 'ligneComplementAdresse', 'ligneComplementDistribution', 'ligneNom'],
|
||||
'contact' => ['email', 'telephone', 'telephone2'],
|
||||
'inscription' => ['dateInscription', 'dateCessationInscription', 'codeCertificationCNAV', 'codeCategorieInscription', 'libelleCategorieInscription']
|
||||
},
|
||||
'mesri' => {
|
||||
'identifiant' => ['ine'],
|
||||
'identite' => ['nom', 'prenom', 'dateNaissance'],
|
||||
'inscriptions' => ['statut', 'regime', 'dateDebutInscription', 'dateFinInscription', 'codeCommune'],
|
||||
'admissions' => ['statut', 'regime', 'dateDebutAdmission', 'dateFinAdmission', 'codeCommune'],
|
||||
'etablissements' => ['uai', 'nom']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
47
app/models/champs/mesri_champ.rb
Normal file
47
app/models/champs/mesri_champ.rb
Normal file
|
@ -0,0 +1,47 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: champs
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# data :jsonb
|
||||
# fetch_external_data_exceptions :string is an Array
|
||||
# private :boolean default(FALSE), not null
|
||||
# rebased_at :datetime
|
||||
# row :integer
|
||||
# type :string
|
||||
# value :string
|
||||
# value_json :jsonb
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# dossier_id :integer
|
||||
# etablissement_id :integer
|
||||
# external_id :string
|
||||
# parent_id :bigint
|
||||
# type_de_champ_id :integer
|
||||
#
|
||||
class Champs::MesriChamp < Champs::TextChamp
|
||||
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/mesri-input-validation.middleware.ts
|
||||
store_accessor :value_json, :ine
|
||||
|
||||
def blank?
|
||||
external_id.nil?
|
||||
end
|
||||
|
||||
def fetch_external_data?
|
||||
true
|
||||
end
|
||||
|
||||
def fetch_external_data
|
||||
return if !valid?
|
||||
|
||||
APIParticulier::MesriAdapter.new(
|
||||
procedure.api_particulier_token,
|
||||
ine,
|
||||
procedure.api_particulier_sources
|
||||
).to_params
|
||||
end
|
||||
|
||||
def external_id
|
||||
{ ine: ine }.to_json if ine.present?
|
||||
end
|
||||
end
|
|
@ -734,6 +734,10 @@ class Procedure < ApplicationRecord
|
|||
api_particulier_sources['pole_emploi'].present?
|
||||
end
|
||||
|
||||
def mesri_enabled?
|
||||
api_particulier_sources['mesri'].present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_for_publication?
|
||||
|
|
|
@ -52,7 +52,8 @@ class TypeDeChamp < ApplicationRecord
|
|||
annuaire_education: 'annuaire_education',
|
||||
cnaf: 'cnaf',
|
||||
dgfip: 'dgfip',
|
||||
pole_emploi: 'pole_emploi'
|
||||
pole_emploi: 'pole_emploi',
|
||||
mesri: 'mesri'
|
||||
}
|
||||
|
||||
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
|
||||
|
@ -330,6 +331,8 @@ class TypeDeChamp < ApplicationRecord
|
|||
procedure.dgfip_enabled?
|
||||
when TypeDeChamp.type_champs.fetch(:pole_emploi)
|
||||
procedure.pole_emploi_enabled?
|
||||
when TypeDeChamp.type_champs.fetch(:mesri)
|
||||
procedure.mesri_enabled?
|
||||
else
|
||||
true
|
||||
end
|
||||
|
|
2
app/models/types_de_champ/mesri_type_de_champ.rb
Normal file
2
app/models/types_de_champ/mesri_type_de_champ.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
class TypesDeChamp::MesriTypeDeChamp < TypesDeChamp::TextTypeDeChamp
|
||||
end
|
57
app/schemas/etudiants.json
Normal file
57
app/schemas/etudiants.json
Normal file
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://demarches-simplifiees.fr/etudiants.schema.json",
|
||||
"title": "statut étudiant",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ine": {
|
||||
"type": "string"
|
||||
},
|
||||
"nom": {
|
||||
"type": "string"
|
||||
},
|
||||
"prenom": {
|
||||
"type": "string"
|
||||
},
|
||||
"dateNaissance": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
},
|
||||
"inscriptions": {
|
||||
"type": "array",
|
||||
"items" : {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dateDebutInscription": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
},
|
||||
"dateFinInscription": {
|
||||
"format": "date",
|
||||
"type": "string"
|
||||
},
|
||||
"statut": {
|
||||
"enum": ["admis", "inscrit"]
|
||||
},
|
||||
"regime": {
|
||||
"enum": ["formation initiale", "formation continue"]
|
||||
},
|
||||
"codeCommune": {
|
||||
"type": "string"
|
||||
},
|
||||
"etablissement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uai": {
|
||||
"type": "string"
|
||||
},
|
||||
"nom": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,6 @@
|
|||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"$defs": {
|
||||
"adresse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -67,7 +66,6 @@
|
|||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dateInscription": {
|
||||
"format": "date",
|
||||
|
|
11
app/views/shared/champs/mesri/_admissions.html.haml
Normal file
11
app/views/shared/champs/mesri/_admissions.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
%table.mesri
|
||||
%caption #{t("api_particulier.providers.mesri.scopes.#{scope}.libelle")} :
|
||||
- admissions.each do |admission|
|
||||
- admission.slice('statut', 'regime', 'dateDebutAdmission', 'dateFinAdmission', 'codeCommune').keys.each do |key|
|
||||
%tr
|
||||
%th= t("api_particulier.providers.mesri.scopes.#{scope}.#{key}")
|
||||
- case key
|
||||
- when 'dateDebutAdmission', 'dateFinAdmission'
|
||||
%td= try_format_date(Date.strptime(admission[key], "%Y-%m-%d"))
|
||||
- else
|
||||
%td= admission[key]
|
7
app/views/shared/champs/mesri/_etablissements.html.haml
Normal file
7
app/views/shared/champs/mesri/_etablissements.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
%table.mesri
|
||||
%caption #{t("api_particulier.providers.mesri.scopes.#{scope}.libelle")} :
|
||||
- etablissements.each do |etablissement|
|
||||
- etablissement.slice('uai', 'nom').keys.each do |key|
|
||||
%tr
|
||||
%th= t("api_particulier.providers.mesri.scopes.#{scope}.#{key}")
|
||||
%td= etablissement[key]
|
6
app/views/shared/champs/mesri/_identifiant.html.haml
Normal file
6
app/views/shared/champs/mesri/_identifiant.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
%table.mesri
|
||||
%caption #{t("api_particulier.providers.mesri.scopes.#{scope}.libelle")} :
|
||||
- identifiant.slice('ine').keys.each do |key|
|
||||
%tr
|
||||
%th= t("api_particulier.providers.mesri.scopes.#{scope}.#{key}")
|
||||
%td= identifiant[key]
|
10
app/views/shared/champs/mesri/_identite.html.haml
Normal file
10
app/views/shared/champs/mesri/_identite.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
%table.mesri
|
||||
%caption #{t("api_particulier.providers.mesri.scopes.#{scope}.libelle")} :
|
||||
- identite.slice('nom', 'prenom', 'dateNaissance').keys.each do |key|
|
||||
%tr
|
||||
%th= t("api_particulier.providers.mesri.scopes.#{scope}.#{key}")
|
||||
- case key
|
||||
- when 'dateNaissance'
|
||||
%td= try_format_date(Date.strptime(identite[key], "%Y-%m-%d"))
|
||||
- else
|
||||
%td= identite[key]
|
11
app/views/shared/champs/mesri/_inscriptions.html.haml
Normal file
11
app/views/shared/champs/mesri/_inscriptions.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
%table.mesri
|
||||
%caption #{t("api_particulier.providers.mesri.scopes.#{scope}.libelle")} :
|
||||
- inscriptions.each do |inscription|
|
||||
- inscription.slice('statut', 'regime', 'dateDebutInscription', 'dateFinInscription', 'codeCommune').keys.each do |key|
|
||||
%tr
|
||||
%th= t("api_particulier.providers.mesri.scopes.#{scope}.#{key}")
|
||||
- case key
|
||||
- when 'dateDebutInscription', 'dateFinInscription'
|
||||
%td= try_format_date(Date.strptime(inscription[key], "%Y-%m-%d"))
|
||||
- else
|
||||
%td= inscription[key]
|
25
app/views/shared/champs/mesri/_show.html.haml
Normal file
25
app/views/shared/champs/mesri/_show.html.haml
Normal file
|
@ -0,0 +1,25 @@
|
|||
- if champ.blank?
|
||||
%p= t('.not_filled')
|
||||
- elsif champ.data.blank?
|
||||
%p= t('.fetching_data', ine: champ.ine)
|
||||
- else
|
||||
- if profile == 'usager'
|
||||
- sources = champ.procedure.api_particulier_sources['mesri'].keys
|
||||
- i18n_sources = sources.map { |s| I18n.t("#{s}.libelle", scope: 'api_particulier.providers.mesri.scopes') }
|
||||
%p= t('.data_fetched', sources: i18n_sources.to_sentence, ine: champ.ine)
|
||||
|
||||
- if profile == 'instructeur'
|
||||
%p= t('.data_fetched_title')
|
||||
|
||||
- champ.data.slice('identifiant', 'identite', 'inscriptions', 'admissions', 'etablissements').keys.each do |scope|
|
||||
- case scope
|
||||
- when 'identifiant'
|
||||
= render partial: 'shared/champs/mesri/identifiant', locals: { scope: scope, identifiant: champ.data[scope] }
|
||||
- when 'identite'
|
||||
= render partial: 'shared/champs/mesri/identite', locals: { scope: scope, identite: champ.data[scope] }
|
||||
- when 'inscriptions'
|
||||
= render partial: 'shared/champs/mesri/inscriptions', locals: { scope: scope, inscriptions: champ.data[scope] }
|
||||
- when 'admissions'
|
||||
= render partial: 'shared/champs/mesri/admissions', locals: { scope: scope, admissions: champ.data[scope] }
|
||||
- when 'etablissements'
|
||||
= render partial: 'shared/champs/mesri/etablissements', locals: { scope: scope, etablissements: champ.data[scope] }
|
|
@ -42,6 +42,8 @@
|
|||
= render partial: "shared/champs/dgfip/show", locals: { champ: c, profile: profile }
|
||||
- when TypeDeChamp.type_champs.fetch(:pole_emploi)
|
||||
= render partial: "shared/champs/pole_emploi/show", locals: { champ: c, profile: profile }
|
||||
- when TypeDeChamp.type_champs.fetch(:mesri)
|
||||
= render partial: "shared/champs/mesri/show", locals: { champ: c, profile: profile }
|
||||
- when TypeDeChamp.type_champs.fetch(:address)
|
||||
= render partial: "shared/champs/address/show", locals: { champ: c }
|
||||
- when TypeDeChamp.type_champs.fetch(:communes)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.mesri-inputs
|
||||
%div
|
||||
= form.label :ine, t('.ine_label')
|
||||
%p.notice= t('.ine_notice')
|
||||
= form.text_field :ine,
|
||||
required: champ.mandatory?,
|
||||
aria: { describedby: describedby_id(champ) }
|
|
@ -104,3 +104,32 @@ en:
|
|||
codeCertificationCNAV: CNAV certification code
|
||||
codeCategorieInscription: registration category code
|
||||
libelleCategorieInscription: registration category label
|
||||
mesri:
|
||||
libelle: Student status
|
||||
scopes:
|
||||
identifiant:
|
||||
libelle: Identifier
|
||||
ine: INE
|
||||
identite:
|
||||
libelle: Identity
|
||||
nom: last name
|
||||
prenom: first name
|
||||
dateNaissance: date of birth
|
||||
inscriptions:
|
||||
libelle: Registrations
|
||||
statut: status
|
||||
regime: system
|
||||
dateDebutInscription: start date of registration
|
||||
dateFinInscription: end date of registration
|
||||
codeCommune: postal code
|
||||
admissions:
|
||||
libelle: Admissions
|
||||
statut: status
|
||||
regime: system
|
||||
dateDebutAdmission: start date of admission
|
||||
dateFinAdmission: end date of admission
|
||||
codeCommune: postal code
|
||||
etablissements:
|
||||
libelle: Institutions
|
||||
uai: UAI
|
||||
nom: name
|
||||
|
|
|
@ -104,3 +104,32 @@ fr:
|
|||
codeCertificationCNAV: code de certification CNAV
|
||||
codeCategorieInscription: code de catégorie d’inscription
|
||||
libelleCategorieInscription: libellé de catégorie d’inscription
|
||||
mesri:
|
||||
libelle: Statut étudiant
|
||||
scopes:
|
||||
identifiant:
|
||||
libelle: Identifiant
|
||||
ine: INE
|
||||
identite:
|
||||
libelle: Identité
|
||||
nom: nom
|
||||
prenom: prénom
|
||||
dateNaissance: date de naissance
|
||||
inscriptions:
|
||||
libelle: Inscriptions
|
||||
statut: statut
|
||||
regime: régime
|
||||
dateDebutInscription: date de début d'inscription
|
||||
dateFinInscription: date de fin d'inscription
|
||||
codeCommune: code de la commune
|
||||
admissions:
|
||||
libelle: Admissions
|
||||
statut: statut
|
||||
regime: régime
|
||||
dateDebutAdmission: date de début d'admission
|
||||
dateFinAdmission: date de fin d'admission
|
||||
codeCommune: code de la commune
|
||||
etablissements:
|
||||
libelle: Établissements
|
||||
uai: UAI
|
||||
nom: nom
|
||||
|
|
|
@ -421,7 +421,7 @@ fr:
|
|||
jeton_particulier:
|
||||
show:
|
||||
configure_token: "Configurer le jeton API Particulier"
|
||||
api_particulier_description_html: "%{app_name} utilise <a href=\"https://api.gouv.fr/les-api/api-particulier\">API Particulier</a> qui permet d'accéder aux données familiales (CAF), aux données fiscales (DGFiP) et au statut pôle-emploi d'un citoyen.<br />Renseignez ici le <a href=\"https://api.gouv.fr/les-api/api-particulier/demande-acces\">jeton API Particulier</a> propre à votre démarche."
|
||||
api_particulier_description_html: "%{app_name} utilise <a href=\"https://api.gouv.fr/les-api/api-particulier\">API Particulier</a> qui permet d'accéder aux données familiales (CAF), aux données fiscales (DGFiP), au statut pôle-emploi et au statut étudiant d'un citoyen.<br />Renseignez ici le <a href=\"https://api.gouv.fr/les-api/api-particulier/demande-acces\">jeton API Particulier</a> propre à votre démarche."
|
||||
token_description: "Il doit contenir au minimum 15 caractères."
|
||||
update:
|
||||
token_ok: "Le jeton a bien été mis à jour"
|
||||
|
@ -435,7 +435,7 @@ fr:
|
|||
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), aux données fiscales (DGFiP) et au statut pôle-emploi d'un citoyen 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>"
|
||||
explication_html: "<p>API Particulier facilite l’accès des administrations aux données familiales (CAF), aux données fiscales (DGFiP), au statut pôle-emploi et au statut étudiant d'un citoyen 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>"
|
||||
update:
|
||||
sources_ok: 'Mise à jour effectuée'
|
||||
procedures:
|
||||
|
|
|
@ -39,3 +39,4 @@ fr:
|
|||
cnaf: 'Données de la Caisse nationale des allocations familiales'
|
||||
dgfip: 'Données de la Direction générale des Finances publiques'
|
||||
pole_emploi: 'Situation Pôle emploi'
|
||||
mesri: "Données du Ministère de l'Enseignement Supérieur, de la Recherche et de l'Innovation"
|
||||
|
|
|
@ -15,6 +15,9 @@ en:
|
|||
pole_emploi:
|
||||
identifiant_label: Identifier
|
||||
identifiant_notice: It is usually composed of alphanumeric characters.
|
||||
mesri:
|
||||
ine_label: INE
|
||||
ine_notice: Student National Number. It is usually composed of alphanumeric characters.
|
||||
header:
|
||||
expires_at:
|
||||
brouillon: "Expires at %{date} (%{duree_conservation_totale} months after the creation of this file)"
|
||||
|
@ -42,3 +45,9 @@ en:
|
|||
fetching_data: "Fetching data for identifier %{identifiant}."
|
||||
data_fetched: "Data concerning %{sources} linked to the identifier %{identifiant} has been received from Pôle emploi."
|
||||
data_fetched_title: "Data received from Pôle emploi"
|
||||
mesri:
|
||||
show:
|
||||
not_filled: not filled
|
||||
fetching_data: "Fetching data for INE %{ine}."
|
||||
data_fetched: "Data concerning %{sources} linked to the INE %{ine} has been received from the MESRI."
|
||||
data_fetched_title: "Data received from the MESRI"
|
||||
|
|
|
@ -15,6 +15,9 @@ fr:
|
|||
pole_emploi:
|
||||
identifiant_label: Identifiant
|
||||
identifiant_notice: Il est généralement composé de caractères alphanumériques.
|
||||
mesri:
|
||||
ine_label: INE
|
||||
ine_notice: Identifiant National Étudiant. Il est généralement composé de caractères alphanumériques.
|
||||
header:
|
||||
expires_at:
|
||||
brouillon: "Expirera le %{date} (%{duree_conservation_totale} mois après la création du dossier)"
|
||||
|
@ -44,3 +47,9 @@ fr:
|
|||
fetching_data: "La récupération automatique des données pour l'identifiant %{identifiant} est en cours."
|
||||
data_fetched: "Des données concernant %{sources} liées à l'identifiant %{identifiant} ont été reçues depuis Pôle emploi."
|
||||
data_fetched_title: "Données obtenues de Pôle emploi"
|
||||
mesri:
|
||||
show:
|
||||
not_filled: non renseigné
|
||||
fetching_data: "La récupération automatique des données pour l'INE %{ine} et en cours."
|
||||
data_fetched: "Des données concernant %{sources} liées à l'INE %{ine} ont été reçues depuis le MESRI."
|
||||
data_fetched_title: "Données obtenues du MESRI"
|
||||
|
|
|
@ -79,7 +79,13 @@ describe Administrateurs::JetonParticulierController, type: :controller do
|
|||
'pole_emploi_identite',
|
||||
'pole_emploi_adresse',
|
||||
'pole_emploi_contact',
|
||||
'pole_emploi_inscription'
|
||||
'pole_emploi_inscription',
|
||||
'mesri_identifiant',
|
||||
'mesri_identite',
|
||||
'mesri_inscription_etudiant',
|
||||
'mesri_inscription_autre',
|
||||
'mesri_admission',
|
||||
'mesri_etablissements'
|
||||
)
|
||||
expect(procedure.api_particulier_sources).to be_empty
|
||||
end
|
||||
|
|
|
@ -197,6 +197,10 @@ FactoryBot.define do
|
|||
type_de_champ { association :type_de_champ_pole_emploi, procedure: dossier.procedure }
|
||||
end
|
||||
|
||||
factory :champ_mesri, class: 'Champs::MesriChamp' do
|
||||
type_de_champ { association :type_de_champ_mesri, procedure: dossier.procedure }
|
||||
end
|
||||
|
||||
factory :champ_siret, class: 'Champs::SiretChamp' do
|
||||
type_de_champ { association :type_de_champ_siret, procedure: dossier.procedure }
|
||||
association :etablissement, factory: [:etablissement]
|
||||
|
|
|
@ -216,6 +216,12 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
trait :with_mesri do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
build(:type_de_champ_mesri, procedure: procedure)
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_explication do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
build(:type_de_champ_explication, procedure: procedure)
|
||||
|
|
|
@ -163,6 +163,9 @@ FactoryBot.define do
|
|||
factory :type_de_champ_pole_emploi do
|
||||
type_champ { TypeDeChamp.type_champs.fetch(:pole_emploi) }
|
||||
end
|
||||
factory :type_de_champ_mesri do
|
||||
type_champ { TypeDeChamp.type_champs.fetch(:mesri) }
|
||||
end
|
||||
factory :type_de_champ_carte do
|
||||
type_champ { TypeDeChamp.type_champs.fetch(:carte) }
|
||||
end
|
||||
|
|
83
spec/fixtures/cassettes/api_particulier/success/etudiants.yml
vendored
Normal file
83
spec/fixtures/cassettes/api_particulier/success/etudiants.yml
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://particulier.api.gouv.fr/api/v2/etudiants?ine=090601811AB
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- demarches-simplifiees.fr
|
||||
Accept:
|
||||
- application/json
|
||||
X-Api-Key:
|
||||
- c6d23f3900b8fb4b3586c4804c051af79062f54b
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Tue, 16 Mar 2021 17:01:19 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '805'
|
||||
Connection:
|
||||
- keep-alive
|
||||
Keep-Alive:
|
||||
- timeout=5
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Expose-Headers:
|
||||
- Range,Content-Range,X-Content-Range,X-API-Key
|
||||
Etag:
|
||||
- W/"2eb-A0NiRd+gbJKIAT0y4tR4j9tjXb0"
|
||||
Server:
|
||||
- nginx
|
||||
Strict-Transport-Security:
|
||||
- max-age=15552000
|
||||
- max-age=15552000
|
||||
Vary:
|
||||
- Origin, Accept
|
||||
X-Gravitee-Request-Id:
|
||||
- 7bfb7f99-ac2d-4443-bb7f-99ac2d0443c5
|
||||
X-Gravitee-Transaction-Id:
|
||||
- f5dca8b3-2ab7-4c9a-9ca8-b32ab70c9a2b
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{
|
||||
"ine": "090601811AB",
|
||||
"nom": "DUBOIS",
|
||||
"prenom": "Angela Claire Louise",
|
||||
"dateNaissance": "1962-08-24",
|
||||
"inscriptions": [
|
||||
{
|
||||
"statut": "admis",
|
||||
"regime": "formation continue",
|
||||
"dateDebutAdmission": "2021-09-01T00:00:00.000Z",
|
||||
"dateFinAdmission": "2022-08-31T00:00:00.000Z",
|
||||
"etablissement": {
|
||||
"uai": "0751722P",
|
||||
"nom": "Université Pierre et Marie Curie - UPCM (Paris 6)"
|
||||
},
|
||||
"codeCommune": "75106"
|
||||
},
|
||||
{
|
||||
"statut": "inscrit",
|
||||
"regime": "formation continue",
|
||||
"dateDebutInscription": "2022-09-01",
|
||||
"dateFinInscription": "2023-08-31",
|
||||
"etablissement": {
|
||||
"uai": "0751722P",
|
||||
"nom": "Université Pierre et Marie Curie - UPCM (Paris 6)"
|
||||
},
|
||||
"codeCommune": "75106"
|
||||
}
|
||||
]
|
||||
}'
|
||||
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
|
||||
recorded_with: VCR 6.0.0
|
83
spec/fixtures/cassettes/api_particulier/success/etudiants_invalid.yml
vendored
Normal file
83
spec/fixtures/cassettes/api_particulier/success/etudiants_invalid.yml
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://particulier.api.gouv.fr/api/v2/etudiants?ine=090601811AB
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- demarches-simplifiees.fr
|
||||
Accept:
|
||||
- application/json
|
||||
X-Api-Key:
|
||||
- c6d23f3900b8fb4b3586c4804c051af79062f54b
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
headers:
|
||||
Date:
|
||||
- Tue, 16 Mar 2021 17:01:19 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '806'
|
||||
Connection:
|
||||
- keep-alive
|
||||
Keep-Alive:
|
||||
- timeout=5
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Expose-Headers:
|
||||
- Range,Content-Range,X-Content-Range,X-API-Key
|
||||
Etag:
|
||||
- W/"2eb-A0NiRd+gbJKIAT0y4tR4j9tjXb0"
|
||||
Server:
|
||||
- nginx
|
||||
Strict-Transport-Security:
|
||||
- max-age=15552000
|
||||
- max-age=15552000
|
||||
Vary:
|
||||
- Origin, Accept
|
||||
X-Gravitee-Request-Id:
|
||||
- 7bfb7f99-ac2d-4443-bb7f-99ac2d0443c5
|
||||
X-Gravitee-Transaction-Id:
|
||||
- f5dca8b3-2ab7-4c9a-9ca8-b32ab70c9a2b
|
||||
body:
|
||||
encoding: ASCII-8BIT
|
||||
string: '{
|
||||
"ine": "090601811AB",
|
||||
"nom": "DUBOIS",
|
||||
"prenom": "Angela Claire Louise",
|
||||
"dateNaissance": "1962-08-24",
|
||||
"inscriptions": [
|
||||
{
|
||||
"statut": "absent",
|
||||
"regime": "formation continue",
|
||||
"dateDebutAdmission": "2021-09-01T00:00:00.000Z",
|
||||
"dateFinAdmission": "2022-08-31T00:00:00.000Z",
|
||||
"etablissement": {
|
||||
"uai": "0751722P",
|
||||
"nom": "Université Pierre et Marie Curie - UPCM (Paris 6)"
|
||||
},
|
||||
"codeCommune": "75106"
|
||||
},
|
||||
{
|
||||
"statut": "inscrit",
|
||||
"regime": "formation continue",
|
||||
"dateDebutInscription": "2022-09-01",
|
||||
"dateFinInscription": "2023-08-31",
|
||||
"etablissement": {
|
||||
"uai": "0751722P",
|
||||
"nom": "Université Pierre et Marie Curie - UPCM (Paris 6)"
|
||||
},
|
||||
"codeCommune": "75106"
|
||||
}
|
||||
]
|
||||
}'
|
||||
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
|
||||
recorded_with: VCR 6.0.0
|
|
@ -25,7 +25,7 @@ http_interactions:
|
|||
Content-Type:
|
||||
- application/json
|
||||
Content-Length:
|
||||
- '257'
|
||||
- '1068'
|
||||
Connection:
|
||||
- keep-alive
|
||||
Keep-Alive:
|
||||
|
@ -38,6 +38,6 @@ http_interactions:
|
|||
- max-age=15552000
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '{"_id":"1d99db5a-a099-4314-ad2f-2707c6b505a6","name":"Application de sandbox","scopes":["cnaf_allocataires","cnaf_enfants","cnaf_adresse","cnaf_quotient_familial","dgfip_declarant1_nom","dgfip_declarant1_nom_naissance","dgfip_declarant1_prenoms","dgfip_declarant1_date_naissance","dgfip_declarant2_nom","dgfip_declarant2_nom_naissance","dgfip_declarant2_prenoms","dgfip_declarant2_date_naissance","dgfip_date_recouvrement","dgfip_date_etablissement","dgfip_adresse_fiscale_taxation","dgfip_adresse_fiscale_annee","dgfip_nombre_parts","dgfip_nombre_personnes_a_charge","dgfip_situation_familiale","dgfip_revenu_brut_global","dgfip_revenu_imposable","dgfip_impot_revenu_net_avant_corrections","dgfip_montant_impot","dgfip_revenu_fiscal_reference","dgfip_annee_impot","dgfip_annee_revenus","dgfip_erreur_correctif","dgfip_situation_partielle", "pole_emploi_identite","pole_emploi_adresse","pole_emploi_contact","pole_emploi_inscription"]}'
|
||||
string: '{"_id":"1d99db5a-a099-4314-ad2f-2707c6b505a6","name":"Application de sandbox","scopes":["cnaf_allocataires","cnaf_enfants","cnaf_adresse","cnaf_quotient_familial","dgfip_declarant1_nom","dgfip_declarant1_nom_naissance","dgfip_declarant1_prenoms","dgfip_declarant1_date_naissance","dgfip_declarant2_nom","dgfip_declarant2_nom_naissance","dgfip_declarant2_prenoms","dgfip_declarant2_date_naissance","dgfip_date_recouvrement","dgfip_date_etablissement","dgfip_adresse_fiscale_taxation","dgfip_adresse_fiscale_annee","dgfip_nombre_parts","dgfip_nombre_personnes_a_charge","dgfip_situation_familiale","dgfip_revenu_brut_global","dgfip_revenu_imposable","dgfip_impot_revenu_net_avant_corrections","dgfip_montant_impot","dgfip_revenu_fiscal_reference","dgfip_annee_impot","dgfip_annee_revenus","dgfip_erreur_correctif","dgfip_situation_partielle", "pole_emploi_identite","pole_emploi_adresse","pole_emploi_contact","pole_emploi_inscription","mesri_identifiant","mesri_identite","mesri_inscription_etudiant","mesri_inscription_autre","mesri_admission","mesri_etablissements"]}'
|
||||
recorded_at: Tue, 16 Mar 2021 15:25:24 GMT
|
||||
recorded_with: VCR 6.0.0
|
||||
|
|
34
spec/fixtures/files/api_particulier/etudiants.json
vendored
Normal file
34
spec/fixtures/files/api_particulier/etudiants.json
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"identifiant": {
|
||||
"ine": "090601811AB"
|
||||
},
|
||||
"identite": {
|
||||
"nom": "DUBOIS",
|
||||
"prenom": "Angela Claire Louise",
|
||||
"dateNaissance": "1962-08-24"
|
||||
},
|
||||
"admissions": [
|
||||
{
|
||||
"statut": "admis",
|
||||
"regime": "formation continue",
|
||||
"dateDebutAdmission": "2021-09-01T00:00:00.000Z",
|
||||
"dateFinAdmission": "2022-08-31T00:00:00.000Z",
|
||||
"codeCommune": "75106"
|
||||
}
|
||||
],
|
||||
"inscriptions": [
|
||||
{
|
||||
"statut": "inscrit",
|
||||
"regime": "formation continue",
|
||||
"dateDebutInscription": "2022-09-01",
|
||||
"dateFinInscription": "2023-08-31",
|
||||
"codeCommune": "75106"
|
||||
}
|
||||
],
|
||||
"etablissements": [
|
||||
{
|
||||
"uai": "0751722P",
|
||||
"nom": "Université Pierre et Marie Curie - UPCM (Paris 6)"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -41,7 +41,13 @@ describe APIParticulier::API do
|
|||
'pole_emploi_identite',
|
||||
'pole_emploi_adresse',
|
||||
'pole_emploi_contact',
|
||||
'pole_emploi_inscription'
|
||||
'pole_emploi_inscription',
|
||||
'mesri_identifiant',
|
||||
'mesri_identite',
|
||||
'mesri_inscription_etudiant',
|
||||
'mesri_inscription_autre',
|
||||
'mesri_admission',
|
||||
'mesri_etablissements'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
70
spec/lib/api_particulier/mesri_adapter_spec.rb
Normal file
70
spec/lib/api_particulier/mesri_adapter_spec.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
describe APIParticulier::MesriAdapter do
|
||||
let(:adapter) { described_class.new(api_particulier_token, ine, requested_sources) }
|
||||
|
||||
before { stub_const('API_PARTICULIER_URL', 'https://particulier.api.gouv.fr/api') }
|
||||
|
||||
describe '#to_params' do
|
||||
let(:api_particulier_token) { 'c6d23f3900b8fb4b3586c4804c051af79062f54b' }
|
||||
let(:ine) { '090601811AB' }
|
||||
|
||||
subject { VCR.use_cassette(cassette) { adapter.to_params } }
|
||||
|
||||
context 'when the api answer is valid' do
|
||||
let(:cassette) { 'api_particulier/success/etudiants' }
|
||||
|
||||
context 'when the token has all the MESRI scopes' do
|
||||
context 'and all the sources are requested' do
|
||||
let(:requested_sources) do
|
||||
{
|
||||
'mesri' => {
|
||||
'identifiant' => ['ine'],
|
||||
'identite' => ['nom', 'prenom', 'dateNaissance'],
|
||||
'inscriptions' => ['statut', 'regime', 'dateDebutInscription', 'dateFinInscription', 'codeCommune'],
|
||||
'admissions' => ['statut', 'regime', 'dateDebutAdmission', 'dateFinAdmission', 'codeCommune'],
|
||||
'etablissements' => ['uai', 'nom']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:result) { JSON.parse(File.read('spec/fixtures/files/api_particulier/etudiants.json')) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
|
||||
context 'when no sources is requested' do
|
||||
let(:requested_sources) { {} }
|
||||
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
|
||||
context 'when an admission statut is requested' do
|
||||
let(:requested_sources) { { 'mesri' => { 'admissions' => ['statut'] } } }
|
||||
|
||||
it { is_expected.to eq('admissions' => [{ 'statut' => 'admis' }]) }
|
||||
end
|
||||
|
||||
context 'when an inscription statut is requested' do
|
||||
let(:requested_sources) { { 'mesri' => { 'inscriptions' => ['statut'] } } }
|
||||
|
||||
it { is_expected.to eq('inscriptions' => [{ 'statut' => 'inscrit' }]) }
|
||||
end
|
||||
|
||||
context 'when a first name is requested' do
|
||||
let(:requested_sources) { { 'mesri' => { 'identite' => ['prenom'] } } }
|
||||
|
||||
it { is_expected.to eq('identite' => { 'prenom' => 'Angela Claire Louise' }) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the api answer is invalid' do
|
||||
let(:cassette) { 'api_particulier/success/etudiants_invalid' }
|
||||
|
||||
context 'when no sources is requested' do
|
||||
let(:requested_sources) { {} }
|
||||
|
||||
it { expect { subject }.to raise_error(APIParticulier::MesriAdapter::InvalidSchemaError) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -62,6 +62,21 @@ describe APIParticulier::Services::SourcesService do
|
|||
it { is_expected.to match(pole_emploi_identite_et_adresse) }
|
||||
end
|
||||
|
||||
context 'when a procedure has a mesri_identite and a mesri_etablissements scopes' do
|
||||
let(:api_particulier_scopes) { ['mesri_identite', 'mesri_etablissements'] }
|
||||
|
||||
let(:mesri_identite_and_etablissements) do
|
||||
{
|
||||
'mesri' => {
|
||||
'identite' => ['nom', 'prenom', 'dateNaissance'],
|
||||
'etablissements' => ['uai', 'nom']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to match(mesri_identite_and_etablissements) }
|
||||
end
|
||||
|
||||
context 'when a procedure has an unknown scope' do
|
||||
let(:api_particulier_scopes) { ['unknown_scope'] }
|
||||
|
||||
|
|
56
spec/models/champs/mesri_champ_spec.rb
Normal file
56
spec/models/champs/mesri_champ_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
describe Champs::MesriChamp, type: :model do
|
||||
let(:champ) { described_class.new }
|
||||
|
||||
describe 'INE' do
|
||||
before do
|
||||
champ.ine = '090601811AB'
|
||||
end
|
||||
|
||||
it 'saves INE' do
|
||||
expect(champ.ine).to eq('090601811AB')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'external_id' do
|
||||
context 'when no data is given' do
|
||||
before do
|
||||
champ.ine = ''
|
||||
champ.save
|
||||
end
|
||||
|
||||
it { expect(champ.external_id).to be_nil }
|
||||
end
|
||||
|
||||
context 'when all data required for an external fetch are given' do
|
||||
before do
|
||||
champ.ine = '090601811AB'
|
||||
champ.save
|
||||
end
|
||||
|
||||
it { expect(JSON.parse(champ.external_id)).to eq("ine" => "090601811AB") }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#validate' do
|
||||
let(:champ) { described_class.new(dossier: create(:dossier), type_de_champ: create(:type_de_champ_mesri)) }
|
||||
let(:validation_context) { :create }
|
||||
|
||||
subject { champ.valid?(validation_context) }
|
||||
|
||||
before do
|
||||
champ.ine = ine
|
||||
end
|
||||
|
||||
context 'when INE is valid' do
|
||||
let(:ine) { '090601811AB' }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'when INE is nil' do
|
||||
let(:ine) { nil }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -80,6 +80,7 @@ describe ProcedureExportService do
|
|||
"cnaf",
|
||||
"dgfip",
|
||||
"pole_emploi",
|
||||
"mesri",
|
||||
"text"
|
||||
]
|
||||
end
|
||||
|
@ -170,6 +171,7 @@ describe ProcedureExportService do
|
|||
"cnaf",
|
||||
"dgfip",
|
||||
"pole_emploi",
|
||||
"mesri",
|
||||
"text"
|
||||
]
|
||||
end
|
||||
|
@ -256,6 +258,7 @@ describe ProcedureExportService do
|
|||
"cnaf",
|
||||
"dgfip",
|
||||
"pole_emploi",
|
||||
"mesri",
|
||||
"text"
|
||||
]
|
||||
end
|
||||
|
|
|
@ -26,6 +26,13 @@ describe 'fetch API Particulier Data', js: true do
|
|||
'adresse' => ['INSEECommune', 'codePostal', 'localite', 'ligneVoie', 'ligneComplementDestinataire', 'ligneComplementAdresse', 'ligneComplementDistribution', 'ligneNom'],
|
||||
'contact' => ['email', 'telephone', 'telephone2'],
|
||||
'inscription' => ['dateInscription', 'dateCessationInscription', 'codeCertificationCNAV', 'codeCategorieInscription', 'libelleCategorieInscription']
|
||||
},
|
||||
'mesri' => {
|
||||
'identifiant' => ['ine'],
|
||||
'identite' => ['nom', 'prenom', 'dateNaissance'],
|
||||
'inscriptions' => ['statut', 'regime', 'dateDebutInscription', 'dateFinInscription', 'codeCommune'],
|
||||
'admissions' => ['statut', 'regime', 'dateDebutAdmission', 'dateFinAdmission', 'codeCommune'],
|
||||
'etablissements' => ['uai', 'nom']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -158,6 +165,37 @@ describe 'fetch API Particulier Data', js: true do
|
|||
check("libellé de catégorie d’inscription")
|
||||
end
|
||||
|
||||
within('#mesri-identifiant') do
|
||||
check('INE')
|
||||
end
|
||||
|
||||
within('#mesri-identite') do
|
||||
check('nom')
|
||||
check('prénom')
|
||||
check('date de naissance')
|
||||
end
|
||||
|
||||
within('#mesri-inscriptions') do
|
||||
check('statut')
|
||||
check('régime')
|
||||
check("date de début d'inscription")
|
||||
check("date de fin d'inscription")
|
||||
check("code de la commune")
|
||||
end
|
||||
|
||||
within('#mesri-admissions') do
|
||||
check('statut')
|
||||
check('régime')
|
||||
check("date de début d'admission")
|
||||
check("date de fin d'admission")
|
||||
check("code de la commune")
|
||||
end
|
||||
|
||||
within('#mesri-etablissements') do
|
||||
check('UAI')
|
||||
check('nom')
|
||||
end
|
||||
|
||||
click_on 'Enregistrer'
|
||||
|
||||
within('#cnaf-enfants') do
|
||||
|
@ -166,10 +204,11 @@ describe 'fetch API Particulier Data', js: true do
|
|||
|
||||
procedure.reload
|
||||
|
||||
expect(procedure.api_particulier_sources.keys).to contain_exactly('cnaf', 'dgfip', 'pole_emploi')
|
||||
expect(procedure.api_particulier_sources.keys).to contain_exactly('cnaf', 'dgfip', 'pole_emploi', 'mesri')
|
||||
expect(procedure.api_particulier_sources['cnaf'].keys).to contain_exactly('adresse', 'allocataires', 'enfants', 'quotient_familial')
|
||||
expect(procedure.api_particulier_sources['dgfip'].keys).to contain_exactly('declarant1', 'declarant2', 'echeance_avis', 'foyer_fiscal', 'agregats_fiscaux', 'complements')
|
||||
expect(procedure.api_particulier_sources['pole_emploi'].keys).to contain_exactly('identite', 'adresse', 'contact', 'inscription')
|
||||
expect(procedure.api_particulier_sources['mesri'].keys).to contain_exactly('identifiant', 'identite', 'inscriptions', 'admissions', 'etablissements')
|
||||
|
||||
procedure.api_particulier_sources.each do |provider, scopes|
|
||||
scopes.each do |scope, fields|
|
||||
|
@ -203,10 +242,11 @@ describe 'fetch API Particulier Data', js: true do
|
|||
let(:reference_avis) { '2097699999077' }
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:identifiant) { 'georges_moustaki_77' }
|
||||
let(:ine) { '090601811AB' }
|
||||
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
|
||||
|
||||
let(:procedure) do
|
||||
create(:procedure, :for_individual, :with_service, :with_cnaf, :with_dgfip, :with_pole_emploi, :published,
|
||||
create(:procedure, :for_individual, :with_service, :with_cnaf, :with_dgfip, :with_pole_emploi, :with_mesri, :published,
|
||||
libelle: 'libellé de la procédure',
|
||||
path: 'libelle-de-la-procedure',
|
||||
instructeurs: [instructeur],
|
||||
|
@ -336,6 +376,67 @@ describe 'fetch API Particulier Data', js: true do
|
|||
end
|
||||
end
|
||||
|
||||
context 'MESRI' do
|
||||
let(:api_particulier_token) { 'c6d23f3900b8fb4b3586c4804c051af79062f54b' }
|
||||
|
||||
scenario 'it can fill a MESRI field' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Commencer la démarche'
|
||||
|
||||
choose 'Madame'
|
||||
fill_in 'individual_nom', with: 'Dubois'
|
||||
fill_in 'individual_prenom', with: 'Angela Claire Louise'
|
||||
|
||||
click_button('Continuer')
|
||||
|
||||
fill_in "INE", with: 'wrong code'
|
||||
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||
|
||||
dossier = Dossier.last
|
||||
mesri_champ = dossier.champs.fourth
|
||||
|
||||
expect(mesri_champ.ine).to eq('wrong code')
|
||||
|
||||
fill_in "INE", with: ine
|
||||
|
||||
VCR.use_cassette('api_particulier/success/etudiants') do
|
||||
perform_enqueued_jobs { click_on 'Déposer le dossier' }
|
||||
end
|
||||
|
||||
visit demande_dossier_path(dossier)
|
||||
expect(page).to have_content(/Des données.*ont été reçues depuis le MESRI/)
|
||||
|
||||
log_out
|
||||
|
||||
login_as instructeur.user, scope: :user
|
||||
|
||||
visit instructeur_dossier_path(procedure, dossier)
|
||||
|
||||
expect(page).to have_content('INE 090601811AB')
|
||||
|
||||
expect(page).to have_content('nom DUBOIS')
|
||||
expect(page).to have_content('prénom Angela Claire Louise')
|
||||
expect(page).to have_content('date de naissance 24 août 1962')
|
||||
|
||||
expect(page).to have_content('statut inscrit')
|
||||
expect(page).to have_content('régime formation continue')
|
||||
expect(page).to have_content("date de début d'inscription 1 septembre 2022")
|
||||
expect(page).to have_content("date de fin d'inscription 31 août 2023")
|
||||
expect(page).to have_content('code de la commune 75106')
|
||||
|
||||
expect(page).to have_content('statut admis')
|
||||
expect(page).to have_content('régime formation continue')
|
||||
expect(page).to have_content("date de début d'admission 1 septembre 2021")
|
||||
expect(page).to have_content("date de fin d'admission 31 août 2022")
|
||||
expect(page).to have_content('code de la commune 75106')
|
||||
|
||||
expect(page).to have_content('UAI 0751722P')
|
||||
expect(page).to have_content('nom Université Pierre et Marie Curie - UPCM (Paris 6)')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'it can fill a DGFiP field' do
|
||||
visit commencer_path(path: procedure.path)
|
||||
click_on 'Commencer la démarche'
|
||||
|
|
Loading…
Reference in a new issue