Skip to content

Commit ef32532

Browse files
authored
Merge pull request #13359 from demarche-numerique/add_avis_imposition
ETQ Instructeur / Usager, j'ai une analyse automatique des avis d'impot
2 parents 690675c + 9367eda commit ef32532

24 files changed

Lines changed: 386 additions & 15 deletions

app/components/dsfr/input_status_message_component.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def referentiel_support_statut?
3737
end
3838

3939
def pjs_statut?
40-
(@champ.rib? || @champ.justificatif_domicile?) && !@champ.idle?
40+
(@champ.rib? || @champ.justificatif_domicile? || @champ.avis_impot?) && !@champ.idle?
4141
end
4242

4343
def address_support_statut?
@@ -130,6 +130,13 @@ def statut_message
130130
else
131131
{ state: :warning, text: t('.pj.justif_domicile.warning') }
132132
end
133+
elsif @champ.avis_impot?
134+
avis = @champ.ocr_result
135+
if avis&.two_ddoc
136+
{ state: :valid, text: t('.pj.avis_impot.valid_html', declarant: avis.declarant_1, reference: avis.reference_avis, annee: avis.annee_des_revenus) }
137+
else
138+
{ state: :warning, text: t('.pj.avis_impot.warning') }
139+
end
133140
else
134141
value_json = @champ.value_json
135142
iban = value_json&.dig('rib', 'iban')

app/components/dsfr/input_status_message_component/input_status_message_component.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ en:
2727
justif_domicile:
2828
warning: "We were unable to verify the address contained in the supporting document.<br>Ignore this message if you are confident your file is correct."
2929
valid_html: "Proof of residence in the name of <strong>%{beneficiary}</strong> (<strong>%{address}</strong>), issued on <strong>%{issue_date}</strong>."
30+
avis_impot:
31+
warning: "We were unable to read the information in the tax notice.<br>Ignore this message if you are confident your file is correct."
32+
valid_html: "Tax notice in the name of <strong>%{declarant}</strong> (reference <strong>%{reference}</strong>), income year <strong>%{annee}</strong>."

app/components/dsfr/input_status_message_component/input_status_message_component.fr.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ fr:
2727
justif_domicile:
2828
warning: "Nous n’avons pas pu vérifier l’adresse contenue dans le justificatif.<br>Ignorez ce message si vous êtes sûr(e) de votre fichier."
2929
valid_html: "Justificatif de domicile au nom de <strong>%{beneficiary}</strong> (<strong>%{address}</strong>), émis le <strong>%{issue_date}</strong>."
30+
avis_impot:
31+
warning: "Nous n’avons pas pu lire les informations de l’avis d’impôt.<br>Ignorez ce message si vous êtes sûr(e) de votre fichier."
32+
valid_html: "Avis d’impôt au nom de <strong>%{declarant}</strong> (référence <strong>%{reference}</strong>), revenus <strong>%{annee}</strong>."
3033

app/components/editable_champ/piece_justificative_component.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def view_as
1414
end
1515

1616
def max
17-
if @champ.rib? || @champ.titre_identite? || @champ.justificatif_domicile?
17+
if @champ.rib? || @champ.titre_identite? || @champ.justificatif_domicile? || @champ.avis_impot?
1818
1
1919
elsif [true, nil].include?(@champ.procedure&.piece_justificative_multiple?)
2020
Attachment::FileFieldComponent::DEFAULT_MAX_ATTACHMENTS

app/components/instructeurs/ocr_viewer_component.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ def data
2121
h = doc.attributes.slice('beneficiary', 'label', 'issue_date')
2222
h['issue_date'] = I18n.l(h['issue_date'], format: :short) if h['issue_date']
2323
h
24+
25+
elsif doc.is_a?(AvisImpot)
26+
h = doc.attributes.slice('declarant_1', 'declarant_2', 'reference_avis', 'annee_des_revenus', 'nombre_de_parts', 'revenu_fiscal_de_reference', 'date_mise_en_recouvrement', 'label')
27+
h['date_mise_en_recouvrement'] = I18n.l(h['date_mise_en_recouvrement'], format: :short) if h['date_mise_en_recouvrement']
28+
h
2429
end
2530

