feat (api particulier): add Pole emploi field

This commit is contained in:
François Vantomme 2021-12-01 10:21:30 +01:00 committed by simon lehericey
parent 4cfc9f7d86
commit 6ab8ac0662
28 changed files with 429 additions and 58 deletions

View file

@ -358,7 +358,8 @@
} }
.cnaf-inputs, .cnaf-inputs,
.dgfip-inputs { .dgfip-inputs,
.pole-emploi-inputs {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;

View file

@ -0,0 +1,30 @@
@import "constants";
@import "colors";
table.pole-emploi {
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;
}
}
}

View file

@ -348,8 +348,8 @@ module Users
def champs_params def champs_params
params.permit(dossier: { params.permit(dossier: {
champs_attributes: [ champs_attributes: [
:id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :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, :piece_justificative_file, :departement, :code_departement, value: [],
champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :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: []]
] ]
}) })
end end

View file

@ -2008,6 +2008,11 @@ enum TypeDeChamp {
""" """
piece_justificative piece_justificative
"""
Situation Pôle emploi
"""
pole_emploi
""" """
Régions Régions
""" """

View 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::PoleEmploiChamp < Champs::TextChamp
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/pole-emploi-input-validation.middleware.ts
store_accessor :value_json, :identifiant
def blank?
external_id.nil?
end
def fetch_external_data?
true
end
def fetch_external_data
return if !valid?
APIParticulier::PoleEmploiAdapter.new(
procedure.api_particulier_token,
identifiant,
procedure.api_particulier_sources
).to_params
end
def external_id
{ identifiant: identifiant }.to_json if identifiant.present?
end
end

View file

@ -730,6 +730,10 @@ class Procedure < ApplicationRecord
api_particulier_sources['dgfip'].present? api_particulier_sources['dgfip'].present?
end end
def pole_emploi_enabled?
api_particulier_sources['pole_emploi'].present?
end
private private
def validate_for_publication? def validate_for_publication?

View file

@ -51,7 +51,8 @@ class TypeDeChamp < ApplicationRecord
iban: 'iban', iban: 'iban',
annuaire_education: 'annuaire_education', annuaire_education: 'annuaire_education',
cnaf: 'cnaf', cnaf: 'cnaf',
dgfip: 'dgfip' dgfip: 'dgfip',
pole_emploi: 'pole_emploi'
} }
belongs_to :revision, class_name: 'ProcedureRevision', optional: true belongs_to :revision, class_name: 'ProcedureRevision', optional: true
@ -327,6 +328,8 @@ class TypeDeChamp < ApplicationRecord
procedure.cnaf_enabled? procedure.cnaf_enabled?
when TypeDeChamp.type_champs.fetch(:dgfip) when TypeDeChamp.type_champs.fetch(:dgfip)
procedure.dgfip_enabled? procedure.dgfip_enabled?
when TypeDeChamp.type_champs.fetch(:pole_emploi)
procedure.pole_emploi_enabled?
else else
true true
end end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::PoleEmploiTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -16,7 +16,7 @@
- scopes.each do |scope_key, sources| - scopes.each do |scope_key, sources|
%h3.explication-libelle= t("api_particulier.providers.#{provider_key}.scopes.#{scope_key}.libelle") %h3.explication-libelle= t("api_particulier.providers.#{provider_key}.scopes.#{scope_key}.libelle")
%ul.procedure-admin-api-particulier-sources{ id: scope_key } %ul.procedure-admin-api-particulier-sources{ id: "#{provider_key}-#{scope_key}" }
- sources.each do |source_key, enabled_hash| - sources.each do |source_key, enabled_hash|
- enabled = (@procedure.api_particulier_sources.dig(provider_key, scope_key)&.include?(source_key)).present? - enabled = (@procedure.api_particulier_sources.dig(provider_key, scope_key)&.include?(source_key)).present?
%li %li

View file

