Merge pull request #6725 from betagouv/main
This commit is contained in:
commit
4b35e4a328
43 changed files with 1114 additions and 46 deletions
30
app/assets/stylesheets/dgfip.scss
Normal file
30
app/assets/stylesheets/dgfip.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
@import "constants";
|
||||||
|
@import "colors";
|
||||||
|
|
||||||
|
table.dgfip {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -357,7 +357,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cnaf-inputs {
|
.cnaf-inputs,
|
||||||
|
.dgfip-inputs {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
|
@ -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, :piece_justificative_file, :departement, :code_departement, value: [],
|
: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: [],
|
||||||
champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :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: []]
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -1933,6 +1933,11 @@ enum TypeDeChamp {
|
||||||
"""
|
"""
|
||||||
departements
|
departements
|
||||||
|
|
||||||
|
"""
|
||||||
|
Données de la Direction générale des Finances publiques
|
||||||
|
"""
|
||||||
|
dgfip
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Lien vers un autre dossier
|
Lien vers un autre dossier
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,6 +3,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"
|
||||||
|
|
||||||
TIMEOUT = 20
|
TIMEOUT = 20
|
||||||
|
|
||||||
|
@ -20,6 +21,14 @@ class APIParticulier::API
|
||||||
codePostal: code_postal)
|
codePostal: code_postal)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def avis_imposition(numero_fiscal, reference_avis)
|
||||||
|
# NOTE: Il est possible que l'utilisateur ajoute une quatorzième lettre à la fin de sa référence d'avis.
|
||||||
|
# Il s'agit d'une clé de vérification qu'il est nécessaire de'enlever avant de contacter API Particulier.
|
||||||
|
get(AVIS_IMPOSITION_RESOURCE_NAME,
|
||||||
|
numeroFiscal: numero_fiscal.to_i.to_s.rjust(13, "0"),
|
||||||
|
referenceAvis: reference_avis.to_i.to_s.rjust(13, "0"))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get(resource_name, params = {})
|
def get(resource_name, params = {})
|
||||||
|
|
49
app/lib/api_particulier/dgfip_adapter.rb
Normal file
49
app/lib/api_particulier/dgfip_adapter.rb
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
class APIParticulier::DgfipAdapter
|
||||||
|
class InvalidSchemaError < ::StandardError
|
||||||
|
def initialize(errors)
|
||||||
|
super(errors.map(&:to_json).join("\n"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(api_particulier_token, numero_fiscal, reference_avis, requested_sources)
|
||||||
|
@api = APIParticulier::API.new(api_particulier_token)
|
||||||
|
@numero_fiscal = numero_fiscal
|
||||||
|
@reference_avis = reference_avis
|
||||||
|
@requested_sources = requested_sources
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_params
|
||||||
|
@api.avis_imposition(@numero_fiscal, @reference_avis)
|
||||||
|
.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/avis-imposition.json'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_requested_sources(data)
|
||||||
|
@requested_sources['dgfip']&.map do |(scope, sources)|
|
||||||
|
case scope
|
||||||
|
when 'foyer_fiscal'
|
||||||
|
{ scope => data['foyerFiscal'].slice(*sources).merge(data.slice(*sources)) }
|
||||||
|
when 'declarant1', 'declarant2'
|
||||||
|
sources.map { |source| { scope => data[scope].slice(*source) } }
|
||||||
|
when 'agregats_fiscaux', 'echeance_avis', 'complements'
|
||||||
|
sources.map { |source| { scope => data.slice(*source) } }
|
||||||
|
else
|
||||||
|
{ scope => data.slice(*sources) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
&.flatten&.reduce(&:deep_merge) || {}
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@ module APIParticulier
|
||||||
.map { |provider_and_scope| raw_scopes[provider_and_scope] }
|
.map { |provider_and_scope| raw_scopes[provider_and_scope] }
|
||||||
.compact
|
.compact
|
||||||
.map { |provider, scope| extract_sources(provider, scope) }
|
.map { |provider, scope| extract_sources(provider, scope) }
|
||||||
.reduce({}) { |acc, el| acc.deep_merge(el) }
|
.reduce({}) { |acc, el| acc.deep_merge(el) { |_, this_val, other_val| this_val + other_val } }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remove sources not available for the procedure
|
# Remove sources not available for the procedure
|
||||||
|
@ -38,7 +38,14 @@ module APIParticulier
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_sources(provider, scope)
|
def extract_sources(provider, scope)
|
||||||
{ provider => { scope => providers[provider][scope] } }
|
provider_scope_value = providers[provider][scope]
|
||||||
|
|
||||||
|
case provider_scope_value
|
||||||
|
when Hash
|
||||||
|
{ provider => provider_scope_value }
|
||||||
|
else
|
||||||
|
{ provider => { scope => Array(provider_scope_value) } }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw_scopes
|
def raw_scopes
|
||||||
|
@ -46,7 +53,31 @@ module APIParticulier
|
||||||
'cnaf_allocataires' => ['cnaf', 'allocataires'],
|
'cnaf_allocataires' => ['cnaf', 'allocataires'],
|
||||||
'cnaf_enfants' => ['cnaf', 'enfants'],
|
'cnaf_enfants' => ['cnaf', 'enfants'],
|
||||||
'cnaf_adresse' => ['cnaf', 'adresse'],
|
'cnaf_adresse' => ['cnaf', 'adresse'],
|
||||||
'cnaf_quotient_familial' => ['cnaf', 'quotient_familial']
|
'cnaf_quotient_familial' => ['cnaf', 'quotient_familial'],
|
||||||
|
'dgfip_declarant1_nom' => ['dgfip', 'declarant1_nom'],
|
||||||
|
'dgfip_declarant1_nom_naissance' => ['dgfip', 'declarant1_nom_naissance'],
|
||||||
|
'dgfip_declarant1_prenoms' => ['dgfip', 'declarant1_prenoms'],
|
||||||
|
'dgfip_declarant1_date_naissance' => ['dgfip', 'declarant1_date_naissance'],
|
||||||
|
'dgfip_declarant2_nom' => ['dgfip', 'declarant2_nom'],
|
||||||
|
'dgfip_declarant2_nom_naissance' => ['dgfip', 'declarant2_nom_naissance'],
|
||||||
|
'dgfip_declarant2_prenoms' => ['dgfip', 'declarant2_prenoms'],
|
||||||
|
'dgfip_declarant2_date_naissance' => ['dgfip', 'declarant2_date_naissance'],
|
||||||
|
'dgfip_date_recouvrement' => ['dgfip', 'date_recouvrement'],
|
||||||
|
'dgfip_date_etablissement' => ['dgfip', 'date_etablissement'],
|
||||||
|
'dgfip_adresse_fiscale_taxation' => ['dgfip', 'adresse_fiscale_taxation'],
|
||||||
|
'dgfip_adresse_fiscale_annee' => ['dgfip', 'adresse_fiscale_annee'],
|
||||||
|
'dgfip_nombre_parts' => ['dgfip', 'nombre_parts'],
|
||||||
|
'dgfip_nombre_personnes_a_charge' => ['dgfip', 'nombre_personnes_a_charge'],
|
||||||
|
'dgfip_situation_familiale' => ['dgfip', 'situation_familiale'],
|
||||||
|
'dgfip_revenu_brut_global' => ['dgfip', 'revenu_brut_global'],
|
||||||
|
'dgfip_revenu_imposable' => ['dgfip', 'revenu_imposable'],
|
||||||
|
'dgfip_impot_revenu_net_avant_corrections' => ['dgfip', 'impot_revenu_net_avant_corrections'],
|
||||||
|
'dgfip_montant_impot' => ['dgfip', 'montant_impot'],
|
||||||
|
'dgfip_revenu_fiscal_reference' => ['dgfip', 'revenu_fiscal_reference'],
|
||||||
|
'dgfip_annee_impot' => ['dgfip', 'annee_impot'],
|
||||||
|
'dgfip_annee_revenus' => ['dgfip', 'annee_revenus'],
|
||||||
|
'dgfip_erreur_correctif' => ['dgfip', 'erreur_correctif'],
|
||||||
|
'dgfip_situation_partielle' => ['dgfip', 'situation_partielle']
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,6 +88,32 @@ module APIParticulier
|
||||||
'enfants' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
'enfants' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||||
'adresse' => ['identite', 'complementIdentite', 'complementIdentiteGeo', 'numeroRue', 'lieuDit', 'codePostalVille', 'pays'],
|
'adresse' => ['identite', 'complementIdentite', 'complementIdentiteGeo', 'numeroRue', 'lieuDit', 'codePostalVille', 'pays'],
|
||||||
'quotient_familial' => ['quotientFamilial', 'annee', 'mois']
|
'quotient_familial' => ['quotientFamilial', 'annee', 'mois']
|
||||||
|
},
|
||||||
|
'dgfip' => {
|
||||||
|
'declarant1_nom' => { 'declarant1' => ['nom'] },
|
||||||
|
'declarant1_nom_naissance' => { 'declarant1' => ['nomNaissance'] },
|
||||||
|
'declarant1_prenoms' => { 'declarant1' => ['prenoms'] },
|
||||||
|
'declarant1_date_naissance' => { 'declarant1' => ['dateNaissance'] },
|
||||||
|
'declarant2_nom' => { 'declarant2' => ['nom'] },
|
||||||
|
'declarant2_nom_naissance' => { 'declarant2' => ['nomNaissance'] },
|
||||||
|
'declarant2_prenoms' => { 'declarant2' => ['prenoms'] },
|
||||||
|
'declarant2_date_naissance' => { 'declarant2' => ['dateNaissance'] },
|
||||||
|
'date_recouvrement' => { 'echeance_avis' => ['dateRecouvrement'] },
|
||||||
|
'date_etablissement' => { 'echeance_avis' => ['dateEtablissement'] },
|
||||||
|
'adresse_fiscale_taxation' => { 'foyer_fiscal' => ['adresse'] },
|
||||||
|
'adresse_fiscale_annee' => { 'foyer_fiscal' => ['annee'] },
|
||||||
|
'nombre_parts' => { 'foyer_fiscal' => ['nombreParts'] },
|
||||||
|
'nombre_personnes_a_charge' => { 'foyer_fiscal' => ['nombrePersonnesCharge'] },
|
||||||
|
'situation_familiale' => { 'foyer_fiscal' => ['situationFamille'] },
|
||||||
|
'revenu_brut_global' => { 'agregats_fiscaux' => ['revenuBrutGlobal'] },
|
||||||
|
'revenu_imposable' => { 'agregats_fiscaux' => ['revenuImposable'] },
|
||||||
|
'impot_revenu_net_avant_corrections' => { 'agregats_fiscaux' => ['impotRevenuNetAvantCorrections'] },
|
||||||
|
'montant_impot' => { 'agregats_fiscaux' => ['montantImpot'] },
|
||||||
|
'revenu_fiscal_reference' => { 'agregats_fiscaux' => ['revenuFiscalReference'] },
|
||||||
|
'annee_impot' => { 'agregats_fiscaux' => ['anneeImpots'] },
|
||||||
|
'annee_revenus' => { 'agregats_fiscaux' => ['anneeRevenus'] },
|
||||||
|
'erreur_correctif' => { 'complements' => ['erreurCorrectif'] },
|
||||||
|
'situation_partielle' => { 'complements' => ['situationPartielle'] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
53
app/models/champs/dgfip_champ.rb
Normal file
53
app/models/champs/dgfip_champ.rb
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# == 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::DgfipChamp < Champs::TextChamp
|
||||||
|
# see https://github.com/betagouv/api-particulier/blob/master/src/presentation/middlewares/dgfip-input-validation.middleware.ts
|
||||||
|
validates :numero_fiscal, format: { with: /\A\w{13,14}\z/ }, if: -> { reference_avis.present? && validation_context != :brouillon }
|
||||||
|
validates :reference_avis, format: { with: /\A\w{13,14}\z/ }, if: -> { numero_fiscal.present? && validation_context != :brouillon }
|
||||||
|
|
||||||
|
store_accessor :value_json, :numero_fiscal, :reference_avis
|
||||||
|
|
||||||
|
def blank?
|
||||||
|
external_id.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_external_data?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_external_data
|
||||||
|
if valid?
|
||||||
|
APIParticulier::DgfipAdapter.new(
|
||||||
|
procedure.api_particulier_token,
|
||||||
|
numero_fiscal,
|
||||||
|
reference_avis,
|
||||||
|
procedure.api_particulier_sources
|
||||||
|
).to_params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def external_id
|
||||||
|
if numero_fiscal.present? && reference_avis.present?
|
||||||
|
{ reference_avis: reference_avis, numero_fiscal: numero_fiscal }.to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -560,7 +560,7 @@ class Dossier < ApplicationRecord
|
||||||
approximative_expiration_date_reference,
|
approximative_expiration_date_reference,
|
||||||
conservation_extension,
|
conservation_extension,
|
||||||
procedure.duree_conservation_dossiers_dans_ds.months
|
procedure.duree_conservation_dossiers_dans_ds.months
|
||||||
].sum - REMAINING_WEEKS_BEFORE_EXPIRATION.weeks
|
].compact.sum - REMAINING_WEEKS_BEFORE_EXPIRATION.weeks
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_to_expiration?
|
def close_to_expiration?
|
||||||
|
|
|
@ -726,6 +726,10 @@ class Procedure < ApplicationRecord
|
||||||
api_particulier_sources['cnaf'].present?
|
api_particulier_sources['cnaf'].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dgfip_enabled?
|
||||||
|
api_particulier_sources['dgfip'].present?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def validate_for_publication?
|
def validate_for_publication?
|
||||||
|
|
|
@ -50,7 +50,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
titre_identite: 'titre_identite',
|
titre_identite: 'titre_identite',
|
||||||
iban: 'iban',
|
iban: 'iban',
|
||||||
annuaire_education: 'annuaire_education',
|
annuaire_education: 'annuaire_education',
|
||||||
cnaf: 'cnaf'
|
cnaf: 'cnaf',
|
||||||
|
dgfip: 'dgfip'
|
||||||
}
|
}
|
||||||
|
|
||||||
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
|
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
|
||||||
|
@ -324,6 +325,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
has_legacy_number
|
has_legacy_number
|
||||||
when TypeDeChamp.type_champs.fetch(:cnaf)
|
when TypeDeChamp.type_champs.fetch(:cnaf)
|
||||||
procedure.cnaf_enabled?
|
procedure.cnaf_enabled?
|
||||||
|
when TypeDeChamp.type_champs.fetch(:dgfip)
|
||||||
|
procedure.dgfip_enabled?
|
||||||
else
|
else
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
2
app/models/types_de_champ/dgfip_type_de_champ.rb
Normal file
2
app/models/types_de_champ/dgfip_type_de_champ.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class TypesDeChamp::DgfipTypeDeChamp < TypesDeChamp::TextTypeDeChamp
|
||||||
|
end
|
81
app/schemas/avis-imposition.json
Normal file
81
app/schemas/avis-imposition.json
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://demarches-simplifiees.fr/avis-imposition.schema.json",
|
||||||
|
"title": "avis imposition",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"declarant1": {
|
||||||
|
"$ref": "#/$defs/declarant"
|
||||||
|
},
|
||||||
|
"declarant2": {
|
||||||
|
"$ref": "#/$defs/declarant"
|
||||||
|
},
|
||||||
|
"dateRecouvrement": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]{2}/[0-9]{2}/[0-9]{4}$"
|
||||||
|
},
|
||||||
|
"dateEtablissement": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]{2}/[0-9]{2}/[0-9]{4}$"
|
||||||
|
},
|
||||||
|
"nombreParts": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"situationFamille": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"revenuBrutGlobal": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"revenuImposable": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"impotRevenuNetAvantCorrections": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"montantImpot": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"revenuFiscalReference": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"nombrePersonnesCharge": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"anneeImpots": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]{4}$"
|
||||||
|
},
|
||||||
|
"anneeRevenus": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]{4}$"
|
||||||
|
},
|
||||||
|
"erreurCorrectif": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"situationPartielle": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"declarant": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"nom": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nomNaissance": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prenoms": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
%table.dgfip
|
||||||
|
%caption #{t("api_particulier.providers.dgfip.scopes.#{scope}.libelle")} :
|
||||||
|
- agregats_fiscaux.slice('revenuBrutGlobal', 'revenuImposable', 'impotRevenuNetAvantCorrections', 'montantImpot', 'revenuFiscalReference', 'anneeImpots', 'anneeRevenus', 'erreurCorrectif', 'situationPartielle').keys.each do |key|
|
||||||
|
%tr
|
||||||
|
%th= t("api_particulier.providers.dgfip.scopes.#{scope}.#{key}")
|
||||||
|
%td= agregats_fiscaux[key]
|
6
app/views/shared/champs/dgfip/_complements.html.haml
Normal file
6
app/views/shared/champs/dgfip/_complements.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%table.dgfip
|
||||||
|
%caption #{t("api_particulier.providers.dgfip.scopes.#{scope}.libelle")} :
|
||||||
|
- complements.slice('erreurCorrectif', 'situationPartielle').keys.each do |key|
|
||||||
|
%tr
|
||||||
|
%th= t("api_particulier.providers.dgfip.scopes.#{scope}.#{key}")
|
||||||
|
%td= complements[key]
|
6
app/views/shared/champs/dgfip/_declarant.html.haml
Normal file
6
app/views/shared/champs/dgfip/_declarant.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%table.dgfip
|
||||||
|
%caption #{t("api_particulier.providers.dgfip.scopes.#{scope}.libelle")} :
|
||||||
|
- declarant.slice('nom', 'nomNaissance', 'prenoms', 'dateNaissance').keys.each do |key|
|
||||||
|
%tr
|
||||||
|
%th= t("api_particulier.providers.dgfip.scopes.#{scope}.#{key}")
|
||||||
|
%td= declarant[key]
|
6
app/views/shared/champs/dgfip/_echeance_avis.html.haml
Normal file
6
app/views/shared/champs/dgfip/_echeance_avis.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%table.dgfip
|
||||||
|
%caption #{t("api_particulier.providers.dgfip.scopes.#{scope}.libelle")} :
|
||||||
|
- echeance_avis.slice('dateRecouvrement', 'dateEtablissement').keys.each do |key|
|
||||||
|
%tr
|
||||||
|
%th= t("api_particulier.providers.dgfip.scopes.#{scope}.#{key}")
|
||||||
|
%td= echeance_avis[key]
|
6
app/views/shared/champs/dgfip/_foyer_fiscal.html.haml
Normal file
6
app/views/shared/champs/dgfip/_foyer_fiscal.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%table.dgfip
|
||||||
|
%caption #{t("api_particulier.providers.dgfip.scopes.#{scope}.libelle")} :
|
||||||
|
- foyer_fiscal.slice('annee', 'adresse', 'nombreParts', 'situationFamille', 'nombrePersonnesCharge').keys.each do |key|
|
||||||
|
%tr
|
||||||
|
%th= t("api_particulier.providers.dgfip.scopes.#{scope}.#{key}")
|
||||||
|
%td= foyer_fiscal[key]
|
30
app/views/shared/champs/dgfip/_show.html.haml
Normal file
30
app/views/shared/champs/dgfip/_show.html.haml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
- if champ.blank?
|
||||||
|
%p= t('.not_filled')
|
||||||
|
- elsif champ.data.blank?
|
||||||
|
%p= t('.fetching_data',
|
||||||
|
numero_fiscal: champ.numero_fiscal,
|
||||||
|
reference_avis: champ.reference_avis)
|
||||||
|
- else
|
||||||
|
- if profile == 'usager'
|
||||||
|
- sources = champ.procedure.api_particulier_sources['dgfip'].keys
|
||||||
|
- i18n_sources = sources.map { |s| I18n.t("#{s}.libelle", scope: 'api_particulier.providers.dgfip.scopes') }
|
||||||
|
%p= t('.data_fetched',
|
||||||
|
sources: i18n_sources.to_sentence,
|
||||||
|
numero_fiscal: champ.numero_fiscal,
|
||||||
|
reference_avis: champ.reference_avis)
|
||||||
|
|
||||||
|
- if profile == 'instructeur'
|
||||||
|
%p= t('.data_fetched_title')
|
||||||
|
|
||||||
|
- champ.data.slice('declarant1', 'declarant2', 'echeance_avis', 'foyer_fiscal', 'agregats_fiscaux', 'complements').keys.each do |scope|
|
||||||
|
- case scope
|
||||||
|
- when 'declarant1', 'declarant2'
|
||||||
|
= render partial: 'shared/champs/dgfip/declarant', locals: { scope: scope, declarant: champ.data[scope] }
|
||||||
|
- when 'echeance_avis'
|
||||||
|
= render partial: 'shared/champs/dgfip/echeance_avis', locals: { scope: scope, echeance_avis: champ.data[scope] }
|
||||||
|
- when 'foyer_fiscal'
|
||||||
|
= render partial: 'shared/champs/dgfip/foyer_fiscal', locals: { scope: scope, foyer_fiscal: champ.data[scope] }
|
||||||
|
- when 'agregats_fiscaux'
|
||||||
|
= render partial: 'shared/champs/dgfip/agregats_fiscaux', locals: { scope: scope, agregats_fiscaux: champ.data[scope] }
|
||||||
|
- when 'complements'
|
||||||
|
= render partial: 'shared/champs/dgfip/complements', locals: { scope: scope, complements: champ.data[scope] }
|
|
@ -38,6 +38,8 @@
|
||||||
= render partial: "shared/champs/annuaire_education/show", locals: { champ: c }
|
= render partial: "shared/champs/annuaire_education/show", locals: { champ: c }
|
||||||
- when TypeDeChamp.type_champs.fetch(:cnaf)
|
- when TypeDeChamp.type_champs.fetch(:cnaf)
|
||||||
= 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)
|
||||||
|
= render partial: "shared/champs/dgfip/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)
|
||||||
|
|
16
app/views/shared/dossiers/editable_champs/_dgfip.html.haml
Normal file
16
app/views/shared/dossiers/editable_champs/_dgfip.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
.dgfip-inputs
|
||||||
|
%div
|
||||||
|
= form.label :numero_fiscal, t('.numero_fiscal_label')
|
||||||
|
%p.notice= t('.numero_fiscal_notice')
|
||||||
|
= form.text_field :numero_fiscal,
|
||||||
|
required: champ.mandatory?,
|
||||||
|
size: 14,
|
||||||
|
aria: { describedby: describedby_id(champ) }
|
||||||
|
|
||||||
|
%div
|
||||||
|
= form.label :reference_avis, t('.reference_avis_label')
|
||||||
|
%p.notice= t('.reference_avis_notice')
|
||||||
|
= form.text_field :reference_avis,
|
||||||
|
size: 14,
|
||||||
|
required: champ.mandatory?,
|
||||||
|
aria: { describedby: describedby_id(champ) }
|
|
@ -30,3 +30,41 @@ en:
|
||||||
quotientFamilial: quotient familial
|
quotientFamilial: quotient familial
|
||||||
mois: month
|
mois: month
|
||||||
annee: year
|
annee: year
|
||||||
|
dgfip:
|
||||||
|
libelle: Direction Générale des Finances Publiques (DGFiP)
|
||||||
|
scopes:
|
||||||
|
declarant: &declarant
|
||||||
|
nom: name
|
||||||
|
nomNaissance: birth name
|
||||||
|
prenoms: firstname
|
||||||
|
dateNaissance: birth date
|
||||||
|
declarant1:
|
||||||
|
libelle: declarant 1
|
||||||
|
<<: *declarant
|
||||||
|
declarant2:
|
||||||
|
libelle: declarant 2
|
||||||
|
<<: *declarant
|
||||||
|
echeance_avis:
|
||||||
|
libelle: expiry of the notice
|
||||||
|
dateEtablissement: date of establishment
|
||||||
|
dateRecouvrement: recovery date
|
||||||
|
foyer_fiscal: &foyer_fiscal
|
||||||
|
libelle: taxable household
|
||||||
|
adresse: tax address for the year
|
||||||
|
annee: year
|
||||||
|
nombreParts: number of units
|
||||||
|
nombrePersonnesCharge: number of dependants
|
||||||
|
situationFamille: family status
|
||||||
|
agregats_fiscaux:
|
||||||
|
libelle: tax notice
|
||||||
|
revenuBrutGlobal: overall gross income
|
||||||
|
revenuImposable: taxable income
|
||||||
|
impotRevenuNetAvantCorrections: net income tax before correction
|
||||||
|
montantImpot: tax amount
|
||||||
|
revenuFiscalReference: reference tax income
|
||||||
|
anneeImpots: tax year
|
||||||
|
anneeRevenus: income year
|
||||||
|
complements:
|
||||||
|
libelle: supplements
|
||||||
|
erreurCorrectif: error correction
|
||||||
|
situationPartielle: partial status
|
||||||
|
|
|
@ -30,3 +30,41 @@ fr:
|
||||||
quotientFamilial: quotient familial
|
quotientFamilial: quotient familial
|
||||||
mois: mois
|
mois: mois
|
||||||
annee: année
|
annee: année
|
||||||
|
dgfip:
|
||||||
|
libelle: Direction Générale des Finances Publiques (DGFiP)
|
||||||
|
scopes:
|
||||||
|
declarant: &declarant
|
||||||
|
nom: nom
|
||||||
|
nomNaissance: nom de naissance
|
||||||
|
prenoms: prénoms
|
||||||
|
dateNaissance: date de naissance
|
||||||
|
declarant1:
|
||||||
|
libelle: déclarant 1
|
||||||
|
<<: *declarant
|
||||||
|
declarant2:
|
||||||
|
libelle: déclarant 2
|
||||||
|
<<: *declarant
|
||||||
|
echeance_avis:
|
||||||
|
libelle: échéance de l’avis
|
||||||
|
dateEtablissement: date d’établissement
|
||||||
|
dateRecouvrement: date de recouvrement
|
||||||
|
foyer_fiscal: &foyer_fiscal
|
||||||
|
libelle: foyer fiscal
|
||||||
|
adresse: adresse fiscale de l’année passée
|
||||||
|
annee: année
|
||||||
|
nombreParts: nombre de parts
|
||||||
|
nombrePersonnesCharge: nombre de personnes à charge
|
||||||
|
situationFamille: situation familiale
|
||||||
|
agregats_fiscaux:
|
||||||
|
libelle: agrégats fiscaux
|
||||||
|
revenuBrutGlobal: revenu brut global
|
||||||
|
revenuImposable: revenu imposable
|
||||||
|
impotRevenuNetAvantCorrections: impôt sur le revenu net avant correction
|
||||||
|
montantImpot: montant de l’impôt
|
||||||
|
revenuFiscalReference: revenu fiscal de référence
|
||||||
|
anneeImpots: année d’imposition
|
||||||
|
anneeRevenus: année des revenus
|
||||||
|
complements:
|
||||||
|
libelle: compléments
|
||||||
|
erreurCorrectif: erreur correctif
|
||||||
|
situationPartielle: situation partielle
|
||||||
|
|
|
@ -291,6 +291,12 @@ en:
|
||||||
invalid: "must be a maximum of 7 digits"
|
invalid: "must be a maximum of 7 digits"
|
||||||
code_postal:
|
code_postal:
|
||||||
invalid: "must be 5 characters long"
|
invalid: "must be 5 characters long"
|
||||||
|
"champs/dgfip_champ":
|
||||||
|
attributes:
|
||||||
|
numero_fiscal:
|
||||||
|
invalid: "must be 13 or 14 characters long"
|
||||||
|
reference_avis:
|
||||||
|
invalid: "must be 13 or 14 characters long"
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
dossier_not_found: "The file does not exist or you do not have access to it."
|
dossier_not_found: "The file does not exist or you do not have access to it."
|
||||||
|
|
|
@ -299,6 +299,12 @@ fr:
|
||||||
invalid: "doit être composé au maximum de 7 chiffres"
|
invalid: "doit être composé au maximum de 7 chiffres"
|
||||||
code_postal:
|
code_postal:
|
||||||
invalid: "doit posséder 5 caractères"
|
invalid: "doit posséder 5 caractères"
|
||||||
|
"champs/dgfip_champ":
|
||||||
|
attributes:
|
||||||
|
numero_fiscal:
|
||||||
|
invalid: "doit posséder 13 ou 14 caractères"
|
||||||
|
reference_avis:
|
||||||
|
invalid: "doit posséder 13 ou 14 caractères"
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
saml_not_authorized: "Vous n’êtes pas autorisé à accéder à ce service."
|
saml_not_authorized: "Vous n’êtes pas autorisé à accéder à ce service."
|
||||||
|
@ -414,12 +420,12 @@ fr:
|
||||||
jeton_particulier:
|
jeton_particulier:
|
||||||
show:
|
show:
|
||||||
configure_token: "Configurer le jeton API Particulier"
|
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 de récupérer les données familiales (CAF).<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 de récupérer les données fiscales (DGFiP) et familiales (CAF).<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."
|
token_description: "Il doit contenir au minimum 15 caractères."
|
||||||
update:
|
update:
|
||||||
token_ok: "Le jeton a bien été mis à jour"
|
token_ok: "Le jeton a bien été mis à jour"
|
||||||
no_scopes_token: "Mise à jour impossible : le jeton n'a pas acces aux données.<br /><br />Vérifier le auprès de <a href='https://datapass.api.gouv.fr/'>https://datapass.api.gouv.fr/</a>"
|
no_scopes_token: "Mise à jour impossible : le jeton n'a pas acces aux données.<br /><br />Vérifiez-le auprès de <a href='https://datapass.api.gouv.fr/'>https://datapass.api.gouv.fr/</a>"
|
||||||
not_found_token: "Mise à jour impossible : le jeton n'a pas été trouvé ou n'est pas actif<br /><br />Vérifier le auprès de <a href='https://datapass.api.gouv.fr/'>https://datapass.api.gouv.fr/</a>"
|
not_found_token: "Mise à jour impossible : le jeton n'a pas été trouvé ou n'est pas actif<br /><br />Vérifiez-le auprès de <a href='https://datapass.api.gouv.fr/'>https://datapass.api.gouv.fr/</a>"
|
||||||
network_error: "Mise à jour impossible : une erreur réseau est survenue"
|
network_error: "Mise à jour impossible : une erreur réseau est survenue"
|
||||||
api_particulier:
|
api_particulier:
|
||||||
already_configured: "Déjà rempli"
|
already_configured: "Déjà rempli"
|
||||||
|
@ -428,7 +434,7 @@ fr:
|
||||||
show:
|
show:
|
||||||
title: "Définir les sources de données"
|
title: "Définir les sources de données"
|
||||||
data_sources: "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>"
|
explication_html: "<p>API Particulier facilite l’accès des administrations aux données fiscales (DGFiP) et 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>"
|
||||||
update:
|
update:
|
||||||
sources_ok: 'Mise à jour effectuée'
|
sources_ok: 'Mise à jour effectuée'
|
||||||
procedures:
|
procedures:
|
||||||
|
|
|
@ -37,4 +37,4 @@ fr:
|
||||||
iban: 'Iban'
|
iban: 'Iban'
|
||||||
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'
|
||||||
|
|
|
@ -7,6 +7,11 @@ en:
|
||||||
numero_allocataire_notice: It is usually composed of 7 digits.
|
numero_allocataire_notice: It is usually composed of 7 digits.
|
||||||
code_postal_label: postal code
|
code_postal_label: postal code
|
||||||
code_postal_notice: It is usually composed of 5 digits.
|
code_postal_notice: It is usually composed of 5 digits.
|
||||||
|
dgfip:
|
||||||
|
numero_fiscal_label: Tax number
|
||||||
|
numero_fiscal_notice: It is usually composed of 13 to 14 characters.
|
||||||
|
reference_avis_label: Tax notice reference
|
||||||
|
reference_avis_notice: It is usually composed of 13 to 14 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)"
|
||||||
|
@ -22,3 +27,9 @@ en:
|
||||||
fetching_data: "Fetching data for recipient No. %{numero_allocataire} with postal code %{code_postal}."
|
fetching_data: "Fetching data for recipient No. %{numero_allocataire} with postal code %{code_postal}."
|
||||||
data_fetched: "Data concerning %{sources} linked to the account Nº %{numero_allocataire} with the postal code %{code_postal} has been received from the CAF."
|
data_fetched: "Data concerning %{sources} linked to the account Nº %{numero_allocataire} with the postal code %{code_postal} has been received from the CAF."
|
||||||
data_fetched_title: "Data received from la Caisse nationale d’allocations familiales"
|
data_fetched_title: "Data received from la Caisse nationale d’allocations familiales"
|
||||||
|
dgfip:
|
||||||
|
show:
|
||||||
|
not_filled: not filled
|
||||||
|
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_title: "Data received from la Direction générale des Finances publiques"
|
||||||
|
|
|
@ -7,6 +7,11 @@ fr:
|
||||||
numero_allocataire_notice: Il est généralement composé de 7 chiffres.
|
numero_allocataire_notice: Il est généralement composé de 7 chiffres.
|
||||||
code_postal_label: Le code postal
|
code_postal_label: Le code postal
|
||||||
code_postal_notice: Il est généralement composé de 5 chiffres.
|
code_postal_notice: Il est généralement composé de 5 chiffres.
|
||||||
|
dgfip:
|
||||||
|
numero_fiscal_label: Le numéro fiscal
|
||||||
|
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_notice: Elle est généralement composée de 13 ou 14 caractères.
|
||||||
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)"
|
||||||
|
@ -24,3 +29,9 @@ fr:
|
||||||
fetching_data: "La récupération automatique des données pour l’allocataire Nº %{numero_allocataire} avec le code postal %{code_postal} est en cours."
|
fetching_data: "La récupération automatique des données pour l’allocataire Nº %{numero_allocataire} avec le code postal %{code_postal} est en cours."
|
||||||
data_fetched: "Des données concernant %{sources} liées au compte Nº %{numero_allocataire} avec le code postal %{code_postal} ont été reçues depuis la CAF."
|
data_fetched: "Des données concernant %{sources} liées au compte Nº %{numero_allocataire} avec le code postal %{code_postal} ont été reçues depuis la CAF."
|
||||||
data_fetched_title: "Données obtenues de la Caisse nationale d’allocations familiales"
|
data_fetched_title: "Données obtenues de la Caisse nationale d’allocations familiales"
|
||||||
|
dgfip:
|
||||||
|
show:
|
||||||
|
not_filled: non renseigné
|
||||||
|
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_title: "Données obtenues de la Direction générale des Finances publiques"
|
||||||
|
|
|
@ -45,9 +45,39 @@ describe Administrateurs::JetonParticulierController, type: :controller do
|
||||||
it 'saves the jeton' do
|
it 'saves the jeton' do
|
||||||
expect(flash.alert).to be_nil
|
expect(flash.alert).to be_nil
|
||||||
expect(flash.notice).to eq("Le jeton a bien été mis à jour")
|
expect(flash.notice).to eq("Le jeton a bien été mis à jour")
|
||||||
expect(procedure.reload.api_particulier_token).to eql(token)
|
procedure.reload
|
||||||
expect(procedure.reload.api_particulier_scopes).to contain_exactly("dgfip_avis_imposition", "dgfip_adresse", "cnaf_allocataires", "cnaf_enfants", "cnaf_adresse", "cnaf_quotient_familial", "mesri_statut_etudiant")
|
expect(procedure.api_particulier_token).to eql(token)
|
||||||
expect(procedure.reload.api_particulier_sources).to be_empty
|
expect(procedure.api_particulier_scopes).to contain_exactly(
|
||||||
|
'cnaf_adresse',
|
||||||
|
'cnaf_allocataires',
|
||||||
|
'cnaf_enfants',
|
||||||
|
'cnaf_quotient_familial',
|
||||||
|
'dgfip_adresse_fiscale_annee',
|
||||||
|
'dgfip_adresse_fiscale_taxation',
|
||||||
|
'dgfip_annee_impot',
|
||||||
|
'dgfip_annee_revenus',
|
||||||
|
'dgfip_date_etablissement',
|
||||||
|
'dgfip_date_recouvrement',
|
||||||
|
'dgfip_declarant1_date_naissance',
|
||||||
|
'dgfip_declarant1_nom',
|
||||||
|
'dgfip_declarant1_nom_naissance',
|
||||||
|
'dgfip_declarant1_prenoms',
|
||||||
|
'dgfip_declarant2_date_naissance',
|
||||||
|
'dgfip_declarant2_nom',
|
||||||
|
'dgfip_declarant2_nom_naissance',
|
||||||
|
'dgfip_declarant2_prenoms',
|
||||||
|
'dgfip_erreur_correctif',
|
||||||
|
'dgfip_impot_revenu_net_avant_corrections',
|
||||||
|
'dgfip_montant_impot',
|
||||||
|
'dgfip_nombre_parts',
|
||||||
|
'dgfip_nombre_personnes_a_charge',
|
||||||
|
'dgfip_revenu_brut_global',
|
||||||
|
'dgfip_revenu_fiscal_reference',
|
||||||
|
'dgfip_revenu_imposable',
|
||||||
|
'dgfip_situation_familiale',
|
||||||
|
'dgfip_situation_partielle'
|
||||||
|
)
|
||||||
|
expect(procedure.api_particulier_sources).to be_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,10 @@ FactoryBot.define do
|
||||||
type_de_champ { association :type_de_champ_cnaf, procedure: dossier.procedure }
|
type_de_champ { association :type_de_champ_cnaf, procedure: dossier.procedure }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :champ_dgfip, class: 'Champs::DgfipChamp' do
|
||||||
|
type_de_champ { association :type_de_champ_dgfip, 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]
|
||||||
|
|
|
@ -200,6 +200,12 @@ FactoryBot.define do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :with_dgfip do
|
||||||
|
after(:build) do |procedure, _evaluator|
|
||||||
|
build(:type_de_champ_dgfip, 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)
|
||||||
|
|
|
@ -157,6 +157,9 @@ FactoryBot.define do
|
||||||
factory :type_de_champ_cnaf do
|
factory :type_de_champ_cnaf do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:cnaf) }
|
type_champ { TypeDeChamp.type_champs.fetch(:cnaf) }
|
||||||
end
|
end
|
||||||
|
factory :type_de_champ_dgfip do
|
||||||
|
type_champ { TypeDeChamp.type_champs.fetch(:dgfip) }
|
||||||
|
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
|
||||||
|
|
84
spec/fixtures/cassettes/api_particulier/success/avis_imposition.yml
vendored
Normal file
84
spec/fixtures/cassettes/api_particulier/success/avis_imposition.yml
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
---
|
||||||
|
http_interactions:
|
||||||
|
- request:
|
||||||
|
method: get
|
||||||
|
uri: https://particulier.api.gouv.fr/api/v2/avis-imposition?numeroFiscal=2097699999077&referenceAvis=2097699999077
|
||||||
|
body:
|
||||||
|
encoding: US-ASCII
|
||||||
|
string: ''
|
||||||
|
headers:
|
||||||
|
User-Agent:
|
||||||
|
- demarches-simplifiees.fr
|
||||||
|
Accept:
|
||||||
|
- application/json
|
||||||
|
X-Api-Key:
|
||||||
|
- d7e9c9f4c3ca00caadde31f50fd4521a
|
||||||
|
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:
|
||||||
|
- '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: '{
|
||||||
|
"declarant1": {
|
||||||
|
"nom": "FERRI",
|
||||||
|
"nomNaissance": "FERRI",
|
||||||
|
"prenoms": "Karine",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"declarant2": {
|
||||||
|
"nom": "",
|
||||||
|
"nomNaissance": "",
|
||||||
|
"prenoms": "",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"dateRecouvrement": "09/10/2020",
|
||||||
|
"dateEtablissement": "07/07/2020",
|
||||||
|
"nombreParts": 1,
|
||||||
|
"situationFamille": "Célibataire",
|
||||||
|
"nombrePersonnesCharge": 0,
|
||||||
|
"revenuBrutGlobal": 38814,
|
||||||
|
"revenuImposable": 38814,
|
||||||
|
"impotRevenuNetAvantCorrections": 38814,
|
||||||
|
"montantImpot": 38814,
|
||||||
|
"revenuFiscalReference": 38814,
|
||||||
|
"foyerFiscal": {
|
||||||
|
"annee": 2020,
|
||||||
|
"adresse": "13 rue de la Plage 97615 Pamanzi"
|
||||||
|
},
|
||||||
|
"anneeImpots": "2020",
|
||||||
|
"anneeRevenus": "2020",
|
||||||
|
"situationPartielle": "SUP DOM"
|
||||||
|
}'
|
||||||
|
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
|
||||||
|
recorded_with: VCR 6.0.0
|
84
spec/fixtures/cassettes/api_particulier/success/avis_imposition_invalid.yml
vendored
Normal file
84
spec/fixtures/cassettes/api_particulier/success/avis_imposition_invalid.yml
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
---
|
||||||
|
http_interactions:
|
||||||
|
- request:
|
||||||
|
method: get
|
||||||
|
uri: https://particulier.api.gouv.fr/api/v2/avis-imposition?numeroFiscal=2097699999077&referenceAvis=2097699999077
|
||||||
|
body:
|
||||||
|
encoding: US-ASCII
|
||||||
|
string: ''
|
||||||
|
headers:
|
||||||
|
User-Agent:
|
||||||
|
- demarches-simplifiees.fr
|
||||||
|
Accept:
|
||||||
|
- application/json
|
||||||
|
X-Api-Key:
|
||||||
|
- d7e9c9f4c3ca00caadde31f50fd4521a
|
||||||
|
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:
|
||||||
|
- '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: '{
|
||||||
|
"declarant1": {
|
||||||
|
"nom": "FERRI",
|
||||||
|
"nomNaissance": "FERRI",
|
||||||
|
"prenoms": "Karine",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"declarant2": {
|
||||||
|
"nom": "",
|
||||||
|
"nomNaissance": "",
|
||||||
|
"prenoms": "",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"dateRecouvrement": "09/10/2020",
|
||||||
|
"dateEtablissement": "07/07/2020",
|
||||||
|
"nombreParts": 1,
|
||||||
|
"situationFamille": "Célibataire",
|
||||||
|
"nombrePersonnesCharge": 0,
|
||||||
|
"revenuBrutGlobal": 38814,
|
||||||
|
"revenuImposable": 38814,
|
||||||
|
"impotRevenuNetAvantCorrections": 38814,
|
||||||
|
"montantImpot": 38814,
|
||||||
|
"revenuFiscalReference": 38814,
|
||||||
|
"foyerFiscal": {
|
||||||
|
"annee": 2020,
|
||||||
|
"adresse": "13 rue de la Plage 97615 Pamanzi"
|
||||||
|
},
|
||||||
|
"anneeImpots": "99",
|
||||||
|
"anneeRevenus": "2020",
|
||||||
|
"situationPartielle": "SUP DOM"
|
||||||
|
}'
|
||||||
|
recorded_at: Tue, 16 Mar 2021 17:01:18 GMT
|
||||||
|
recorded_with: VCR 6.0.0
|
|
@ -38,7 +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
|
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"]}'
|
||||||
sandbox","scopes":["dgfip_avis_imposition","dgfip_adresse","cnaf_allocataires","cnaf_enfants","cnaf_adresse","cnaf_quotient_familial","mesri_statut_etudiant"]}'
|
|
||||||
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
|
||||||
|
|
37
spec/fixtures/files/api_particulier/avis_imposition.json
vendored
Normal file
37
spec/fixtures/files/api_particulier/avis_imposition.json
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"declarant1": {
|
||||||
|
"nom": "FERRI",
|
||||||
|
"nomNaissance": "FERRI",
|
||||||
|
"prenoms": "Karine",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"declarant2": {
|
||||||
|
"nom": "",
|
||||||
|
"nomNaissance": "",
|
||||||
|
"prenoms": "",
|
||||||
|
"dateNaissance": "12/08/1978"
|
||||||
|
},
|
||||||
|
"echeance_avis": {
|
||||||
|
"dateRecouvrement": "09/10/2020",
|
||||||
|
"dateEtablissement": "07/07/2020"
|
||||||
|
},
|
||||||
|
"foyer_fiscal": {
|
||||||
|
"annee": 2020,
|
||||||
|
"adresse": "13 rue de la Plage 97615 Pamanzi",
|
||||||
|
"nombreParts": 1,
|
||||||
|
"situationFamille": "Célibataire",
|
||||||
|
"nombrePersonnesCharge": 0
|
||||||
|
},
|
||||||
|
"agregats_fiscaux": {
|
||||||
|
"revenuBrutGlobal": 38814,
|
||||||
|
"revenuImposable": 38814,
|
||||||
|
"impotRevenuNetAvantCorrections": 38814,
|
||||||
|
"montantImpot": 38814,
|
||||||
|
"revenuFiscalReference": 38814,
|
||||||
|
"anneeImpots": "2020",
|
||||||
|
"anneeRevenus": "2020"
|
||||||
|
},
|
||||||
|
"complements": {
|
||||||
|
"situationPartielle": "SUP DOM"
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,36 @@ describe APIParticulier::API do
|
||||||
|
|
||||||
it "doit retourner une liste de scopes" do
|
it "doit retourner une liste de scopes" do
|
||||||
VCR.use_cassette("api_particulier/success/introspect") do
|
VCR.use_cassette("api_particulier/success/introspect") do
|
||||||
expect(subject).to match_array(['dgfip_avis_imposition', 'dgfip_adresse', 'cnaf_allocataires', 'cnaf_enfants', 'cnaf_adresse', 'cnaf_quotient_familial', 'mesri_statut_etudiant'])
|
expect(subject).to contain_exactly(
|
||||||
|
'cnaf_adresse',
|
||||||
|
'cnaf_allocataires',
|
||||||
|
'cnaf_enfants',
|
||||||
|
'cnaf_quotient_familial',
|
||||||
|
'dgfip_adresse_fiscale_annee',
|
||||||
|
'dgfip_adresse_fiscale_taxation',
|
||||||
|
'dgfip_annee_impot',
|
||||||
|
'dgfip_annee_revenus',
|
||||||
|
'dgfip_date_etablissement',
|
||||||
|
'dgfip_date_recouvrement',
|
||||||
|
'dgfip_declarant1_date_naissance',
|
||||||
|
'dgfip_declarant1_nom',
|
||||||
|
'dgfip_declarant1_nom_naissance',
|
||||||
|
'dgfip_declarant1_prenoms',
|
||||||
|
'dgfip_declarant2_date_naissance',
|
||||||
|
'dgfip_declarant2_nom',
|
||||||
|
'dgfip_declarant2_nom_naissance',
|
||||||
|
'dgfip_declarant2_prenoms',
|
||||||
|
'dgfip_erreur_correctif',
|
||||||
|
'dgfip_impot_revenu_net_avant_corrections',
|
||||||
|
'dgfip_montant_impot',
|
||||||
|
'dgfip_nombre_parts',
|
||||||
|
'dgfip_nombre_personnes_a_charge',
|
||||||
|
'dgfip_revenu_brut_global',
|
||||||
|
'dgfip_revenu_fiscal_reference',
|
||||||
|
'dgfip_revenu_imposable',
|
||||||
|
'dgfip_situation_familiale',
|
||||||
|
'dgfip_situation_partielle'
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ describe APIParticulier::CnafAdapter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the api answer is valid' do
|
context 'when the api answer is invalid' do
|
||||||
let(:cassette) { "api_particulier/success/composition_familiale_invalid" }
|
let(:cassette) { "api_particulier/success/composition_familiale_invalid" }
|
||||||
|
|
||||||
context 'when no sources is requested' do
|
context 'when no sources is requested' do
|
||||||
|
|
66
spec/lib/api_particulier/dgfip_adapter_spec.rb
Normal file
66
spec/lib/api_particulier/dgfip_adapter_spec.rb
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
describe APIParticulier::DgfipAdapter do
|
||||||
|
let(:adapter) { described_class.new(api_particulier_token, numero_fiscal, reference_avis, requested_sources) }
|
||||||
|
|
||||||
|
before { stub_const('API_PARTICULIER_URL', 'https://particulier.api.gouv.fr/api') }
|
||||||
|
|
||||||
|
describe '#to_params' do
|
||||||
|
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
|
||||||
|
let(:numero_fiscal) { '2097699999077' }
|
||||||
|
let(:reference_avis) { '2097699999077' }
|
||||||
|
|
||||||
|
subject { VCR.use_cassette(cassette) { adapter.to_params } }
|
||||||
|
|
||||||
|
context 'when the api answer is valid' do
|
||||||
|
let(:cassette) { 'api_particulier/success/avis_imposition' }
|
||||||
|
|
||||||
|
context 'when the token has all the dgfip scopes' do
|
||||||
|
context 'and all the sources are requested' do
|
||||||
|
let(:requested_sources) do
|
||||||
|
{
|
||||||
|
"dgfip" => {
|
||||||
|
"declarant1" => ["nom", "nomNaissance", "prenoms", "dateNaissance"],
|
||||||
|
"declarant2" => ["nom", "nomNaissance", "prenoms", "dateNaissance"],
|
||||||
|
"echeance_avis" => ["dateRecouvrement", "dateEtablissement"],
|
||||||
|
"foyer_fiscal" => ["adresse", "annee", "nombreParts", "nombrePersonnesCharge", "situationFamille"],
|
||||||
|
"agregats_fiscaux" => ["revenuBrutGlobal", "revenuImposable", "impotRevenuNetAvantCorrections", "montantImpot", "revenuFiscalReference", "anneeImpots", "anneeRevenus"],
|
||||||
|
"complements" => ["erreurCorrectif", "situationPartielle"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:result) { JSON.parse(File.read('spec/fixtures/files/api_particulier/avis_imposition.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 a declarer name is requested' do
|
||||||
|
let(:requested_sources) { { 'dgfip' => { 'declarant1' => ['nom'] } } }
|
||||||
|
|
||||||
|
it { is_expected.to eq('declarant1' => { 'nom' => 'FERRI' }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a revenue is requested' do
|
||||||
|
let(:requested_sources) { { 'dgfip' => { 'agregats_fiscaux' => ['revenuBrutGlobal'] } } }
|
||||||
|
|
||||||
|
it { is_expected.to eq('agregats_fiscaux' => { 'revenuBrutGlobal' => 38814 }) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the api answer is invalid' do
|
||||||
|
let(:cassette) { 'api_particulier/success/avis_imposition_invalid' }
|
||||||
|
|
||||||
|
context 'when no sources is requested' do
|
||||||
|
let(:requested_sources) { {} }
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error(APIParticulier::DgfipAdapter::InvalidSchemaError) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,7 +17,7 @@ describe APIParticulier::Services::SourcesService do
|
||||||
it { is_expected.to eq({}) }
|
it { is_expected.to eq({}) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a procedure has a cnaf_allocataires and a cnaf_adresse scopes' do
|
context 'when a procedure has a cnaf_allocataires and a cnaf_enfants scopes' do
|
||||||
let(:api_particulier_scopes) { ['cnaf_allocataires', 'cnaf_enfants'] }
|
let(:api_particulier_scopes) { ['cnaf_allocataires', 'cnaf_enfants'] }
|
||||||
|
|
||||||
let(:cnaf_allocataires_and_enfants) do
|
let(:cnaf_allocataires_and_enfants) do
|
||||||
|
@ -32,6 +32,21 @@ describe APIParticulier::Services::SourcesService do
|
||||||
it { is_expected.to match(cnaf_allocataires_and_enfants) }
|
it { is_expected.to match(cnaf_allocataires_and_enfants) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when a procedure has a dgfip_declarant1_nom , prenom and a dgfip_adresse_fiscale_taxation scopes' do
|
||||||
|
let(:api_particulier_scopes) { ['dgfip_declarant1_nom', 'dgfip_declarant1_prenoms', 'dgfip_adresse_fiscale_taxation'] }
|
||||||
|
|
||||||
|
let(:dgfip_avis_imposition_et_adresse) do
|
||||||
|
{
|
||||||
|
'dgfip' => {
|
||||||
|
'declarant1' => ['nom', 'prenoms'],
|
||||||
|
'foyer_fiscal' => ['adresse']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to match(dgfip_avis_imposition_et_adresse) }
|
||||||
|
end
|
||||||
|
|
||||||
context 'when a procedure has an unknown scope' do
|
context 'when a procedure has an unknown scope' do
|
||||||
let(:api_particulier_scopes) { ['unknown_scope'] }
|
let(:api_particulier_scopes) { ['unknown_scope'] }
|
||||||
|
|
||||||
|
|
103
spec/models/champs/dgfip_champ_spec.rb
Normal file
103
spec/models/champs/dgfip_champ_spec.rb
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
describe Champs::DgfipChamp, type: :model do
|
||||||
|
let(:champ) { described_class.new }
|
||||||
|
|
||||||
|
describe 'numero_fiscal and reference_avis' do
|
||||||
|
before do
|
||||||
|
champ.numero_fiscal = '1122299999092'
|
||||||
|
champ.reference_avis = 'FC22299999092'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'saves numero_fiscal and reference_avis' do
|
||||||
|
expect(champ.numero_fiscal).to eq('1122299999092')
|
||||||
|
expect(champ.reference_avis).to eq('FC22299999092')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'external_id' do
|
||||||
|
context 'when only one data is given' do
|
||||||
|
before do
|
||||||
|
champ.numero_fiscal = '1122299999092'
|
||||||
|
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.numero_fiscal = '1122299999092'
|
||||||
|
champ.reference_avis = 'FC22299999092'
|
||||||
|
champ.save
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(JSON.parse(champ.external_id)).to eq({ "reference_avis" => "FC22299999092", "numero_fiscal" => "1122299999092" }) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#validate' do
|
||||||
|
let(:numero_fiscal) { '1122299999092' }
|
||||||
|
let(:reference_avis) { 'FC22299999092' }
|
||||||
|
let(:champ) { described_class.new(dossier: create(:dossier), type_de_champ: create(:type_de_champ_dgfip)) }
|
||||||
|
let(:validation_context) { :create }
|
||||||
|
|
||||||
|
subject { champ.valid?(validation_context) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
champ.numero_fiscal = numero_fiscal
|
||||||
|
champ.reference_avis = reference_avis
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when numero_fiscal and reference_avis are valid' do
|
||||||
|
it { is_expected.to be true }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when numero_fiscal and reference_avis are nil' do
|
||||||
|
let(:numero_fiscal) { nil }
|
||||||
|
let(:reference_avis) { nil }
|
||||||
|
|
||||||
|
it { is_expected.to be true }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when only reference_avis is nil' do
|
||||||
|
let(:reference_avis) { nil }
|
||||||
|
|
||||||
|
it do
|
||||||
|
is_expected.to be false
|
||||||
|
expect(champ.errors.full_messages).to eq(["Reference avis doit posséder 13 ou 14 caractères"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when only numero_fiscal is nil' do
|
||||||
|
let(:numero_fiscal) { nil }
|
||||||
|
|
||||||
|
it do
|
||||||
|
is_expected.to be false
|
||||||
|
expect(champ.errors.full_messages).to eq(["Numero fiscal doit posséder 13 ou 14 caractères"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when numero_fiscal is invalid' do
|
||||||
|
let(:numero_fiscal) { '11222' }
|
||||||
|
|
||||||
|
it do
|
||||||
|
is_expected.to be false
|
||||||
|
expect(champ.errors.full_messages).to eq(["Numero fiscal doit posséder 13 ou 14 caractères"])
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the validation_context is :brouillon' do
|
||||||
|
let(:validation_context) { :brouillon }
|
||||||
|
|
||||||
|
it { is_expected.to be true }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when reference_avis is invalid' do
|
||||||
|
let(:reference_avis) { 'FC222' }
|
||||||
|
|
||||||
|
it do
|
||||||
|
is_expected.to be false
|
||||||
|
expect(champ.errors.full_messages).to eq(["Reference avis doit posséder 13 ou 14 caractères"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -78,6 +78,7 @@ describe ProcedureExportService do
|
||||||
"iban",
|
"iban",
|
||||||
"annuaire_education",
|
"annuaire_education",
|
||||||
"cnaf",
|
"cnaf",
|
||||||
|
"dgfip",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -166,6 +167,7 @@ describe ProcedureExportService do
|
||||||
"iban",
|
"iban",
|
||||||
"annuaire_education",
|
"annuaire_education",
|
||||||
"cnaf",
|
"cnaf",
|
||||||
|
"dgfip",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -250,6 +252,7 @@ describe ProcedureExportService do
|
||||||
"iban",
|
"iban",
|
||||||
"annuaire_education",
|
"annuaire_education",
|
||||||
"cnaf",
|
"cnaf",
|
||||||
|
"dgfip",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,35 +5,44 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
|
|
||||||
let(:expected_sources) do
|
let(:expected_sources) do
|
||||||
{
|
{
|
||||||
"cnaf" =>
|
'cnaf' =>
|
||||||
{
|
{
|
||||||
"adresse" => ["identite", "complementIdentite", "complementIdentiteGeo", "numeroRue", "lieuDit", "codePostalVille", "pays"],
|
'adresse' => ['identite', 'complementIdentite', 'complementIdentiteGeo', 'numeroRue', 'lieuDit', 'codePostalVille', 'pays'],
|
||||||
"allocataires" => ["nomPrenom", "dateDeNaissance", "sexe"],
|
'allocataires' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||||
"enfants" => ["nomPrenom", "dateDeNaissance", "sexe"],
|
'enfants' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||||
"quotient_familial" => ["quotientFamilial", "annee", "mois"]
|
'quotient_familial' => ['quotientFamilial', 'annee', 'mois']
|
||||||
|
},
|
||||||
|
'dgfip' =>
|
||||||
|
{
|
||||||
|
'declarant1' => ['dateNaissance', 'nom', 'nomNaissance', 'prenoms'],
|
||||||
|
'declarant2' => ['dateNaissance', 'nom', 'nomNaissance', 'prenoms'],
|
||||||
|
'echeance_avis' => ['dateEtablissement', 'dateRecouvrement'],
|
||||||
|
'foyer_fiscal' => ['adresse', 'annee', 'nombreParts', 'nombrePersonnesCharge', 'situationFamille'],
|
||||||
|
'agregats_fiscaux' => ['anneeImpots', 'anneeRevenus', 'impotRevenuNetAvantCorrections', 'montantImpot', 'revenuBrutGlobal', 'revenuFiscalReference', 'revenuImposable'],
|
||||||
|
'complements' => ['situationPartielle', 'erreurCorrectif']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_const("API_PARTICULIER_URL", "https://particulier.api.gouv.fr/api")
|
stub_const('API_PARTICULIER_URL', 'https://particulier.api.gouv.fr/api')
|
||||||
Flipper.enable(:api_particulier)
|
Flipper.enable(:api_particulier)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when an administrateur is logged" do
|
context 'when an administrateur is logged' 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,
|
||||||
administrateurs: [administrateur],
|
administrateurs: [administrateur],
|
||||||
libelle: "libellé de la procédure",
|
libelle: 'libellé de la procédure',
|
||||||
path: "libelle-de-la-procedure")
|
path: 'libelle-de-la-procedure')
|
||||||
end
|
end
|
||||||
|
|
||||||
before { login_as administrateur.user, scope: :user }
|
before { login_as administrateur.user, scope: :user }
|
||||||
|
|
||||||
scenario 'it can enable api particulier' do
|
scenario 'it can enable api particulier' do
|
||||||
visit admin_procedure_path(procedure)
|
visit admin_procedure_path(procedure)
|
||||||
expect(page).to have_content("Configurer le jeton API particulier")
|
expect(page).to have_content('Configurer le jeton API particulier')
|
||||||
|
|
||||||
find('#api-particulier').click
|
find('#api-particulier').click
|
||||||
expect(page).to have_current_path(admin_procedure_api_particulier_path(procedure))
|
expect(page).to have_current_path(admin_procedure_api_particulier_path(procedure))
|
||||||
|
@ -42,7 +51,7 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
expect(page).to have_current_path(admin_procedure_api_particulier_jeton_path(procedure))
|
expect(page).to have_current_path(admin_procedure_api_particulier_jeton_path(procedure))
|
||||||
|
|
||||||
fill_in 'procedure_api_particulier_token', with: expected_token
|
fill_in 'procedure_api_particulier_token', with: expected_token
|
||||||
VCR.use_cassette("api_particulier/success/introspect") { click_on 'Enregistrer' }
|
VCR.use_cassette('api_particulier/success/introspect') { click_on 'Enregistrer' }
|
||||||
expect(page).to have_text('Le jeton a bien été mis à jour')
|
expect(page).to have_text('Le jeton a bien été mis à jour')
|
||||||
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))
|
||||||
|
|
||||||
|
@ -54,7 +63,7 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
within("#adresse") do
|
within('#adresse') do
|
||||||
check('identité')
|
check('identité')
|
||||||
check('complément d’identité')
|
check('complément d’identité')
|
||||||
check('complément d’identité géographique')
|
check('complément d’identité géographique')
|
||||||
|
@ -64,19 +73,67 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
check('pays')
|
check('pays')
|
||||||
end
|
end
|
||||||
|
|
||||||
within("#quotient_familial") do
|
within('#quotient_familial') do
|
||||||
check('quotient familial')
|
check('quotient familial')
|
||||||
check('année')
|
check('année')
|
||||||
check('mois')
|
check('mois')
|
||||||
end
|
end
|
||||||
|
|
||||||
click_on "Enregistrer"
|
['declarant1', 'declarant2'].each do |scope|
|
||||||
|
within("##{scope}") do
|
||||||
|
check('nom')
|
||||||
|
check('nom de naissance')
|
||||||
|
check('prénoms')
|
||||||
|
check('date de naissance')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
within("#enfants") do
|
scroll_to(find('#echeance_avis'))
|
||||||
|
within ('#echeance_avis') do
|
||||||
|
check('date de recouvrement')
|
||||||
|
check("date d’établissement")
|
||||||
|
end
|
||||||
|
|
||||||
|
within('#foyer_fiscal') do
|
||||||
|
check('année')
|
||||||
|
check('adresse')
|
||||||
|
check('nombre de parts')
|
||||||
|
check('situation familiale')
|
||||||
|
check('nombre de personnes à charge')
|
||||||
|
end
|
||||||
|
|
||||||
|
within('#agregats_fiscaux') do
|
||||||
|
check('revenu brut global')
|
||||||
|
check('revenu imposable')
|
||||||
|
check('impôt sur le revenu net avant correction')
|
||||||
|
check("montant de l’impôt")
|
||||||
|
check('revenu fiscal de référence')
|
||||||
|
check("année d’imposition")
|
||||||
|
check('année des revenus')
|
||||||
|
end
|
||||||
|
|
||||||
|
within('#complements') do
|
||||||
|
check('erreur correctif')
|
||||||
|
check('situation partielle')
|
||||||
|
end
|
||||||
|
|
||||||
|
click_on 'Enregistrer'
|
||||||
|
|
||||||
|
within('#enfants') do
|
||||||
expect(find('input[value=nomPrenom]')).to be_checked
|
expect(find('input[value=nomPrenom]')).to be_checked
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(procedure.reload.api_particulier_sources).to eq(expected_sources)
|
procedure.reload
|
||||||
|
|
||||||
|
expect(procedure.api_particulier_sources.keys).to contain_exactly('cnaf', 'dgfip')
|
||||||
|
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')
|
||||||
|
|
||||||
|
procedure.api_particulier_sources.each do |provider, scopes|
|
||||||
|
scopes.each do |scope, fields|
|
||||||
|
expect(fields).to match_array(expected_sources[provider][scope])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
visit champs_admin_procedure_path(procedure)
|
visit champs_admin_procedure_path(procedure)
|
||||||
|
|
||||||
|
@ -101,12 +158,14 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
|
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(:reference_avis) { '2097699999077' }
|
||||||
let(:instructeur) { create(:instructeur) }
|
let(:instructeur) { create(:instructeur) }
|
||||||
|
|
||||||
let(:procedure) do
|
let(:procedure) do
|
||||||
create(:procedure, :for_individual, :with_service, :with_cnaf, :published,
|
create(:procedure, :for_individual, :with_service, :with_cnaf, :with_dgfip, :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],
|
||||||
api_particulier_sources: expected_sources,
|
api_particulier_sources: expected_sources,
|
||||||
api_particulier_token: api_particulier_token)
|
api_particulier_token: api_particulier_token)
|
||||||
|
@ -138,7 +197,7 @@ describe 'fetch API Particulier Data', js: true do
|
||||||
|
|
||||||
fill_in 'Le code postal', with: code_postal
|
fill_in 'Le code postal', with: code_postal
|
||||||
|
|
||||||
VCR.use_cassette("api_particulier/success/composition_familiale") do
|
VCR.use_cassette('api_particulier/success/composition_familiale') do
|
||||||
perform_enqueued_jobs { click_on 'Déposer le dossier' }
|
perform_enqueued_jobs { click_on 'Déposer le dossier' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -163,5 +222,69 @@ 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
|
||||||
|
|
||||||
|
scenario 'it can fill a DGFiP field' do
|
||||||
|
visit commencer_path(path: procedure.path)
|
||||||
|
click_on 'Commencer la démarche'
|
||||||
|
|
||||||
|
choose 'Madame'
|
||||||
|
fill_in 'individual_nom', with: 'FERRI'
|
||||||
|
fill_in 'individual_prenom', with: 'Karine'
|
||||||
|
|
||||||
|
click_button('Continuer')
|
||||||
|
|
||||||
|
fill_in 'Le numéro fiscal', with: numero_fiscal
|
||||||
|
fill_in "La référence d'avis d'imposition", with: 'wrong_code'
|
||||||
|
|
||||||
|
blur
|
||||||
|
expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true)
|
||||||
|
|
||||||
|
dossier = Dossier.last
|
||||||
|
expect(dossier.champs.second.reference_avis).to eq('wrong_code')
|
||||||
|
|
||||||
|
click_on 'Déposer le dossier'
|
||||||
|
expect(page).to have_content(/reference avis doit posséder 13 ou 14 caractères/)
|
||||||
|
|
||||||
|
fill_in "La référence d'avis d'imposition", with: reference_avis
|
||||||
|
|
||||||
|
VCR.use_cassette('api_particulier/success/avis_imposition') 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 la DGFiP/)
|
||||||
|
|
||||||
|
log_out
|
||||||
|
|
||||||
|
login_as instructeur.user, scope: :user
|
||||||
|
|
||||||
|
visit instructeur_dossier_path(procedure, dossier)
|
||||||
|
|
||||||
|
expect(page).to have_content('nom FERRI')
|
||||||
|
expect(page).to have_content('nom de naissance FERRI')
|
||||||
|
expect(page).to have_content('prénoms Karine')
|
||||||
|
expect(page).to have_content('date de naissance 12/08/1978')
|
||||||
|
|
||||||
|
expect(page).to have_content('date de recouvrement 09/10/2020')
|
||||||
|
expect(page).to have_content("date d’établissement 07/07/2020")
|
||||||
|
|
||||||
|
expect(page).to have_content('année 2020')
|
||||||
|
expect(page).to have_content("adresse fiscale de l’année passée 13 rue de la Plage 97615 Pamanzi")
|
||||||
|
expect(page).to have_content('nombre de parts 1')
|
||||||
|
expect(page).to have_content('situation familiale Célibataire')
|
||||||
|
expect(page).to have_content('nombre de personnes à charge 0')
|
||||||
|
|
||||||
|
expect(page).to have_content('revenu brut global 38814')
|
||||||
|
expect(page).to have_content('revenu imposable 38814')
|
||||||
|
expect(page).to have_content('impôt sur le revenu net avant correction 38814')
|
||||||
|
expect(page).to have_content("montant de l’impôt 38814")
|
||||||
|
expect(page).to have_content('revenu fiscal de référence 38814')
|
||||||
|
expect(page).to have_content("année d’imposition 2020")
|
||||||
|
expect(page).to have_content('année des revenus 2020')
|
||||||
|
|
||||||
|
expect(page).to have_content('situation partielle SUP DOM')
|
||||||
|
|
||||||
|
expect(page).not_to have_content('erreur correctif')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue