-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #259 from openfisca/pote
Pote
- Loading branch information
Showing
19 changed files
with
1,248 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,3 +89,5 @@ openfisca_erfs_fpr.json | |
.pytest_cache/ | ||
|
||
figures_directory | ||
|
||
*.parquet |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Version pote du template du fichier config.ini de openfisca-survey-manager | ||
# pour qu'il fonctionne avec openfisca-france-data | ||
|
||
|
||
[collections] | ||
collections_directory = /tests/pote/fake_data/output/data_collections | ||
pote = /tests/pote/fake_data/output/data_collections/pote.json | ||
|
||
[data] | ||
sas_pote = / | ||
chunks_pote = / | ||
raw_pote = /tests/pote/fake_data/raw/ | ||
output_directory = /tests/pote/fake_data/output/ | ||
tmp_directory = /tests/pote/fake_data/tmp/ | ||
|
||
[openfisca_france_data_pote] | ||
errors_path = /tests/pote/fake_data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
from openfisca_france.model.base import ( | ||
FoyerFiscal, | ||
Individu, | ||
YEAR, | ||
Variable, | ||
Reform | ||
) | ||
|
||
from numpy import maximum as max_ | ||
|
||
class AnnualisationVariablesIR(Reform): | ||
name = "Annualisation des variables dans le calcul de l'impôt sur le revenu" | ||
tax_benefit_system_name = "openfisca_france" | ||
|
||
def apply(self): | ||
|
||
class salaire_imposable(Variable): | ||
value_type = float | ||
unit = 'currency' | ||
cerfa_field = { # (f1aj, f1bj, f1cj, f1dj, f1ej) | ||
0: '1AJ', | ||
1: '1BJ', | ||
2: '1CJ', | ||
3: '1DJ', | ||
4: '1EJ', | ||
} | ||
entity = Individu | ||
label = 'Salaires imposables' | ||
reference = 'https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000042683657' | ||
definition_period = YEAR | ||
|
||
class retraite_imposable(Variable): | ||
unit = 'currency' | ||
value_type = float | ||
cerfa_field = { | ||
0: '1AS', | ||
1: '1BS', | ||
2: '1CS', | ||
3: '1DS', | ||
4: '1ES', | ||
} | ||
entity = Individu | ||
label = 'Retraites au sens strict imposables (rentes à titre onéreux exclues)' | ||
reference = 'http://vosdroits.service-public.fr/particuliers/F415.xhtml' | ||
definition_period = YEAR | ||
|
||
class chomage_imposable(Variable): | ||
value_type = float | ||
unit = 'currency' | ||
cerfa_field = { | ||
0: '1AP', | ||
1: '1BP', | ||
2: '1CP', | ||
3: '1DP', | ||
4: '1EP', | ||
} | ||
entity = Individu | ||
label = 'Allocations chômage imposables' | ||
reference = 'http://www.insee.fr/fr/methodes/default.asp?page=definitions/chomage.htm' | ||
definition_period = YEAR | ||
|
||
|
||
baseline_revenus_capitaux_pfu = self.baseline.get_variable( | ||
"revenus_capitaux_prelevement_forfaitaire_unique_ir" | ||
) | ||
formula_revenus_capitaux_pfu = ( | ||
baseline_revenus_capitaux_pfu.get_formula("2021-01-01") | ||
) | ||
|
||
class revenus_capitaux_prelevement_forfaitaire_unique_ir(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = 'Revenus des valeurs et capitaux mobiliers soumis au prélèvement forfaitaire unique (partie impôt sur le revenu)' | ||
definition_period = YEAR | ||
|
||
def formula_2021_01_01(foyer_fiscal, period, parameters): | ||
return formula_revenus_capitaux_pfu(foyer_fiscal, period.first_month, parameters) * 12 | ||
|
||
|
||
baseline_revenus_capitaux_prelevement_bareme = self.baseline.get_variable( | ||
"revenus_capitaux_prelevement_bareme" | ||
) | ||
formula_revenus_capitaux_prelevement_bareme = ( | ||
baseline_revenus_capitaux_prelevement_bareme.get_formula("2021-01-01") | ||
) | ||
|
||
class revenus_capitaux_prelevement_bareme(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = 'Revenus du capital imposés au barème (montants bruts)' | ||
reference = 'http://bofip.impots.gouv.fr/bofip/3775-PGP' | ||
definition_period = YEAR | ||
|
||
def formula_2021_01_01(foyer_fiscal, period, parameters): | ||
formula_revenus_capitaux_prelevement_bareme(foyer_fiscal, period.first_month, parameters) * 12 | ||
|
||
baseline_revenus_capitaux_prelevement_liberatoire = self.baseline.get_variable( | ||
"revenus_capitaux_prelevement_liberatoire" | ||
) | ||
formula_revenus_capitaux_prelevement_liberatoire = ( | ||
baseline_revenus_capitaux_prelevement_liberatoire.get_formula("2021-01-01") | ||
) | ||
|
||
class revenus_capitaux_prelevement_liberatoire(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = 'Revenu du capital imposé au prélèvement libératoire (montants bruts)' | ||
reference = 'http://bofip.impots.gouv.fr/bofip/3817-PGP' | ||
definition_period = YEAR | ||
|
||
def formula_2021_01_01(foyer_fiscal, period, parameters): | ||
return formula_revenus_capitaux_prelevement_liberatoire(foyer_fiscal, period, parameters) * 12 | ||
|
||
class revenus_individuels(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = "Somme des revenus_individuels utilisés pour l'imputation des revenus du capital" | ||
definition_period = YEAR | ||
|
||
def formula(foyer_fiscal, period): | ||
revenu_assimile_salaire_i = foyer_fiscal.members("revenu_assimile_salaire", period) | ||
revenu_assimile_salaire = foyer_fiscal.sum(revenu_assimile_salaire_i) | ||
revenu_assimile_pension_i = foyer_fiscal.members("revenu_assimile_pension", period) | ||
revenu_assimile_pension = foyer_fiscal.sum(revenu_assimile_pension_i) | ||
rpns_imposables_i = foyer_fiscal.members("rpns_imposables", period) | ||
rpns_imposables = foyer_fiscal.sum(rpns_imposables_i) | ||
|
||
return max_(revenu_assimile_salaire + revenu_assimile_pension + rpns_imposables, 0) | ||
|
||
baseline_rfr = self.baseline.get_variable( | ||
"rfr" | ||
) | ||
formula_rfr = ( | ||
baseline_rfr.get_formula() | ||
) | ||
|
||
class rfr(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = "Revenu fiscal de référence" | ||
definition_period = YEAR | ||
|
||
def formula(foyer_fiscal, period, parameters): | ||
rfr = formula_rfr(foyer_fiscal, period, parameters) | ||
return max_(rfr, 0) | ||
|
||
class salaire_imposable_large(Variable): | ||
value_type = float | ||
entity = Individu | ||
label = "Salaires imposables au sens large, mais sans le chomage imposable" | ||
definition_period = YEAR | ||
|
||
def formula(individu, period): | ||
revenu_assimile_salaire = individu("revenu_assimile_salaire", period) | ||
chomage_imposable = individu("chomage_imposable", period) | ||
|
||
return revenu_assimile_salaire - chomage_imposable | ||
|
||
class rfr_par_part(Variable): | ||
value_type = float | ||
entity = FoyerFiscal | ||
label = "Revenu fiscal de référence par part" | ||
definition_period = YEAR | ||
|
||
def formula(foyer_fiscal,period): | ||
rfr = foyer_fiscal("rfr", period) | ||
nbptr = foyer_fiscal("nbptr", period) | ||
|
||
return rfr / nbptr | ||
|
||
|
||
variables_annualisees = [ | ||
salaire_imposable, | ||
retraite_imposable, | ||
chomage_imposable, | ||
revenus_capitaux_prelevement_forfaitaire_unique_ir, | ||
revenus_capitaux_prelevement_bareme, | ||
revenus_capitaux_prelevement_liberatoire, | ||
rfr | ||
] | ||
|
||
variables_ajout = [ | ||
revenus_individuels, | ||
salaire_imposable_large, | ||
rfr_par_part | ||
] | ||
|
||
for variable in variables_annualisees: | ||
self.update_variable(variable) | ||
|
||
for variable in variables_ajout: | ||
self.add_variable(variable) |
130 changes: 130 additions & 0 deletions
130
openfisca_france_data/pote/input_data_builder/analyse_variables.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
from openfisca_france_data.utils import build_cerfa_fields_by_variable | ||
from openfisca_core.simulation_builder import SimulationBuilder | ||
from openfisca_france_data.pote.annualisation_variables import AnnualisationVariablesIR | ||
import openfisca_france | ||
|
||
|
||
|
||
def liens_variables(year): | ||
''' | ||
Pour une année year de simulation de l'impôt sur le revenu renvoi : | ||
- les variables composées d'input variables qui ne sont utilisée que dans cette variables | ||
- la liste des input variables qui composent chaque variable du point précédent | ||
Ces listes vont être utilisées pour faire des pré calcul dans l'impôt sur le revenu afin de limiter le nombre de colonnes. | ||
''' | ||
|
||
var_foyer_fiscal = list() | ||
cerfa_var_dict = build_cerfa_fields_by_variable(year = year) | ||
|
||
for openfisca_var, cerfa in cerfa_var_dict.items(): | ||
if len(cerfa) == 1: | ||
var_foyer_fiscal.append(openfisca_var) | ||
|
||
cas_type = { | ||
"individus": { | ||
"ind0": { | ||
"date_naissance": {'ETERNITY':'1970-01-01'}, | ||
"salaire_imposable": {f"{year}":0}, | ||
"retraite_imposable": {f"{year}":0}, | ||
"chomage_imposable": {f"{year}":0} | ||
} | ||
} | ||
} | ||
tax_benefit_system = AnnualisationVariablesIR(openfisca_france.FranceTaxBenefitSystem()) | ||
simulation = SimulationBuilder() | ||
simulation = simulation.build_from_entities(tax_benefit_system, cas_type) | ||
simulation.trace = True | ||
simulation.calculate('irpp_economique', year) | ||
lines = simulation.tracer.computation_log.lines() | ||
text = list() | ||
for line in lines: | ||
line = line.split(">>") | ||
if len(line)==2: | ||
text.append(line[0]) | ||
|
||
indented_variables = list() | ||
for line in text: | ||
split_line = line.split("<") | ||
assert len(split_line) == 2 | ||
assert split_line[1].startswith(str(year)), f"{split_line} doesn't start with {year}" | ||
indented_variables += [split_line[0]] | ||
|
||
indent_max = 0 | ||
for line in indented_variables: | ||
level = (len(line) - len(line.lstrip()))/2 | ||
if level > indent_max: | ||
indent_max = level | ||
|
||
tot = dict() | ||
for max in reversed(range(int(indent_max))): | ||
arborescence = dict() | ||
arborescence_i = dict() | ||
for line in indented_variables: | ||
indent = (len(line) - len(line.lstrip()))/2 | ||
if indent < max: | ||
arborescence_i[indent] = line.lstrip() | ||
elif indent == max: | ||
arborescence[line.lstrip()] = arborescence_i | ||
tot[max] = arborescence | ||
|
||
i = 0 | ||
dictionnaire_parent_enfants = dict() | ||
|
||
for max in reversed(range(2, int(indent_max + 1))): | ||
for line in indented_variables: | ||
level = (len(line) - len(line.lstrip()))/2 | ||
if level == max - 1: | ||
variable = line.lstrip() | ||
rang_ident_1 = i | ||
if level == max: | ||
if i == rang_ident_1 + 1: | ||
dictionnaire_parent_enfants[variable] = [line.lstrip()] | ||
else: | ||
dictionnaire_parent_enfants[variable] += [line.lstrip()] | ||
i += 1 | ||
variables = list(set([line.strip() for line in indented_variables])) | ||
|
||
dictionnaire_enfant_parents = dict() | ||
for variable in variables: | ||
dictionnaire_enfant_parents[variable] = [] | ||
|
||
for parent, enfants in dictionnaire_parent_enfants.items(): | ||
for enfant in enfants: | ||
dictionnaire_enfant_parents[enfant] += [parent] | ||
|
||
unique_appel = list() | ||
for enfant, parents in dictionnaire_enfant_parents.items(): | ||
if len(parents) == 1: | ||
unique_appel += [enfant] | ||
assert len(unique_appel) == len(list(set(unique_appel))), "Il y a des doublons dans les appels uniques" | ||
|
||
variables_to_compute = list() | ||
for case_fiscal in var_foyer_fiscal: | ||
if case_fiscal in unique_appel: | ||
parent = dictionnaire_enfant_parents[case_fiscal] | ||
assert len(parent) == 1 | ||
if parent[0] not in variables_to_compute: # si déjà dedans c'est qu'on a déjà checké que tous les enfants étaient bien appelés qu'une seule fois | ||
enfants_parent = dictionnaire_parent_enfants[parent[0]] | ||
unique_appel_enfants = [e for e in enfants_parent if e in unique_appel] | ||
only_case_fiscal = [c for c in enfants_parent if c in var_foyer_fiscal] | ||
if len(enfants_parent) == len(unique_appel_enfants): | ||
if len(enfants_parent) == len(only_case_fiscal): | ||
variables_to_compute += [parent[0]] | ||
|
||
variables_to_compute = [v for v in variables_to_compute if len(dictionnaire_parent_enfants[v])>1] # cela ne sert à rien de calculer si qu'une variable, aucun gain de colonnes | ||
enfants_tot = list() | ||
for var in variables_to_compute: | ||
enfants_tot += dictionnaire_parent_enfants[var] | ||
|
||
for enfant in dictionnaire_parent_enfants['duflot_pinel_denormandie_metropole'] + dictionnaire_parent_enfants['duflot_pinel_denormandie_om']: | ||
assert enfant.startswith("f7") | ||
ref = {'duflot_pinel_denormandie_metropole', 'duflot_pinel_denormandie_om'} | ||
assert set(dictionnaire_enfant_parents[enfant]).issubset(ref), f"{enfant}" | ||
enfants_tot = enfants_tot + dictionnaire_parent_enfants['duflot_pinel_denormandie_metropole'] | ||
enfants_tot = enfants_tot + dictionnaire_parent_enfants['duflot_pinel_denormandie_om'] | ||
variables_to_compute += ['duflot_pinel_denormandie_metropole', 'duflot_pinel_denormandie_om'] | ||
|
||
return variables_to_compute, enfants_tot, dictionnaire_enfant_parents, dictionnaire_parent_enfants |
Oops, something went wrong.