@ -0,0 +1,6 @@
%table.pole-emploi
%caption #{t("api_particulier.providers.pole_emploi.scopes.#{scope}.libelle")} :
- adresse.slice('INSEECommune', 'codePostal', 'localite', 'ligneVoie', 'ligneComplementDestinataire', 'ligneComplementAdresse', 'ligneComplementDistribution', 'ligneNom').keys.each do |key|
%tr
%th= t("api_particulier.providers.pole_emploi.scopes.#{scope}.#{key}")
%td= adresse[key]

View file

@ -0,0 +1,6 @@
%table.pole-emploi
%caption #{t("api_particulier.providers.pole_emploi.scopes.#{scope}.libelle")} :
- contact.slice('email', 'telephone', 'telephone2').keys.each do |key|
%tr
%th= t("api_particulier.providers.pole_emploi.scopes.#{scope}.#{key}")
%td= contact[key]

View file

@ -0,0 +1,12 @@
%table.pole-emploi
%caption #{t("api_particulier.providers.pole_emploi.scopes.#{scope}.libelle")} :
- identite.slice('identifiant', 'civilite', 'nom', 'nomUsage', 'prenom', 'sexe', 'dateNaissance').keys.each do |key|
%tr
%th= t("api_particulier.providers.pole_emploi.scopes.#{scope}.#{key}")
- case key
- when 'dateNaissance'
%td= try_format_date(Date.strptime(identite[key], "%Y-%m-%d"))
- when 'sexe'
%td= t("api_particulier.providers.pole_emploi.scopes.#{scope}.#{identite[key]}")
- else
%td= identite[key]

View file

@ -0,0 +1,10 @@
%table.pole-emploi
%caption #{t("api_particulier.providers.pole_emploi.scopes.#{scope}.libelle")} :
- inscription.slice('dateInscription', 'dateCessationInscription', 'codeCertificationCNAV', 'codeCategorieInscription', 'libelleCategorieInscription').keys.each do |key|
%tr
%th= t("api_particulier.providers.pole_emploi.scopes.#{scope}.#{key}")
- case key
- when 'dateInscription', 'dateCessationInscription'
%td= try_format_date(Date.strptime(inscription[key], "%Y-%m-%d"))
- else
%td= inscription[key]

View file

@ -0,0 +1,24 @@
- if champ.blank?
%p= t('.not_filled')
- elsif champ.data.blank?
%p= t('.fetching_data',
identifiant: champ.identifiant)
- else
- if profile == 'usager'
- sources = champ.procedure.api_particulier_sources['pole_emploi'].keys
- i18n_sources = sources.map { |s| I18n.t("#{s}.libelle", scope: 'api_particulier.providers.pole_emploi.scopes') }
%p= t('.data_fetched', sources: i18n_sources.to_sentence, identifiant: champ.identifiant)
- if profile == 'instructeur'
%p= t('.data_fetched_title')
- champ.data.slice('identite', 'adresse', 'contact', 'inscription').keys.each do |scope|
- case scope
- when 'identite'
= render partial: 'shared/champs/pole_emploi/identite', locals: { scope: scope, identite: champ.data[scope] }
- when 'adresse'
= render partial: 'shared/champs/pole_emploi/adresse', locals: { scope: scope, adresse: champ.data[scope] }
- when 'contact'
= render partial: 'shared/champs/pole_emploi/contact', locals: { scope: scope, contact: champ.data[scope] }
- when 'inscription'
= render partial: 'shared/champs/pole_emploi/inscription', locals: { scope: scope, inscription: champ.data[scope] }

View file

@ -40,6 +40,8 @@
= render partial: "shared/champs/cnaf/show", locals: { champ: c, profile: profile } = render partial: "shared/champs/cnaf/show", locals: { champ: c, profile: profile }
- when TypeDeChamp.type_champs.fetch(:dgfip) - when TypeDeChamp.type_champs.fetch(:dgfip)
= render partial: "shared/champs/dgfip/show", locals: { champ: c, profile: profile } = 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(:address) - when TypeDeChamp.type_champs.fetch(:address)
= render partial: "shared/champs/address/show", locals: { champ: c } = render partial: "shared/champs/address/show", locals: { champ: c }
- when TypeDeChamp.type_champs.fetch(:communes) - when TypeDeChamp.type_champs.fetch(:communes)

