feat(api particulier): add Pole Emploi adapter

This commit is contained in:
François Vantomme 2021-11-30 15:43:47 +01:00 committed by simon lehericey
parent 2e05a3fde2
commit 4cfc9f7d86
7 changed files with 382 additions and 0 deletions

View file

@ -4,6 +4,7 @@ class APIParticulier::API
INTROSPECT_RESOURCE_NAME = "introspect" INTROSPECT_RESOURCE_NAME = "introspect"
COMPOSITION_FAMILIALE_RESOURCE_NAME = "v2/composition-familiale" COMPOSITION_FAMILIALE_RESOURCE_NAME = "v2/composition-familiale"
AVIS_IMPOSITION_RESOURCE_NAME = "v2/avis-imposition" AVIS_IMPOSITION_RESOURCE_NAME = "v2/avis-imposition"
SITUATION_POLE_EMPLOI = "v2/situations-pole-emploi"
TIMEOUT = 20 TIMEOUT = 20
@ -29,6 +30,10 @@ class APIParticulier::API
referenceAvis: reference_avis.to_i.to_s.rjust(13, "0")) referenceAvis: reference_avis.to_i.to_s.rjust(13, "0"))
end end
def situation_pole_emploi(identifiant)
get(SITUATION_POLE_EMPLOI, identifiant: identifiant)
end
private private
def get(resource_name, params = {}) def get(resource_name, params = {})

View file

@ -0,0 +1,46 @@
class APIParticulier::PoleEmploiAdapter
class InvalidSchemaError < ::StandardError
def initialize(errors)
super(errors.map(&:to_json).join("\n"))
end
end
def initialize(api_particulier_token, identifiant, requested_sources)
@api = APIParticulier::API.new(api_particulier_token)
@identifiant = identifiant
@requested_sources = requested_sources
end
def to_params
@api.situation_pole_emploi(@identifiant)
.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/situation-pole-emploi.json'))
end
def extract_requested_sources(data)
@requested_sources['pole_emploi']&.map do |(scope, sources)|
case scope
when 'adresse'
sources.map { |source| { scope => data[scope].slice(*source) } }
when 'identifiant', 'contact', 'inscription'
sources.map { |source| { scope => data.slice(*source) } }
else
{ scope => data.slice(*sources) }
end
end
&.flatten&.reduce(&:deep_merge) || {}
end
end

View file

@ -0,0 +1,87 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://demarches-simplifiees.fr/situation-pole-emploi.schema.json",
"title": "situation pole emploi",
"type": "object",
"properties": {
"identifiant": {
"type": "string"
},
"civilite": {
"type": "string"
},
"nom": {
"type": "string"
},
"nomUsage": {
"type": "string"
},
"prenom": {
"type": "string"
},
"sexe": {
"enum": ["F", "M"]
},
"dateNaissance": {
"format": "date",
"type": "string"
},
"codeCertificationCNAV": {
"type": "string"
},
"telephone": {
"type": "string"
},
"telephone2": {
"type": "string"
},
"email": {
"type": "string"
},
"$defs": {
"adresse": {
"type": "object",
"properties": {
"codePostal": {
"type": "string"
},
"INSEECommune": {
"type": "string"
},
"localite": {
"type": "string"
},
"ligneVoie": {
"type": "string"
},
"ligneComplementDestinataire": {
"type": "string"
},
"ligneComplementAdresse": {
"type": "string"
},
"ligneComplementDistribution": {
"type": "string"
},
"ligneNom": {
"type": "string"
}
}
}
},
"dateInscription": {
"format": "date",
"type": "string"
},
"dateCessationInscription": {
"format": "date",
"type": "string"
},
"codeCategorieInscription": {
"type": "integer"
},
"libelleCategroiieInscription": {
"type": "string"
}
}
}

View file

