From 2eee0cf48b5ce97ec9cbb52ac68e8f7bec8d500f Mon Sep 17 00:00:00 2001 From: Adrien Chardon Date: Tue, 23 May 2023 18:15:21 +0200 Subject: [PATCH] Corrige l'exoneration de la CSG et CRDS pour les non residents (#2104) --- CHANGELOG.md | 14 +++++ .../demographie.py | 11 +++- .../contributions_sociales/activite.py | 11 +++- .../contributions_sociales/base.py | 16 ++++++ .../contributions_sociales/capital.py | 7 +++ .../contributions_sociales/csg_crds.py | 10 ++++ .../model/prestations/minima_sociaux/rsa.py | 4 ++ setup.py | 2 +- .../non_residents_exoneration_csg_crds.yaml | 57 +++++++++++++++++++ 9 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 tests/capital/non_residents_exoneration_csg_crds.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 795cae1d64..20be1ca310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 147.1.1 [#2106](https://github.com/openfisca/openfisca-france/pull/2106) + +* Évolution du système socio-fiscal +* Périodes concernées : après 2019 +* Zones impactées : + * `openfisca_france/model/caracteristiques_socio_demographiques/demographie.py` + * `openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/` + * `openfisca_france/model/prestations/minima_sociaux/rsa.py` + * `tests/` +* Détails : + * Après 2019, les non résidents sont exonérés de la CSG et CRDS. + * Les non résidents ne sont pas éligibles au RSA. + * Création de la variable `resident_eee_hors_france` pour gérer ce cas. + ## 147.0.1 [#2102](https://github.com/openfisca/openfisca-france/pull/2102) * Amélioration technique. diff --git a/openfisca_france/model/caracteristiques_socio_demographiques/demographie.py b/openfisca_france/model/caracteristiques_socio_demographiques/demographie.py index c632575d82..a4d3d5c579 100644 --- a/openfisca_france/model/caracteristiques_socio_demographiques/demographie.py +++ b/openfisca_france/model/caracteristiques_socio_demographiques/demographie.py @@ -364,11 +364,20 @@ def formula(individu, period, parameters): return sum([nationalite == str.encode(etat_membre) for etat_membre in parameters(period).geopolitique.eee]) # TOOPTIMIZE: string encoding into bytes array should be done at load time +class resident_eee_hors_france(Variable): + value_type = bool + default_value = False + entity = Individu + label = "Individu résident dans un pays membre de l'Espace Économique Européen (EEE), hors France. Voir aussi 'resident_ue'." + definition_period = YEAR + set_input = set_input_dispatch_by_period + + class resident_ue(Variable): value_type = bool default_value = True entity = Individu - label = "Individu résidant dans pays membre de l'Union européenne (UE)." + label = "Individu résidant dans pays membre de l'Union européenne (UE). Voir aussi 'resident_eee_hors_france'." definition_period = MONTH set_input = set_input_dispatch_by_period diff --git a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/activite.py b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/activite.py index e6b34885d3..30f0aac8ed 100644 --- a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/activite.py +++ b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/activite.py @@ -1,7 +1,7 @@ import logging from openfisca_france.model.base import * -from openfisca_france.model.prelevements_obligatoires.prelevements_sociaux.contributions_sociales.base import montant_csg_crds +from openfisca_france.model.prelevements_obligatoires.prelevements_sociaux.contributions_sociales.base import montant_csg_crds, est_exonere_csg_crds log = logging.getLogger(__name__) @@ -106,6 +106,9 @@ class csg_deductible_salaire(Variable): set_input = set_input_divide_by_period def formula(individu, period, parameters): + if est_exonere_csg_crds(individu, period.this_year): + return 0 + assiette_csg_abattue = individu('assiette_csg_abattue', period) assiette_csg_non_abattue = individu('assiette_csg_non_abattue', period) plafond_securite_sociale = individu('plafond_securite_sociale', period) @@ -129,6 +132,9 @@ class csg_imposable_salaire(Variable): set_input = set_input_divide_by_period def formula(individu, period, parameters): + if est_exonere_csg_crds(individu, period.this_year): + return 0 + assiette_csg_abattue = individu('assiette_csg_abattue', period) assiette_csg_non_abattue = individu('assiette_csg_non_abattue', period) plafond_securite_sociale = individu('plafond_securite_sociale', period) @@ -153,6 +159,9 @@ class crds_salaire(Variable): set_input = set_input_divide_by_period def formula(individu, period, parameters): + if est_exonere_csg_crds(individu, period.this_year): + return 0 + assiette_csg_abattue = individu('assiette_csg_abattue', period) assiette_csg_non_abattue = individu('assiette_csg_non_abattue', period) plafond_securite_sociale = individu('plafond_securite_sociale', period) diff --git a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/base.py b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/base.py index d5b8b42b8a..0219f3608b 100644 --- a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/base.py +++ b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/base.py @@ -1,3 +1,4 @@ +from openfisca_core import periods def montant_csg_crds(base_avec_abattement = None, base_sans_abattement = None, indicatrice_taux_plein = None, @@ -18,3 +19,18 @@ def montant_csg_crds(base_avec_abattement = None, base_sans_abattement = None, i return -law_node.taux * base else: return - (law_node.taux_plein * indicatrice_taux_plein + law_node.taux_reduit * indicatrice_taux_reduit) * base + + +def est_exonere_csg_crds(individu_or_members, period): + ''' + Depuis le 1er janvier 2019, les personnes affiliées à un régime obligatoire + de sécurité sociale autre que français au sein d'un pays de l'EEE (Union + européenne, Islande, Norvège, Liechtenstein) ou de la Suisse sont exonérées + de CSG et de CRDS. + Ces revenus demeurent soumis à un prélèvement de solidarité au taux de 7,5%. + Reference: https://www.impots.gouv.fr/international-particulier/questions/je-suis-non-resident-suis-je-redevable-des-contributions + ''' + return ( + (periods.period('2019-01-01').start <= period.start) + and individu_or_members('resident_eee_hors_france', period) + ) diff --git a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/capital.py b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/capital.py index 8d8e334425..bbc422f69d 100644 --- a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/capital.py +++ b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/capital.py @@ -1,5 +1,6 @@ import logging from openfisca_france.model.base import * +from openfisca_france.model.prelevements_obligatoires.prelevements_sociaux.contributions_sociales.base import est_exonere_csg_crds log = logging.getLogger(__name__) @@ -330,6 +331,9 @@ def formula(foyer_fiscal, period, parameters): Attention : Pour les années avant 2013, cette formule n'est pas entièrement correcte car le taux de la CSG n'était pas unique (distinction revenus du patrimoine et revenus de placement) et il y a aussi un problème pour les années postérieures à 2017/2018 ''' + if est_exonere_csg_crds(foyer_fiscal.members, period): + return 0 + assiette_csg_revenus_capital = foyer_fiscal('assiette_csg_revenus_capital', period) csg = parameters(period).taxation_capital.prelevements_sociaux.csg @@ -346,6 +350,9 @@ class crds_revenus_capital(Variable): definition_period = YEAR def formula(foyer_fiscal, period, parameters): + if est_exonere_csg_crds(foyer_fiscal.members, period): + return 0 + assiette_csg_revenus_capital = foyer_fiscal('assiette_csg_revenus_capital', period) P = parameters(period).taxation_capital.prelevements_sociaux diff --git a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/csg_crds.py b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/csg_crds.py index a45d5bd94b..04d4ad6318 100644 --- a/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/csg_crds.py +++ b/openfisca_france/model/prelevements_obligatoires/prelevements_sociaux/contributions_sociales/csg_crds.py @@ -1,5 +1,6 @@ import logging from openfisca_france.model.base import * +from openfisca_france.model.prelevements_obligatoires.prelevements_sociaux.contributions_sociales.base import est_exonere_csg_crds log = logging.getLogger(__name__) @@ -11,6 +12,9 @@ class csg(Variable): definition_period = YEAR def formula(individu, period): + if est_exonere_csg_crds(individu, period): + return 0 + csg_imposable_salaire = individu('csg_imposable_salaire', period, options = [ADD]) csg_deductible_salaire = individu('csg_deductible_salaire', period, options = [ADD]) csg_imposable_chomage = individu('csg_imposable_chomage', period, options = [ADD]) @@ -49,6 +53,9 @@ class crds(Variable): definition_period = YEAR def formula(individu, period): + if est_exonere_csg_crds(individu, period): + return 0 + # CRDS sur revenus individuels crds_salaire = individu('crds_salaire', period, options = [ADD]) crds_retraite = individu('crds_retraite', period, options = [ADD]) @@ -75,6 +82,9 @@ class crds_hors_prestations(Variable): definition_period = YEAR def formula(individu, period): + if est_exonere_csg_crds(individu, period): + return 0 + # CRDS sur revenus individuels crds_salaire = individu('crds_salaire', period, options = [ADD]) crds_retraite = individu('crds_retraite', period, options = [ADD]) diff --git a/openfisca_france/model/prestations/minima_sociaux/rsa.py b/openfisca_france/model/prestations/minima_sociaux/rsa.py index b7d6dce308..e88ba25c61 100644 --- a/openfisca_france/model/prestations/minima_sociaux/rsa.py +++ b/openfisca_france/model/prestations/minima_sociaux/rsa.py @@ -665,6 +665,10 @@ class rsa_eligibilite(Variable): set_input = set_input_dispatch_by_period def formula(famille, period, parameters): + # les non residents ne sont pas eligibles au RSA + if famille.members('resident_eee_hors_france', period.this_year): + return 0 + rsa_nb_enfants = famille('rsa_nb_enfants', period) rsa_eligibilite_tns = famille('rsa_eligibilite_tns', period) condition_nationalite_i = famille.members('rsa_condition_nationalite', period) diff --git a/setup.py b/setup.py index 25ffd58456..21d642fbf6 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name = 'OpenFisca-France', - version = '147.0.1', + version = '147.1.1', author = 'OpenFisca Team', author_email = 'contact@openfisca.fr', classifiers = [ diff --git a/tests/capital/non_residents_exoneration_csg_crds.yaml b/tests/capital/non_residents_exoneration_csg_crds.yaml new file mode 100644 index 0000000000..f2af33b10f --- /dev/null +++ b/tests/capital/non_residents_exoneration_csg_crds.yaml @@ -0,0 +1,57 @@ +# Before 2019, everybody pay + +- name: pre_2019_residents_non_exoneres + description: Avant 2019, les résidents ne sont pas exonérés + period: 2018 + absolute_error_margin: 1 + input: + f4ba: 1000 + # resident_eee_hors_france: False + output: + csg_revenus_capital: -99 + crds_revenus_capital: -5 + prelevements_sociaux_revenus_capital_hors_csg_crds: -68 + revenus_nets_du_capital: 828 + +- name: pre_2019_non_residents_non_exoneres + description: Avant 2019, les non résidents ne sont pas exonérés + period: 2018 + absolute_error_margin: 1 + input: + f4ba: 1000 + resident_eee_hors_france: True + output: + csg_revenus_capital: -99 + crds_revenus_capital: -5 + prelevements_sociaux_revenus_capital_hors_csg_crds: -68 + revenus_nets_du_capital: 828 + +# After 2019, only residents in France pay + +- name: post_2019_residents_non_exoneres + description: A partir de 2019, les résidents ne sont pas exonérés + period: 2019 + absolute_error_margin: 1 + input: + f4ba: 1000 + # resident_eee_hors_france: False + output: + csg_revenus_capital: -92 + crds_revenus_capital: -5 + prelevements_sociaux_revenus_capital_hors_csg_crds: -75 + revenus_nets_du_capital: 828 + revenu_disponible: 6837 # due to RSA + +- name: post_2019_non_residents_exoneres + description: A partir de 2019, les non résidents sont exonérés + period: 2019 + absolute_error_margin: 1 + input: + f4ba: 1000 + resident_eee_hors_france: True + output: + csg_revenus_capital: 0 + crds_revenus_capital: 0 + prelevements_sociaux_revenus_capital_hors_csg_crds: -75 + revenus_nets_du_capital: 925 + revenu_disponible: 925