2631
d.map { |k, *tail| [doc.class.human_attribute_name(k), *tail] }

app/models/avis_impot.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
class AvisImpot
4+
include ActiveModel::Model
5+
include ActiveModel::Attributes
6+
7+
# 2ddoc-specific
8+
attribute :two_ddoc, :boolean
9+
attribute :reference_avis, :string
10+
attribute :annee_des_revenus, :integer
11+
attribute :nombre_de_parts, :float
12+
attribute :declarant_1, :string
13+
attribute :declarant_1_numero_fiscal, :string
14+
attribute :declarant_2, :string
15+
attribute :declarant_2_numero_fiscal, :string
16+
attribute :revenu_fiscal_de_reference, :integer
17+
attribute :impot_revenu_net, :integer
18+
attribute :reste_a_payer, :integer
19+
attribute :retenue_a_la_source, :integer
20+
attribute :date_mise_en_recouvrement, :date
21+
22+
# APIGeoService.parse_ban_address output
23+
attribute :label, :string
24+
attribute :type, :string
25+
attribute :street_address, :string
26+
attribute :street_number, :string
27+
attribute :street_name, :string
28+
attribute :postal_code, :string
29+
attribute :city_code, :string
30+
attribute :city_name, :string
31+
attribute :department_code, :string
32+
attribute :department_name, :string
33+
attribute :region_code, :string
34+
attribute :region_name, :string
35+
attribute :country_code, :string
36+
attribute :country_name, :string
37+
end

app/models/champ.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def type_de_champ=(type_de_champ)
9595
:rib?,
9696
:france_connect?,
9797
:justificatif_domicile?,
98+
:avis_impot?,
9899
to: :type_de_champ
99100

100101
delegate(*TypeDeChamp.type_champs.values.map { "#{_1}?".to_sym }, to: :type_de_champ)
@@ -355,7 +356,7 @@ def update_timestamps
355356
dossier.update_columns(attributes)
356357
end
357358

358-
def ocr_compatible? = rib? || justificatif_domicile?
359+
def ocr_compatible? = rib? || justificatif_domicile? || avis_impot?
359360

360361
class NotImplemented < ::StandardError
361362
def initialize(method)

app/models/champs/piece_justificative_champ.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ def ocr_result
3737
RIB.new(value_json.dig('rib'))
3838
elsif justificatif_domicile?
3939
JustificatifDomicile.new(value_json)
40+
elsif avis_impot?
41+
AvisImpot.new(value_json)
4042
end
4143
end
4244

app/models/procedure_revision.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ def compare_type_de_champ(from_type_de_champ, to_type_de_champ, from_coordinates
527527
to_type_de_champ.nature)
528528
end
529529

530-
# titre d'identité, RIB et justificatif de domicile ont des règles spécifiques, pas besoin de comparer les limit de pj (tous limite a 1), les format (tous du scan, et de comparer l'autopurge)
531-
if [to_type_de_champ, from_type_de_champ].none? { |it| it.titre_identite? || it.rib? || it.justificatif_domicile? }
530+
# titre d'identité, RIB, justificatif de domicile et avis d'impôt ont des règles spécifiques, pas besoin de comparer les limit de pj (tous limite a 1), les format (tous du scan, et de comparer l'autopurge)
531+
if [to_type_de_champ, from_type_de_champ].none? { |it| it.titre_identite? || it.rib? || it.justificatif_domicile? || it.avis_impot? }
532532
if from_type_de_champ.pj_limit_formats != to_type_de_champ.pj_limit_formats
533533
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
534534
:pj_limit_formats,

app/models/type_de_champ.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class TypeDeChamp < ApplicationRecord
108108
pre_rempli: 'pre_rempli',
109109
}
110110

111-
enum :nature, %w[non_specifie titre_identite rib justificatif_domicile].index_by(&:itself)
111+
enum :nature, %w[non_specifie titre_identite rib justificatif_domicile avis_impot].index_by(&:itself)
112112

113113
SIMPLE_ROUTABLE_TYPES = [
114114
type_champs.fetch(:drop_down_list),

0 commit comments

Comments
 (0)