View file

@ -0,0 +1,7 @@
.pole_emploi-inputs
%div
= form.label :identifiant, t('.identifiant_label')
%p.notice= t('.identifiant_notice')
= form.text_field :identifiant,
required: champ.mandatory?,
aria: { describedby: describedby_id(champ) }

View file

@ -38,3 +38,4 @@ fr:
annuaire_education: 'Annuaire de léducation' annuaire_education: 'Annuaire de léducation'
cnaf: 'Données de la Caisse nationale des allocations familiales' cnaf: 'Données de la Caisse nationale des allocations familiales'
dgfip: 'Données de la Direction générale des Finances publiques' dgfip: 'Données de la Direction générale des Finances publiques'
pole_emploi: 'Situation Pôle emploi'

View file

@ -12,6 +12,9 @@ en:
numero_fiscal_notice: It is usually composed of 13 to 14 characters. numero_fiscal_notice: It is usually composed of 13 to 14 characters.
reference_avis_label: Tax notice reference reference_avis_label: Tax notice reference
reference_avis_notice: It is usually composed of 13 to 14 characters. reference_avis_notice: It is usually composed of 13 to 14 characters.
pole_emploi:
identifiant_label: Identifier
identifiant_notice: It is usually composed of alphanumeric characters.
header: header:
expires_at: expires_at:
brouillon: "Expires at %{date} (%{duree_conservation_totale} months after the creation of this file)" brouillon: "Expires at %{date} (%{duree_conservation_totale} months after the creation of this file)"
@ -33,3 +36,9 @@ en:
fetching_data: "Fetching data for declarant No. %{numero_fiscal} with tax notice reference %{reference_avis}." fetching_data: "Fetching data for declarant No. %{numero_fiscal} with tax notice reference %{reference_avis}."
data_fetched: "Data concerning %{sources} linked to the declarant Nº %{numero_fiscal} with tax notice reference %{reference_avis} has been received from the DGFiP." data_fetched: "Data concerning %{sources} linked to the declarant Nº %{numero_fiscal} with tax notice reference %{reference_avis} has been received from the DGFiP."
data_fetched_title: "Data received from la Direction générale des Finances publiques" data_fetched_title: "Data received from la Direction générale des Finances publiques"
pole_emploi:
show:
not_filled: not filled
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"

View file

@ -12,6 +12,9 @@ fr:
numero_fiscal_notice: Il est généralement composé de 13 ou 14 caractères. numero_fiscal_notice: Il est généralement composé de 13 ou 14 caractères.
reference_avis_label: La référence d'avis d'imposition reference_avis_label: La référence d'avis d'imposition
reference_avis_notice: Elle est généralement composée de 13 ou 14 caractères. reference_avis_notice: Elle est généralement composée de 13 ou 14 caractères.
pole_emploi:
identifiant_label: Identifiant
identifiant_notice: Il est généralement composé de caractères alphanumériques.
header: header:
expires_at: expires_at:
brouillon: "Expirera le %{date} (%{duree_conservation_totale} mois après la création du dossier)" brouillon: "Expirera le %{date} (%{duree_conservation_totale} mois après la création du dossier)"
@ -35,3 +38,9 @@ fr:
fetching_data: "La récupération automatique des données pour le déclarant Nº %{numero_fiscal} avec la référence d'avis %{reference_avis} est en cours." fetching_data: "La récupération automatique des données pour le déclarant Nº %{numero_fiscal} avec la référence d'avis %{reference_avis} est en cours."
data_fetched: "Des données concernant %{sources} liées au déclarant Nº %{numero_fiscal} avec la référence d'avis %{reference_avis} ont été reçues depuis la DGFiP." data_fetched: "Des données concernant %{sources} liées au déclarant Nº %{numero_fiscal} avec la référence d'avis %{reference_avis} ont été reçues depuis la DGFiP."
data_fetched_title: "Données obtenues de la Direction générale des Finances publiques" data_fetched_title: "Données obtenues de la Direction générale des Finances publiques"
pole_emploi:
show:
not_filled: non renseigné
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"