@ -0,0 +1,76 @@
---
http_interactions:
- request:
method: get
uri: https://particulier.api.gouv.fr/api/v2/situations-pole-emploi?identifiant=georges_moustaki_77
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- demarches-simplifiees.fr
Accept:
- application/json
X-Api-Key:
- 06fd8675601267d2988cbbdef56ecb0de1d45223
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:
- '651'
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: '{
"identifiant": "georges_moustaki_77",
"civilite": "M.",
"nom": "Moustaki",
"nomUsage": "Moustaki",
"prenom": "Georges",
"sexe": "M",
"dateNaissance": "1934-05-03",
"adresse": {
"INSEECommune": "75118",
"codePostal": "75018",
"localite": "75018 Paris",
"ligneVoie": "3 rue des Huttes",
"ligneNom": "MOUSTAKI"
},
"email": "georges@moustaki.fr",
"telephone": "0629212921",
"dateInscription": "1965-05-03",
"dateCessationInscription": "1966-05-03",
"codeCertificationCNAV": "VC",
"codeCategorieInscription": 1,
"libelleCategorieInscription": "PERSONNE SANS EMPLOI DISPONIBLE DUREE INDETERMINEE PLEIN TPS"
}'
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,76 @@
---
http_interactions:
- request:
method: get
uri: https://particulier.api.gouv.fr/api/v2/situations-pole-emploi?identifiant=georges_moustaki_77
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- demarches-simplifiees.fr
Accept:
- application/json
X-Api-Key:
- 06fd8675601267d2988cbbdef56ecb0de1d45223
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:
- '747'
Connection:
- keep-alive
Keep-Alive:
- timeout=5
Access-Control-Allow-Credentials:
- '651'
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: '{
"identifiant": "georges_moustaki_77",
"civilite": "M.",
"nom": "Moustaki",
"nomUsage": "Moustaki",
"prenom": "Georges",
"sexe": "X",
"dateNaissance": "1934-05-03",
"adresse": {
"INSEECommune": "75118",
"codePostal": "75018",
"localite": "75018 Paris",
"ligneVoie": "3 rue des Huttes",
"ligneNom": "MOUSTAKI"
},
"email": "georges@moustaki.fr",
"telephone": "0629212921",
"dateInscription": "1965-05-03",
"dateCessationInscription": "1966-05-03",
"codeCertificationCNAV": "VC",
"codeCategorieInscription": 1,
"libelleCategorieInscription": "PERSONNE SANS EMPLOI DISPONIBLE DUREE INDETERMINEE PLEIN TPS"
}'
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,29 @@
{
"identite": {
"identifiant": "georges_moustaki_77",
"civilite": "M.",
"nom": "Moustaki",
"nomUsage": "Moustaki",
"prenom": "Georges",
"sexe": "M",
"dateNaissance": "1934-05-03"
},
"adresse": {
"INSEECommune": "75118",
"codePostal": "75018",
"localite": "75018 Paris",
"ligneVoie": "3 rue des Huttes",
"ligneNom": "MOUSTAKI"
},
"contact": {
"email": "georges@moustaki.fr",
"telephone": "0629212921"
},
"inscription": {
"dateInscription": "1965-05-03",
"dateCessationInscription": "1966-05-03",
"codeCertificationCNAV": "VC",
"codeCategorieInscription": 1,
"libelleCategorieInscription": "PERSONNE SANS EMPLOI DISPONIBLE DUREE INDETERMINEE PLEIN TPS"
}
}

View file

@ -0,0 +1,63 @@
describe APIParticulier::PoleEmploiAdapter do
let(:adapter) { described_class.new(api_particulier_token, identifiant, requested_sources) }
before { stub_const('API_PARTICULIER_URL', 'https://particulier.api.gouv.fr/api') }
describe '#to_params' do
let(:api_particulier_token) { '06fd8675601267d2988cbbdef56ecb0de1d45223' }
let(:identifiant) { 'georges_moustaki_77' }
subject { VCR.use_cassette(cassette) { adapter.to_params } }
context 'when the api answer is valid' do
let(:cassette) { 'api_particulier/success/situation_pole_emploi' }
context 'when the token has all the pole emploi scopes' do
context 'and all the sources are requested' do
let(:requested_sources) do
{
'pole_emploi' => {
'identite' => ['identifiant', 'civilite', 'nom', 'nomUsage', 'prenom', 'sexe', 'dateNaissance'],
'adresse' => ['INSEECommune', 'codePostal', 'localite', 'ligneVoie', 'ligneComplementDestinataire', 'ligneComplementAdresse', 'ligneComplementDistribution', 'ligneNom'],
'contact' => ['email', 'telephone', 'telephone2'],
'inscription' => ['dateInscription', 'dateCessationInscription', 'codeCertificationCNAV', 'codeCategorieInscription', 'libelleCategorieInscription']
}
}
end
let(:result) { JSON.parse(File.read('spec/fixtures/files/api_particulier/situation_pole_emploi.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 address name is requested' do
let(:requested_sources) { { 'pole_emploi' => { 'adresse' => ['ligneNom'] } } }
it { is_expected.to eq('adresse' => { 'ligneNom' => 'MOUSTAKI' }) }
end
context 'when a first name is requested' do
let(:requested_sources) { { 'pole_emploi' => { 'identite' => ['prenom'] } } }
it { is_expected.to eq('identite' => { 'prenom' => 'Georges' }) }
end
end
end
context 'when the api answer is invalid' do
let(:cassette) { 'api_particulier/success/situation_pole_emploi_invalid' }
context 'when no sources is requested' do
let(:requested_sources) { {} }
it { expect { subject }.to raise_error(APIParticulier::PoleEmploiAdapter::InvalidSchemaError) }
end
end
end
end