View file

@ -75,7 +75,11 @@ describe Administrateurs::JetonParticulierController, type: :controller do
'dgfip_revenu_fiscal_reference', 'dgfip_revenu_fiscal_reference',
'dgfip_revenu_imposable', 'dgfip_revenu_imposable',
'dgfip_situation_familiale', 'dgfip_situation_familiale',
'dgfip_situation_partielle' 'dgfip_situation_partielle',
'pole_emploi_identite',
'pole_emploi_adresse',
'pole_emploi_contact',
'pole_emploi_inscription'
) )
expect(procedure.api_particulier_sources).to be_empty expect(procedure.api_particulier_sources).to be_empty
end end

View file

@ -193,6 +193,10 @@ FactoryBot.define do
type_de_champ { association :type_de_champ_dgfip, procedure: dossier.procedure } type_de_champ { association :type_de_champ_dgfip, procedure: dossier.procedure }
end end
factory :champ_pole_emploi, class: 'Champs::PoleEmploiChamp' do
type_de_champ { association :type_de_champ_pole_emploi, procedure: dossier.procedure }
end
factory :champ_siret, class: 'Champs::SiretChamp' do factory :champ_siret, class: 'Champs::SiretChamp' do
type_de_champ { association :type_de_champ_siret, procedure: dossier.procedure } type_de_champ { association :type_de_champ_siret, procedure: dossier.procedure }
association :etablissement, factory: [:etablissement] association :etablissement, factory: [:etablissement]

View file

@ -206,6 +206,12 @@ FactoryBot.define do
end end
end end
trait :with_pole_emploi do
after(:build) do |procedure, _evaluator|
build(:type_de_champ_pole_emploi, procedure: procedure)
end
end
trait :with_explication do trait :with_explication do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
build(:type_de_champ_explication, procedure: procedure) build(:type_de_champ_explication, procedure: procedure)

View file

@ -160,6 +160,9 @@ FactoryBot.define do
factory :type_de_champ_dgfip do factory :type_de_champ_dgfip do
type_champ { TypeDeChamp.type_champs.fetch(:dgfip) } type_champ { TypeDeChamp.type_champs.fetch(:dgfip) }
end end
factory :type_de_champ_pole_emploi do
type_champ { TypeDeChamp.type_champs.fetch(:pole_emploi) }
end
factory :type_de_champ_carte do factory :type_de_champ_carte do
type_champ { TypeDeChamp.type_champs.fetch(:carte) } type_champ { TypeDeChamp.type_champs.fetch(:carte) }
end end

View file

@ -25,7 +25,7 @@ http_interactions:
Content-Type: Content-Type:
- application/json - application/json
Content-Length: Content-Length:
- '228' - '257'
Connection: Connection:
- keep-alive - keep-alive
Keep-Alive: Keep-Alive:
@ -38,6 +38,6 @@ http_interactions:
- max-age=15552000 - max-age=15552000
body: body:
encoding: UTF-8 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"]}' 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"]}'
recorded_at: Tue, 16 Mar 2021 15:25:24 GMT recorded_at: Tue, 16 Mar 2021 15:25:24 GMT
recorded_with: VCR 6.0.0 recorded_with: VCR 6.0.0

View file

@ -37,7 +37,11 @@ describe APIParticulier::API do
'dgfip_revenu_fiscal_reference', 'dgfip_revenu_fiscal_reference',
'dgfip_revenu_imposable', 'dgfip_revenu_imposable',
'dgfip_situation_familiale', 'dgfip_situation_familiale',
'dgfip_situation_partielle' 'dgfip_situation_partielle',
'pole_emploi_identite',
'pole_emploi_adresse',
'pole_emploi_contact',
'pole_emploi_inscription'
) )
end end
end end

View file

@ -0,0 +1,56 @@
describe Champs::PoleEmploiChamp, type: :model do
let(:champ) { described_class.new }
describe 'identifiant' do
before do
champ.identifiant = 'georges_moustaki_77'
end
it 'saves identifiant' do
expect(champ.identifiant).to eq('georges_moustaki_77')
end
end
describe 'external_id' do
context 'when no data is given' do
before do
champ.identifiant = ''
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.identifiant = 'georges_moustaki_77'
champ.save
end
it { expect(JSON.parse(champ.external_id)).to eq("identifiant" => "georges_moustaki_77") }
end
end
describe '#validate' do
let(:champ) { described_class.new(dossier: create(:dossier), type_de_champ: create(:type_de_champ_pole_emploi)) }
let(:validation_context) { :create }
subject { champ.valid?(validation_context) }
before do
champ.identifiant = identifiant
end
context 'when identifiant is valid' do
let(:identifiant) { 'georges_moustaki_77' }
it { is_expected.to be true }
end
context 'when identifiant is nil' do
let(:identifiant) { nil }
it { is_expected.to be true }
end
end
end

View file

@ -79,6 +79,7 @@ describe ProcedureExportService do
"annuaire_education", "annuaire_education",
"cnaf", "cnaf",
"dgfip", "dgfip",
"pole_emploi",
"text" "text"
] ]
end end
@ -168,6 +169,7 @@ describe ProcedureExportService do
"annuaire_education", "annuaire_education",
"cnaf", "cnaf",
"dgfip", "dgfip",
"pole_emploi",
"text" "text"
] ]
end end
@ -253,6 +255,7 @@ describe ProcedureExportService do
"annuaire_education", "annuaire_education",
"cnaf", "cnaf",
"dgfip", "dgfip",
"pole_emploi",
"text" "text"
] ]
end end

View file

@ -20,6 +20,12 @@ describe 'fetch API Particulier Data', js: true do
'foyer_fiscal' => ['adresse', 'annee', 'nombreParts', 'nombrePersonnesCharge', 'situationFamille'], 'foyer_fiscal' => ['adresse', 'annee', 'nombreParts', 'nombrePersonnesCharge', 'situationFamille'],
'agregats_fiscaux' => ['anneeImpots', 'anneeRevenus', 'impotRevenuNetAvantCorrections', 'montantImpot', 'revenuBrutGlobal', 'revenuFiscalReference', 'revenuImposable'], 'agregats_fiscaux' => ['anneeImpots', 'anneeRevenus', 'impotRevenuNetAvantCorrections', 'montantImpot', 'revenuBrutGlobal', 'revenuFiscalReference', 'revenuImposable'],
'complements' => ['situationPartielle', 'erreurCorrectif'] 'complements' => ['situationPartielle', 'erreurCorrectif']
},
'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 end
@ -29,7 +35,7 @@ describe 'fetch API Particulier Data', js: true do
Flipper.enable(:api_particulier) Flipper.enable(:api_particulier)
end end
context 'when an administrateur is logged' do context 'when an administrateur is logged in' do
let(:procedure) do let(:procedure) do
create(:procedure, :with_service, :with_instructeur, create(:procedure, :with_service, :with_instructeur,
aasm_state: :brouillon, aasm_state: :brouillon,
@ -56,14 +62,14 @@ describe 'fetch API Particulier Data', js: true do
expect(page).to have_current_path(admin_procedure_api_particulier_sources_path(procedure)) expect(page).to have_current_path(admin_procedure_api_particulier_sources_path(procedure))
['allocataires', 'enfants'].each do |scope| ['allocataires', 'enfants'].each do |scope|
within("##{scope}") do within("#cnaf-#{scope}") do
check('noms et prénoms') check('noms et prénoms')
check('date de naissance') check('date de naissance')
check('sexe') check('sexe')
end end
end end
within('#adresse') do within('#cnaf-adresse') do
check('identité') check('identité')
check('complément didentité') check('complément didentité')
check('complément didentité géographique') check('complément didentité géographique')
@ -73,14 +79,14 @@ describe 'fetch API Particulier Data', js: true do
check('pays') check('pays')
end end
within('#quotient_familial') do within('#cnaf-quotient_familial') do
check('quotient familial') check('quotient familial')
check('année') check('année')
check('mois') check('mois')
end end
['declarant1', 'declarant2'].each do |scope| ['declarant1', 'declarant2'].each do |scope|
within("##{scope}") do within("#dgfip-#{scope}") do
check('nom') check('nom')
check('nom de naissance') check('nom de naissance')
check('prénoms') check('prénoms')
@ -88,13 +94,13 @@ describe 'fetch API Particulier Data', js: true do
end end
end end
scroll_to(find('#echeance_avis')) scroll_to(find('#dgfip-echeance_avis'))
within ('#echeance_avis') do within ('#dgfip-echeance_avis') do
check('date de recouvrement') check('date de recouvrement')
check("date détablissement") check("date détablissement")
end end
within('#foyer_fiscal') do within('#dgfip-foyer_fiscal') do
check('année') check('année')
check('adresse') check('adresse')
check('nombre de parts') check('nombre de parts')
@ -102,7 +108,7 @@ describe 'fetch API Particulier Data', js: true do
check('nombre de personnes à charge') check('nombre de personnes à charge')
end end
within('#agregats_fiscaux') do within('#dgfip-agregats_fiscaux') do
check('revenu brut global') check('revenu brut global')
check('revenu imposable') check('revenu imposable')
check('impôt sur le revenu net avant correction') check('impôt sur le revenu net avant correction')
@ -112,22 +118,58 @@ describe 'fetch API Particulier Data', js: true do
check('année des revenus') check('année des revenus')
end end
within('#complements') do within('#dgfip-complements') do
check('erreur correctif') check('erreur correctif')
check('situation partielle') check('situation partielle')
end end
within('#pole_emploi-identite') do
check('identifiant')
check('civilité')
check('nom')
check("nom dusage")
check('prénom')
check('sexe')
check('date de naissance')
end
within('#pole_emploi-adresse') do
check('code INSEE de la commune')
check('code postal')
check('localité')
check('voie')
check('destinataire')
check('adresse')
check('distribution')
check('nom')
end
within('#pole_emploi-contact') do
check('email')
check('téléphone')
check('téléphone 2')
end
within('#pole_emploi-inscription') do
check("date dinscription")
check("date de cessation dinscription")
check('code de certification CNAV')
check("code de catégorie dinscription")
check("libellé de catégorie dinscription")
end
click_on 'Enregistrer' click_on 'Enregistrer'
within('#enfants') do within('#cnaf-enfants') do
expect(find('input[value=nomPrenom]')).to be_checked expect(find('input[value=nomPrenom]')).to be_checked
end end
procedure.reload procedure.reload
expect(procedure.api_particulier_sources.keys).to contain_exactly('cnaf', 'dgfip') expect(procedure.api_particulier_sources.keys).to contain_exactly('cnaf', 'dgfip', 'pole_emploi')
expect(procedure.api_particulier_sources['cnaf'].keys).to contain_exactly('adresse', 'allocataires', 'enfants', 'quotient_familial') 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['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')
procedure.api_particulier_sources.each do |provider, scopes| procedure.api_particulier_sources.each do |provider, scopes|
scopes.each do |scope, fields| scopes.each do |scope, fields|
@ -153,17 +195,18 @@ describe 'fetch API Particulier Data', js: true do
end end
end end
context 'when an user is logged' do context 'when a user is logged in' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
let(:numero_allocataire) { '5843972' } let(:numero_allocataire) { '5843972' }
let(:code_postal) { '92110' } let(:code_postal) { '92110' }
let(:numero_fiscal) { '2097699999077' } let(:numero_fiscal) { '2097699999077' }
let(:reference_avis) { '2097699999077' } let(:reference_avis) { '2097699999077' }
let(:instructeur) { create(:instructeur) } let(:instructeur) { create(:instructeur) }
let(:identifiant) { 'georges_moustaki_77' }
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
let(:procedure) do let(:procedure) do
create(:procedure, :for_individual, :with_service, :with_cnaf, :with_dgfip, :published, create(:procedure, :for_individual, :with_service, :with_cnaf, :with_dgfip, :with_pole_emploi, :published,
libelle: 'libellé de la procédure', libelle: 'libellé de la procédure',
path: 'libelle-de-la-procedure', path: 'libelle-de-la-procedure',
instructeurs: [instructeur], instructeurs: [instructeur],
@ -173,6 +216,7 @@ describe 'fetch API Particulier Data', js: true do
before { login_as user, scope: :user } before { login_as user, scope: :user }
context 'CNAF' do
scenario 'it can fill an cnaf champ' do scenario 'it can fill an cnaf champ' do
visit commencer_path(path: procedure.path) visit commencer_path(path: procedure.path)
click_on 'Commencer la démarche' click_on 'Commencer la démarche'
@ -222,6 +266,75 @@ describe 'fetch API Particulier Data', js: true do
expect(page).to have_content('PAUL SNOW masculin 04/01/2018') expect(page).to have_content('PAUL SNOW masculin 04/01/2018')
expect(page).to have_content('1856 6 2021') expect(page).to have_content('1856 6 2021')
end end
end
context 'Pôle emploi' do
let(:api_particulier_token) { '06fd8675601267d2988cbbdef56ecb0de1d45223' }
scenario 'it can fill a Pôle emploi field' do
visit commencer_path(path: procedure.path)
click_on 'Commencer la démarche'
choose 'Monsieur'
fill_in 'individual_nom', with: 'Moustaki'
fill_in 'individual_prenom', with: 'Georges'
click_button('Continuer')
fill_in "Identifiant", with: 'wrong code'
blur
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
dossier = Dossier.last
pole_emploi_champ = dossier.champs.third
expect(pole_emploi_champ.identifiant).to eq('wrong code')
fill_in "Identifiant", with: identifiant
VCR.use_cassette('api_particulier/success/situation_pole_emploi') 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 Pôle emploi/)
log_out
login_as instructeur.user, scope: :user
visit instructeur_dossier_path(procedure, dossier)
expect(page).to have_content('identifiant georges_moustaki_77')
expect(page).to have_content('civilité M.')
expect(page).to have_content('nom Moustaki')
expect(page).to have_content("nom dusage Moustaki")
expect(page).to have_content('prénom Georges')
expect(page).to have_content('sexe masculin')
expect(page).to have_content('date de naissance 3 mai 1934')
expect(page).to have_content('code INSEE de la commune 75118')
expect(page).to have_content('code postal 75018')
expect(page).to have_content('localité 75018 Paris')
expect(page).to have_content('voie 3 rue des Huttes')
expect(page).to have_content('nom MOUSTAKI')
expect(page).to have_content('email georges@moustaki.fr')
expect(page).to have_content('téléphone 0629212921')
expect(page).to have_content("date dinscription 3 mai 1965")
expect(page).to have_content("date de cessation dinscription 3 mai 1966")
expect(page).to have_content('code de certification CNAV VC')
expect(page).to have_content("code de catégorie dinscription 1")
expect(page).to have_content("libellé de catégorie dinscription PERSONNE SANS EMPLOI DISPONIBLE DUREE INDETERMINEE PLEIN TPS")
expect(page).not_to have_content('téléphone 2')
expect(page).not_to have_content('destinataire')
expect(page).not_to have_content('adresse')
expect(page).not_to have_content('distribution')
end
end
scenario 'it can fill a DGFiP field' do scenario 'it can fill a DGFiP field' do
visit commencer_path(path: procedure.path) visit commencer_path(path: procedure.path)