From 43d5ad021759a76e10719abcdfac80d6fbc9f1f4 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 11:34:50 +0100 Subject: [PATCH 01/24] =?UTF-8?q?Ajoute=20les=20taux=20d'annuit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parameters/retraite/cnrps/taux_annuite_maximum | 5 +++++ .../parameters/retraite/cnrps/taux_annuite_periode_base.yaml | 5 +++++ .../retraite/cnrps/taux_annuite_periode_supplemetaire.yaml | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum new file mode 100644 index 0000000..6a99e35 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum @@ -0,0 +1,5 @@ +description: Taux d'annuité maximal +unit: /1 +values: + 1959-02-01: + value: 0.9 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml new file mode 100644 index 0000000..13dec9e --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml @@ -0,0 +1,5 @@ +description: Taux d'annuité de la période de base (allant de la 1ère à la 10e année liquidable) par trimestre +unit: /1 +values: + 1959-02-01: + value: 0.05 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml new file mode 100644 index 0000000..43f6a96 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml @@ -0,0 +1,5 @@ +description: Taux d'annuité de la période supplémentaire (allant de la 11e à la 20e année liquidable) par trimestre +unit: /1 +values: + 1959-02-01: + value: 0.075 From d4f190dcdbbb48a18f647c504bccced93ce80254 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 12:38:46 +0100 Subject: [PATCH 02/24] Fix typo and refactor --- .github/PULL_REQUEST_TEMPLATE.md | 3 +- README.md | 4 +- ....yaml => taux_annuite_supplementaire.yaml} | 0 ....yaml => taux_annuite_supplementaire.yaml} | 0 openfisca_tunisia_pension/variables/cnrps.py | 78 +++++++++++++++++++ .../variables/helpers.py | 6 +- openfisca_tunisia_pension/variables/rsa.py | 16 +++- openfisca_tunisia_pension/variables/rsna.py | 12 ++- tests/formulas/pension_rsna.yaml | 4 +- tests/formulas/salaire_reference_rsna.yaml | 2 +- 10 files changed, 105 insertions(+), 20 deletions(-) rename openfisca_tunisia_pension/parameters/retraite/rsa/{taux_annuite_supplemetaire.yaml => taux_annuite_supplementaire.yaml} (100%) rename openfisca_tunisia_pension/parameters/retraite/rsna/{taux_annuite_supplemetaire.yaml => taux_annuite_supplementaire.yaml} (100%) create mode 100644 openfisca_tunisia_pension/variables/cnrps.py diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 182a42e..688f4aa 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,5 @@ -Merci de contribuer à OpenFisca ! Effacez cette ligne ainsi que, pour chaque ligne ci-dessous, les cas ne correspondant pas à votre contribution :) + +Merci de contribuer à OpenFisca ! Effacez cette ligne ainsi que, pour chaque ligne ci-dessous, les cas ne correspondant pas à votre contribution : * Évolution du système socio-fiscal. | Amélioration technique. | Correction d'un crash. | Changement mineur. * Périodes concernées : toutes. | jusqu'au JJ/MM/AAAA. | à partir du JJ/MM/AAAA. diff --git a/README.md b/README.md index 0e7aeff..08d0fad 100644 --- a/README.md +++ b/README.md @@ -141,10 +141,10 @@ nosetests openfisca_tunisia_pension/tests/test_pension.py:test_rsna Le format d'un test yaml est décrit dans la [documentation officielle](https://doc.openfisca.fr/coding-the-legislation/writing_yaml_tests.html). -Ainsi, si vous souhaitez exécuter le test yaml `openfisca_tunisia_pension/tests/formulas/pension_rsna.yaml`, utilisez la commande : +Ainsi, si vous souhaitez exécuter le test yaml `openfisca_tunisia_pension/tests/formulas/rsna_pension.yaml`, utilisez la commande : ``` -openfisca-run-test -c openfisca_tunisia_pension openfisca_tunisia_pension/tests/formulas/pension_rsna.yaml +openfisca-run-test -c openfisca_tunisia_pension openfisca_tunisia_pension/tests/formulas/rsna_pension.yaml ``` ### Tout tester diff --git a/openfisca_tunisia_pension/parameters/retraite/rsa/taux_annuite_supplemetaire.yaml b/openfisca_tunisia_pension/parameters/retraite/rsa/taux_annuite_supplementaire.yaml similarity index 100% rename from openfisca_tunisia_pension/parameters/retraite/rsa/taux_annuite_supplemetaire.yaml rename to openfisca_tunisia_pension/parameters/retraite/rsa/taux_annuite_supplementaire.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplemetaire.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml similarity index 100% rename from openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplemetaire.yaml rename to openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py new file mode 100644 index 0000000..10fba9c --- /dev/null +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -0,0 +1,78 @@ +import functools +from numpy import ( + apply_along_axis, + logical_not as not_, + maximum as max_, + vstack, + ) + +from openfisca_core.model_api import * +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + + +class cnrps_salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaire de référence de la CNRPS' + definition_period = YEAR + + def formula(individu, period): + # TODO: gérer le nombre d'année n + # TODO: plafonner les salaires à 6 fois le smig de l'année d'encaissement + n = 10 + mean_over_largest = functools.partial(mean_over_k_largest, k = n) + salaire_refererence = apply_along_axis( + mean_over_largest, + axis = 0, + arr = vstack([ + individu('salaire', period = year) + for year in range(period.start.year, period.start.year - n, -1) + ]), + ) + return salaire_refererence + + +class cnrps_pension(Variable): + value_type = float + entity = Individu + label = 'Pension des affiliés au régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + trimestres_valides = individu('trimestres_valides', period = period) + salaire_reference = individu('rsna_salaire_reference', period = period) + age = individu('age', period = period) + + rsna = parameters(period).retraite.rsna + taux_annuite_base = rsna.taux_annuite_base + taux_annuite_supplementaire = rsna.taux_annuite_supplementaire + duree_stage = rsna.stage_derog + age_eligible = rsna.age_dep_anticip + periode_remplacement_base = rsna.periode_remplacement_base + plaf_taux_pension = rsna.plaf_taux_pension + smig = parameters(period).marche_travail.smig_48h + + pension_min_sup = rsna.pension_minimale.sup + pension_min_inf = rsna.pension_minimale.inf + + stage = trimestres_valides > 4 * duree_stage + pension_minimale = ( + stage * pension_min_sup + not_(stage) * pension_min_inf + ) + montant = pension_generique( + trimestres_valides, + salaire_reference, + taux_annuite_base, + taux_annuite_supplementaire, + duree_stage, + age_eligible, + periode_remplacement_base, + plaf_taux_pension, + ) + # eligibilite + eligibilite_age = age > age_eligible + eligibilite = stage * eligibilite_age * (salaire_reference > 0) + # plafonnement + montant_pension_percu = max_(montant, pension_minimale * smig) + return eligibilite * montant_pension_percu diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index dcf14c2..01cde80 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -5,13 +5,13 @@ from numpy import minimum as min_ -def pension_generique(trimestres_valides, sal_ref, age, taux_annuite_base, taux_annuite_supplemetaire, duree_stage, - age_elig, periode_remplacement_base, plaf_taux_pension, smig): +def pension_generique(trimestres_valides, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, + age_elig, periode_remplacement_base, plaf_taux_pension): taux_pension = ( (trimestres_valides < 4 * periode_remplacement_base) * (trimestres_valides / 4) * taux_annuite_base + (trimestres_valides >= 4 * periode_remplacement_base) * ( taux_annuite_base * periode_remplacement_base - + (trimestres_valides / 4 - periode_remplacement_base) * taux_annuite_supplemetaire + + (trimestres_valides / 4 - periode_remplacement_base) * taux_annuite_supplementaire ) ) montant = min_(taux_pension, plaf_taux_pension) * sal_ref diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index df81f07..e7a84f3 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -36,7 +36,7 @@ def formula(individu, period): return salaire_refererence -class pension_rsa(Variable): +class rsa_pension(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime des salariés agricoles' @@ -45,7 +45,7 @@ class pension_rsa(Variable): def formula(individu, period, parameters): rsa = parameters.retraite.rsa(period) taux_annuite_base = rsa.taux_annuite_base - taux_annuite_supplemetaire = rsa.taux_annuite_supplemetaire + taux_annuite_supplementaire = rsa.taux_annuite_supplementaire duree_stage = rsa.stage_requis age_elig = rsa.age_legal periode_remplacement_base = rsa.periode_remplacement_base @@ -55,8 +55,16 @@ def formula(individu, period, parameters): pension_min = rsa.pension_min salaire_reference = individu('salaire_reference_rsa', period) - montant = pension_generique(trimestres_valides, sal_ref, age, taux_annuite_base, taux_annuite_supplemetaire, - duree_stage, age_elig, periode_remplacement_base, plaf_taux_pension, smag) + montant = pension_generique( + trimestres_valides, + sal_ref, + taux_annuite_base, + taux_annuite_supplementaire, + duree_stage, + age_elig, + periode_remplacement_base, + plaf_taux_pension + ) elig_age = age > age_elig elig = duree_stage_validee * elig_age * (salaire_reference > 0) diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index 48c7b35..de52705 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -11,7 +11,7 @@ from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique -class salaire_reference_rsna(Variable): +class rsna_salaire_reference(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime des salariés non agricoles' @@ -33,7 +33,7 @@ def formula(individu, period): return salaire_refererence -class pension_rsna(Variable): +class rsna_pension(Variable): value_type = float entity = Individu label = 'Pension des affiliés au régime des salariés non agricoles' @@ -41,12 +41,12 @@ class pension_rsna(Variable): def formula(individu, period, parameters): trimestres_valides = individu('trimestres_valides', period = period) - salaire_reference = individu('salaire_reference_rsna', period = period) + salaire_reference = individu('rsna_salaire_reference', period = period) age = individu('age', period = period) rsna = parameters(period).retraite.rsna taux_annuite_base = rsna.taux_annuite_base - taux_annuite_supplemetaire = rsna.taux_annuite_supplemetaire + taux_annuite_supplementaire = rsna.taux_annuite_supplementaire duree_stage = rsna.stage_derog age_eligible = rsna.age_dep_anticip periode_remplacement_base = rsna.periode_remplacement_base @@ -63,14 +63,12 @@ def formula(individu, period, parameters): montant = pension_generique( trimestres_valides, salaire_reference, - age, taux_annuite_base, - taux_annuite_supplemetaire, + taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension, - smig, ) # eligibilite eligibilite_age = age > age_eligible diff --git a/tests/formulas/pension_rsna.yaml b/tests/formulas/pension_rsna.yaml index f2fe4e4..d8791e1 100644 --- a/tests/formulas/pension_rsna.yaml +++ b/tests/formulas/pension_rsna.yaml @@ -47,5 +47,5 @@ 2014: 12000 output: trimestres_valides: 50 - salaire_reference_rsna: 12000 - pension_rsna: 5400 + rsna_salaire_reference: 12000 + rsna_pension: 5400 diff --git a/tests/formulas/salaire_reference_rsna.yaml b/tests/formulas/salaire_reference_rsna.yaml index 02a8ff7..852a402 100644 --- a/tests/formulas/salaire_reference_rsna.yaml +++ b/tests/formulas/salaire_reference_rsna.yaml @@ -47,4 +47,4 @@ 2014: 12000 output: trimestres_valides: 50 - salaire_reference_rsna: 12000 + rsna_salaire_reference: 12000 From 057b4b6725c33b63c5a8e8f154566d60796a8b5a Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 12:40:23 +0100 Subject: [PATCH 03/24] Bump --- CHANGELOG.md | 11 ++++++++++- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8aa793..49313a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog -# 3.0.0 [#14](https://github.com/openfisca/openfisca-tunisia-pension/pull/14) +# 5.0.0 [#15](https://github.com/openfisca/openfisca-tunisia-pension/pull/15) + +* Évolution du système socio-fiscal. +* Périodes concernées : toutes. +* Zones impactées : `variables/regimes/cnrps`. +* Détails : + - Introduit le régime de la CNRPS + + +# 4.0.0 [#14](https://github.com/openfisca/openfisca-tunisia-pension/pull/14) * Évolution du système socio-fiscal. * Périodes concernées : toutes. diff --git a/pyproject.toml b/pyproject.toml index 4448bf4..1b0f35b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "OpenFisca-Tunisia-Pension" -version = "4.0.0" +version = "5.0.0" description = "OpenFisca Rules as Code model for Tunisia pensions." readme = "README.md" keywords = ["microsimulation", "tax", "benefit", "pension", "rac", "rules-as-code", "tunisia"] From 1aa24d33edecc1c406d3f269ad4157be7806812c Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 17:10:46 +0100 Subject: [PATCH 04/24] Use script_ast generator --- CHANGELOG.md | 2 +- openfisca_tunisia_pension/__init__.py | 37 ++- openfisca_tunisia_pension/regimes/__init__.py | 0 openfisca_tunisia_pension/regimes/regime.py | 249 ++++++++++++++++++ openfisca_tunisia_pension/regimes/rsa.py | 88 +++++++ openfisca_tunisia_pension/regimes/rsna.py | 91 +++++++ .../scripts_ast/__init__.py | 0 .../scripts_ast/script_ast.py | 237 +++++++++++++++++ .../tunisia_pension_taxbenefitsystem.py | 25 -- openfisca_tunisia_pension/variables/cnrps.py | 6 +- openfisca_tunisia_pension/variables/data.py | 2 +- .../variables/helpers.py | 8 +- openfisca_tunisia_pension/variables/rsa.py | 4 +- openfisca_tunisia_pension/variables/rsna.py | 204 ++++++++++---- .../{pension_rsna.yaml => rsna_pension.yaml} | 3 +- ..._rsna.yaml => rsna_salaire_reference.yaml} | 3 +- 16 files changed, 873 insertions(+), 86 deletions(-) create mode 100644 openfisca_tunisia_pension/regimes/__init__.py create mode 100644 openfisca_tunisia_pension/regimes/regime.py create mode 100644 openfisca_tunisia_pension/regimes/rsa.py create mode 100644 openfisca_tunisia_pension/regimes/rsna.py create mode 100644 openfisca_tunisia_pension/scripts_ast/__init__.py create mode 100644 openfisca_tunisia_pension/scripts_ast/script_ast.py delete mode 100644 openfisca_tunisia_pension/tunisia_pension_taxbenefitsystem.py rename tests/formulas/{pension_rsna.yaml => rsna_pension.yaml} (94%) rename tests/formulas/{salaire_reference_rsna.yaml => rsna_salaire_reference.yaml} (94%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49313a6..940e78b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ * Move parameters from xml format to yaml files tree ### 1.0.0 -* Renomme `nb_trim_val` en `trimestres_valides` +* Renomme `nb_trim_val` en `duree_assurance` * Utilisation de noms longs pour différent paramètres ## 0.9.2 diff --git a/openfisca_tunisia_pension/__init__.py b/openfisca_tunisia_pension/__init__.py index 6b04e0a..93adb49 100644 --- a/openfisca_tunisia_pension/__init__.py +++ b/openfisca_tunisia_pension/__init__.py @@ -1,3 +1,38 @@ -from openfisca_tunisia_pension.tunisia_pension_taxbenefitsystem import TunisiaPensionTaxBenefitSystem +'''OpenFisca Tunisia Pension tax-benefit system.''' + + +import logging +import os + +from openfisca_core.taxbenefitsystems import TaxBenefitSystem + +from openfisca_tunisia_pension import entities +from openfisca_tunisia_pension.scripts_ast import script_ast + + +COUNTRY_DIR = os.path.dirname(os.path.abspath(__file__)) + +logging.getLogger('numba.core.ssa').disabled = True +logging.getLogger('numba.core.byteflow').disabled = True +logging.getLogger('numba.core.interpreter').disabled = True + +# Convert regimes classes to OpenFisca variables. +script_ast.main(verbose = False) + + +class TunisiaPensionTaxBenefitSystem(TaxBenefitSystem): + '''Tunisian pensions tax benefit system''' + CURRENCY = 'DT' + + def __init__(self): + super(TunisiaPensionTaxBenefitSystem, self).__init__(entities.entities) + + # We add to our tax and benefit system all the variables + self.add_variables_from_directory(os.path.join(COUNTRY_DIR, 'variables')) + + # We add to our tax and benefit system all the legislation parameters defined in the parameters files + parameters_path = os.path.join(COUNTRY_DIR, 'parameters') + self.load_parameters(parameters_path) + CountryTaxBenefitSystem = TunisiaPensionTaxBenefitSystem diff --git a/openfisca_tunisia_pension/regimes/__init__.py b/openfisca_tunisia_pension/regimes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py new file mode 100644 index 0000000..a2e1109 --- /dev/null +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -0,0 +1,249 @@ +'''Abstract regimes definition.''' + + +from openfisca_core.model_api import * +# from openfisca_core.errors.variable_not_found_error import VariableNotFoundError + +# Import the Entities specifically defined for this tax and benefit system +from openfisca_tunisia_pension.entities import Individu + + +class AbstractRegime(object): + name = None + variable_prefix = None + parameters = None + + class cotisation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'cotisation retraite employeur' + + def formula(individu, period, parameters): + NotImplementedError + + class duree_assurance(Variable): + value_type = int + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (trimestres validés)" + + # def formula(individu, period, parameters): + # duree_assurance_validee = individu("regime_name_duree_assurance_validee", period) + # annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + # majoration_duree_assurance = individu('regime_name_majoration_duree_assurance', period) + # return where( + # annee_de_liquidation == period.start.year, + # round_(duree_assurance_validee + majoration_duree_assurance), # On arrondi l'année de la liquidation + # duree_assurance_validee + # ) + + class liquidation_date(Variable): + value_type = date + entity = Individu + definition_period = ETERNITY + label = 'Date de liquidation' + default_value = date(2250, 12, 31) + + class majoration_pension(Variable): + value_type = int + entity = Individu + definition_period = MONTH + label = 'Majoration de pension' + + def formula(individu, period, parameters): + NotImplementedError + + class pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period, parameters): + NotImplementedError + + class pension_brute(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute' + + def formula(individu, period, parameters): + NotImplementedError + + class pension_servie(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension servie' + + def formula(individu, period, parameters): + NotImplementedError + + +class AbstractRegimeEnAnnuites(AbstractRegime): + name = 'Régime en annuités' + variable_prefix = 'regime_en_annuites' + parameters = 'regime_en_annuites' + + class duree_assurance_annuelle(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (en trimestres validés l'année considérée)" + + class majoration_duree_assurance(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance" + + def formula(individu, period): + return ( + individu('regime_name_majoration_duree_assurance_enfant', period) + + individu('regime_name_majoration_duree_assurance_autre', period) + ) + + class majoration_duree_assurance_autre(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" + + class majoration_pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension' + + class majoration_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + # Raccouci pour arrêter les calculs dans le passé quand toutes les liquidations ont lieu dans le futur + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + majoration_pension_au_31_decembre_annee_precedente = individu('regime_name_majoration_pension_au_31_decembre', last_year) + revalorisation = parameters(period).regime_name.revalorisation_pension_au_31_decembre + majoration_pension = individu('regime_name_majoration_pension', period) + return revalorise( + majoration_pension_au_31_decembre_annee_precedente, + majoration_pension, + annee_de_liquidation, + revalorisation, + period, + ) + + class pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period): + pension_brute = individu('regime_name_pension_brute', period) + majoration_pension = individu('regime_name_majoration_pension', period) + return pension_brute + majoration_pension + + class pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period): + pension_brute_au_31_decembre = individu('regime_name_pension_brute_au_31_decembre', period) + majoration_pension_au_31_decembre = individu('regime_name_majoration_pension_au_31_decembre', period) + return pension_brute_au_31_decembre + majoration_pension_au_31_decembre + + class pension_brute_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + # Raccouci pour arrêter les calculs dans le passé quand toutes les liquidations ont lieu dans le futur + if all(period.start.year < annee_de_liquidation): + return individu.empty_array() + last_year = period.last_year + pension_brute_au_31_decembre_annee_precedente = individu('regime_name_pension_brute_au_31_decembre', last_year) + revalorisation = parameters(period).regime_name.revalorisation_pension_au_31_decembre + pension_brute = individu('regime_name_pension_brute', period) + return revalorise( + pension_brute_au_31_decembre_annee_precedente, + pension_brute, + annee_de_liquidation, + revalorisation, + period, + ) + + class pension_servie(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension servie' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + # Raccouci pour arrêter les calculs dans le passé quand toutes les liquidations ont lieu dans le futur + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + pension_au_31_decembre_annee_precedente = individu('regime_name_pension_au_31_decembre', last_year) + revalorisation = parameters(period).regime_name.revalarisation_pension_servie + pension = individu('regime_name_pension_au_31_decembre', period) + return revalorise( + pension_au_31_decembre_annee_precedente, + pension, + annee_de_liquidation, + revalorisation, + period, + ) + + class salaire_de_base(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Salaire de base (salaire brut)' + set_input = set_input_divide_by_period + + class salaire_de_reference(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = 'Salaire de référence' + + class taux_de_liquidation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Taux de liquidation de la pension' + + def formula(individu, period, parameters): + decote = individu('regime_name_decote', period) + surcote = individu('regime_name_surcote', period) + taux_plein = parameters(period).regime_name.taux_plein.taux_plein + return taux_plein * (1 - decote + surcote) + + +# def revalorise(variable_31_decembre_annee_precedente, variable_originale, annee_de_liquidation, revalorisation, period): +# return select( +# [ +# annee_de_liquidation > period.start.year, +# annee_de_liquidation == period.start.year, +# annee_de_liquidation < period.start.year, +# ], +# [ +# 0, +# variable_originale, +# variable_31_decembre_annee_precedente * revalorisation +# ] +# ) diff --git a/openfisca_tunisia_pension/regimes/rsa.py b/openfisca_tunisia_pension/regimes/rsa.py new file mode 100644 index 0000000..c0b3b91 --- /dev/null +++ b/openfisca_tunisia_pension/regimes/rsa.py @@ -0,0 +1,88 @@ +'''Régime des salariés agricoles.''' + + +from openfisca_core.model_api import * +from openfisca_core import periods + +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites +# from openfisca_tunisia_pension.tools import add_vectorial_timedelta, year_ + + +import functools +from numpy import ( + apply_along_axis, + logical_not as not_, + maximum as max_, + vstack, + ) + +from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + + +class RegimeRSA(AbstractRegimeEnAnnuites): + name = 'Régime des salariés agricoles' + variable_prefix = 'rsa' + parameters_prefix = 'rsa' + + class salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés agricoles' + definition_period = YEAR + + def formula(individu, period): + # TODO: gérer le nombre d'année + # TODO: plafonner les salaires à 2 fois le smag de l'année d'encaissement + base_declaration_rsa = 180 + base_liquidation_rsa = 300 + + n = 3 + mean_over_largest = functools.partial(mean_over_k_largest, k = n) + salaire = apply_along_axis( + mean_over_largest, + axis = 0, + arr = vstack([ + individu('salaire', period = periods.period('year', year)) + for year in range(period.start.year, period.start.year - n, -1) + ]), + ) + salaire_refererence = salaire * base_liquidation_rsa / base_declaration_rsa + return salaire_refererence + + + class pension(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + rsa = parameters(period).retraite.regime_name + taux_annuite_base = rsa.taux_annuite_base + taux_annuite_supplementaire = rsa.taux_annuite_supplementaire + duree_stage = rsa.stage_requis + age_elig = rsa.age_legal + periode_remplacement_base = rsa.periode_remplacement_base + plaf_taux_pension = rsa.plaf_taux_pension + smag = parameters(period).marche_travail.smag * 25 + duree_stage_validee = duree_assurance > 4 * duree_stage + pension_min = rsa.pension_min + salaire_reference = individu('regime_name_salaire_reference', period) + + montant = pension_generique( + duree_assurance, + sal_ref, + taux_annuite_base, + taux_annuite_supplementaire, + duree_stage, + age_elig, + periode_remplacement_base, + plaf_taux_pension + ) + + elig_age = age > age_elig + elig = duree_stage_validee * elig_age * (salaire_reference > 0) + montant_percu = max_(montant, pension_min * smag) + pension = elig * montant_percu + return pension diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py new file mode 100644 index 0000000..00bc078 --- /dev/null +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -0,0 +1,91 @@ +'''Régime des salariés non agricoles.''' + + +from openfisca_core.model_api import * + + +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites +# from openfisca_tunisia_pension.tools import add_vectorial_timedelta, year_ + + +import functools +from numpy import ( + apply_along_axis, + logical_not as not_, + maximum as max_, + vstack, + ) + +from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + + +class RegimeRSNA(AbstractRegimeEnAnnuites): + name = 'Régime des salariés non agricoles' + variable_prefix = 'rsna' + parameters_prefix = 'rsna' + + class salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period): + # TODO: gérer le nombre d'année n + # TODO: plafonner les salaires à 6 fois le smig de l'année d'encaissement + n = 10 + mean_over_largest = functools.partial(mean_over_k_largest, k = n) + salaire_refererence = apply_along_axis( + mean_over_largest, + axis = 0, + arr = vstack([ + individu('salaire', period = year) + for year in range(period.start.year, period.start.year - n, -1) + ]), + ) + return salaire_refererence + + class pension(Variable): + value_type = float + entity = Individu + label = 'Pension des affiliés au régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('regime_name_duree_assurance', period = period) + salaire_reference = individu('regime_name_salaire_reference', period = period) + age = individu('age', period = period) + + rsna = parameters(period).retraite.regime_name + taux_annuite_base = rsna.taux_annuite_base + taux_annuite_supplementaire = rsna.taux_annuite_supplementaire + duree_stage = rsna.stage_derog + age_eligible = rsna.age_dep_anticip + periode_remplacement_base = rsna.periode_remplacement_base + plaf_taux_pension = rsna.plaf_taux_pension + smig = parameters(period).marche_travail.smig_48h + + pension_min_sup = rsna.pension_minimale.sup + pension_min_inf = rsna.pension_minimale.inf + + stage = duree_assurance > 4 * duree_stage + pension_minimale = ( + stage * pension_min_sup + not_(stage) * pension_min_inf + ) + montant = pension_generique( + duree_assurance, + salaire_reference, + taux_annuite_base, + taux_annuite_supplementaire, + duree_stage, + age_eligible, + periode_remplacement_base, + plaf_taux_pension, + ) + # eligibilite + eligibilite_age = age > age_eligible + eligibilite = stage * eligibilite_age * (salaire_reference > 0) + # plafonnement + montant_pension_percu = max_(montant, pension_minimale * smig) + return eligibilite * montant_pension_percu diff --git a/openfisca_tunisia_pension/scripts_ast/__init__.py b/openfisca_tunisia_pension/scripts_ast/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/openfisca_tunisia_pension/scripts_ast/script_ast.py b/openfisca_tunisia_pension/scripts_ast/script_ast.py new file mode 100644 index 0000000..843d3f9 --- /dev/null +++ b/openfisca_tunisia_pension/scripts_ast/script_ast.py @@ -0,0 +1,237 @@ +'''Generate openfisca variables of pension scheme.''' + +import ast +import copy +import logging +import os +import sys +from pathlib import Path + + +import openfisca_tunisia_pension +tunisia_pension_root = str(Path(openfisca_tunisia_pension.__file__).parent.parent) + + +log = logging.getLogger(__name__) + + +# tunisia_pension_root = pkg_resources.get_distribution('openfisca-tunisia-pension').location + +class RewriteRegimeFormula(ast.NodeTransformer): + parameters_prefix = None + variable_prefix = None + + def __init__(self, parameters_prefix, variable_prefix): + self.parameters_prefix = parameters_prefix + self.variable_prefix = variable_prefix + + def visit_Attribute(self, node): + node = self.generic_visit(node) + if type(node.attr) is str and node.attr.startswith('regime_name'): + new_attr = node.attr.replace('regime_name', self.parameters_prefix) + log.debug(f'Found attribute to replace: {node.attr} => {new_attr}') + node.attr = new_attr + return node + + def visit_Constant(self, node): + # Useless: node = self.generic_visit(node), because a constant has no + # sub-tree to visit. + if type(node.value) is str and node.value.startswith('regime_name'): + new_value = node.value.replace('regime_name', self.variable_prefix) + log.debug(f'Found parameter to replace: {node.value} => {new_value}') + node.value = new_value + return node + + +class RewriteRegimeVariableClass(ast.NodeTransformer): + parameters_prefix = None + variable_prefix = None + + def __init__(self, parameters_prefix, variable_prefix): + self.parameters_prefix = parameters_prefix + self.variable_prefix = variable_prefix + + def visit_ClassDef(self, node): + node.name = self.variable_prefix + '_' + node.name + node = self.generic_visit(node) + return node + + def visit_FunctionDef(self, node): + if node.name.startswith('formula'): + log.debug(f'Found formula: {node.name}') + node = RewriteRegimeFormula(self.parameters_prefix, self.variable_prefix).visit(node) + else: + node = self.generic_visit(node) + return node + + +def flatten_regime( + regime_class_node_by_name, + regime_class_node, + parameters_prefix, + variable_prefix, + existing_variables_name, + variables_node, + ): + new_variables_name = set() + for node in regime_class_node.body: + if type(node) is ast.ClassDef: + # Node is a variable. + if node.name not in existing_variables_name: + # Variable is not overriden by a subclass variable. + existing_variables_name.add(node.name) + new_variables_name.add(node.name) + + # Aplatit récursivement les variables la classe de base de cette classe Regime. + if regime_class_node.bases[0].id != 'object': + flatten_regime( + regime_class_node_by_name, + regime_class_node_by_name[regime_class_node.bases[0].id], + parameters_prefix, + variable_prefix, + existing_variables_name, + variables_node, + ) + + # Aplatit les variables de cette classe Regime. + for node in regime_class_node.body: + if type(node) is ast.ClassDef: + # Node is a variable. + if node.name in new_variables_name: + node = copy.deepcopy(node) + node = ast.fix_missing_locations(RewriteRegimeVariableClass( + parameters_prefix, + variable_prefix, + ).visit(node)) + variables_node.append(node) + + +def flatten_regimes(input_string, output_filename): + '''Creates regime variables. + + Args: + input_string (str): String to be processed by ast + output_filename (path): Destination of created variables code + ''' + # parser le texte du fichier en structure logique de type AST + input_node = ast.parse(input_string) + + # pour afficher un arbre AST faire une commande + # print(ast.dump(input_node, indent=4)) + + # créer un nouveau arbre AST vide qui va contenir le nouveau code + output_node = ast.Module(body=[], type_ignores=[]) + + # Crée un dictionnaire de toutes les classes contenant 'Regime' dans le nom. + regime_class_node_by_name = {} + for node in input_node.body: + if type(node) is ast.ClassDef and 'Regime' in node.name: + regime_class_node_by_name[node.name] = node + + # Recrée un AST en aplatissant les classes Regime + # (ie en en extrayant et renommant les variables OpenFisca). + variables_node = [] + for node in input_node.body: + if type(node) is ast.ClassDef and 'Regime' in node.name: + if 'Abstract' not in node.name: + parameters_prefix = get_regime_attribute(node, 'parameters_prefix') + variable_prefix = get_regime_attribute(node, 'variable_prefix') + flatten_regime( + regime_class_node_by_name, + node, + parameters_prefix, + variable_prefix, + set(), + variables_node, + ) + else: + output_node.body.append(node) + # Trie les variables OpenFisca par ordre alphabétique. + variables_node.sort(key = lambda variable_node: variable_node.name) + for variable_node in variables_node: + output_node.body.append(variable_node) + + # pour afficher le nouveau arbre AST faire une commande + # print(ast.dump(output_node, indent=4)) + + # convertir la structure logique de l'arbre AST en code python formatté (type string) + output_string = ast.unparse(output_node) + + # sauvegarder + with open(output_filename, 'w', encoding='utf-8') as file: + file.write(output_string) + + log.info(f'Result saved as {output_filename}') + + +def get_regime_attribute(regime_class_node, attribute): + '''Gets regime attribute. + + Args: + regime_class_node (ast.ClassDef): regime node + attribute (str): attribute name + + Returns: + [Any]: the attribute value + ''' + assert ( + isinstance(regime_class_node, ast.ClassDef) + and 'Regime' in regime_class_node.name + and 'Abstract' not in regime_class_node.name + ), f'{regime_class_node.name} is not a valid regime' + for sub_node in regime_class_node.body: + if isinstance(sub_node, ast.Assign): + for target in sub_node.targets: + if target.id == attribute: + assert isinstance(sub_node.value, ast.Constant), f'{sub_node.value} is not a constant' + return sub_node.value.value + + return None + + +def main(verbose = False): + regime_de_base = os.path.join( + tunisia_pension_root, + 'openfisca_tunisia_pension', + 'regimes', + 'regime.py' + ) + + regimes_files_by_name = { + name: { + 'input': os.path.join( + tunisia_pension_root, + 'openfisca_tunisia_pension', + 'regimes', + f'{name}.py' + ), + 'output': os.path.join( + tunisia_pension_root, + 'openfisca_tunisia_pension', + 'variables', + f'{name}.py' + ) + } + for name in [ + 'rsna', + # 'rsa', + # 'cnrps' + ] + } + + for _regime_name, regime_files in regimes_files_by_name.items(): + input_file_names = [ + regime_de_base, + regime_files['input'], + ] + input_string = '' + for input_filename in input_file_names: + with open(input_filename, encoding='utf-8') as file: + input_string += '\n' + file.read() + + logging.basicConfig(level = logging.DEBUG if verbose else logging.WARNING, stream = sys.stdout) + flatten_regimes(input_string, regime_files['output']) + + +if __name__ == '__main__': + main(verbose = True) diff --git a/openfisca_tunisia_pension/tunisia_pension_taxbenefitsystem.py b/openfisca_tunisia_pension/tunisia_pension_taxbenefitsystem.py deleted file mode 100644 index a844e21..0000000 --- a/openfisca_tunisia_pension/tunisia_pension_taxbenefitsystem.py +++ /dev/null @@ -1,25 +0,0 @@ -import glob -import os - -from openfisca_core.taxbenefitsystems import TaxBenefitSystem - -from openfisca_tunisia_pension import entities - -COUNTRY_DIR = os.path.dirname(os.path.abspath(__file__)) -EXTENSIONS_PATH = os.path.join(COUNTRY_DIR, 'extensions') -EXTENSIONS_DIRECTORIES = glob.glob(os.path.join(EXTENSIONS_PATH, '*/')) - - -class TunisiaPensionTaxBenefitSystem(TaxBenefitSystem): - '''Tunisian pensions tax benefit system''' - CURRENCY = 'DT' - - def __init__(self): - super(TunisiaPensionTaxBenefitSystem, self).__init__(entities.entities) - - # We add to our tax and benefit system all the variables - self.add_variables_from_directory(os.path.join(COUNTRY_DIR, 'variables')) - - # We add to our tax and benefit system all the legislation parameters defined in the parameters files - parameters_path = os.path.join(COUNTRY_DIR, 'parameters') - self.load_parameters(parameters_path) diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index 10fba9c..dec0cc0 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -40,7 +40,7 @@ class cnrps_pension(Variable): definition_period = YEAR def formula(individu, period, parameters): - trimestres_valides = individu('trimestres_valides', period = period) + duree_assurance = individu('duree_assurance', period = period) salaire_reference = individu('rsna_salaire_reference', period = period) age = individu('age', period = period) @@ -56,12 +56,12 @@ def formula(individu, period, parameters): pension_min_sup = rsna.pension_minimale.sup pension_min_inf = rsna.pension_minimale.inf - stage = trimestres_valides > 4 * duree_stage + stage = duree_assurance > 4 * duree_stage pension_minimale = ( stage * pension_min_sup + not_(stage) * pension_min_inf ) montant = pension_generique( - trimestres_valides, + duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, diff --git a/openfisca_tunisia_pension/variables/data.py b/openfisca_tunisia_pension/variables/data.py index 51a2ebc..8b666e5 100644 --- a/openfisca_tunisia_pension/variables/data.py +++ b/openfisca_tunisia_pension/variables/data.py @@ -25,7 +25,7 @@ class date_naissance(Variable): definition_period = ETERNITY -class trimestres_valides(Variable): +class duree_assurance(Variable): value_type = int entity = Individu label = 'Nombre de trimestres validés' diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index 01cde80..6f45c3a 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -5,13 +5,13 @@ from numpy import minimum as min_ -def pension_generique(trimestres_valides, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, +def pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_elig, periode_remplacement_base, plaf_taux_pension): taux_pension = ( - (trimestres_valides < 4 * periode_remplacement_base) * (trimestres_valides / 4) * taux_annuite_base - + (trimestres_valides >= 4 * periode_remplacement_base) * ( + (duree_assurance < 4 * periode_remplacement_base) * (duree_assurance / 4) * taux_annuite_base + + (duree_assurance >= 4 * periode_remplacement_base) * ( taux_annuite_base * periode_remplacement_base - + (trimestres_valides / 4 - periode_remplacement_base) * taux_annuite_supplementaire + + (duree_assurance / 4 - periode_remplacement_base) * taux_annuite_supplementaire ) ) montant = min_(taux_pension, plaf_taux_pension) * sal_ref diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index e7a84f3..e7f6d26 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -51,12 +51,12 @@ def formula(individu, period, parameters): periode_remplacement_base = rsa.periode_remplacement_base plaf_taux_pension = rsa.plaf_taux_pension smag = parameters(period).marche_travail.smag * 25 - duree_stage_validee = trimestres_valides > 4 * duree_stage + duree_stage_validee = duree_assurance > 4 * duree_stage pension_min = rsa.pension_min salaire_reference = individu('salaire_reference_rsa', period) montant = pension_generique( - trimestres_valides, + duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index de52705..9e01ac5 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -1,37 +1,78 @@ -import functools -from numpy import ( - apply_along_axis, - logical_not as not_, - maximum as max_, - vstack, - ) - +"""Abstract regimes definition.""" +from openfisca_core.model_api import * +from openfisca_tunisia_pension.entities import Individu +'Régime des salariés non agricoles.' from openfisca_core.model_api import * from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites +import functools +from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique +class rsna_cotisation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'cotisation retraite employeur' -class rsna_salaire_reference(Variable): + def formula(individu, period, parameters): + NotImplementedError + +class rsna_duree_assurance(Variable): + value_type = int + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (trimestres validés)" + +class rsna_duree_assurance_annuelle(Variable): value_type = float entity = Individu - label = 'Salaires de référence du régime des salariés non agricoles' definition_period = YEAR + label = "Durée d'assurance (en trimestres validés l'année considérée)" + +class rsna_liquidation_date(Variable): + value_type = date + entity = Individu + definition_period = ETERNITY + label = 'Date de liquidation' + default_value = date(2250, 12, 31) + +class rsna_majoration_duree_assurance(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance" def formula(individu, period): - # TODO: gérer le nombre d'année n - # TODO: plafonner les salaires à 6 fois le smig de l'année d'encaissement - n = 10 - mean_over_largest = functools.partial(mean_over_k_largest, k = n) - salaire_refererence = apply_along_axis( - mean_over_largest, - axis = 0, - arr = vstack([ - individu('salaire', period = year) - for year in range(period.start.year, period.start.year - n, -1) - ]), - ) - return salaire_refererence + return individu('rsna_majoration_duree_assurance_enfant', period) + individu('rsna_majoration_duree_assurance_autre', period) + +class rsna_majoration_duree_assurance_autre(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" +class rsna_majoration_pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension' + +class rsna_majoration_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsna_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + majoration_pension_au_31_decembre_annee_precedente = individu('rsna_majoration_pension_au_31_decembre', last_year) + revalorisation = parameters(period).rsna.revalorisation_pension_au_31_decembre + majoration_pension = individu('rsna_majoration_pension', period) + return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) class rsna_pension(Variable): value_type = float @@ -40,10 +81,9 @@ class rsna_pension(Variable): definition_period = YEAR def formula(individu, period, parameters): - trimestres_valides = individu('trimestres_valides', period = period) - salaire_reference = individu('rsna_salaire_reference', period = period) - age = individu('age', period = period) - + duree_assurance = individu('rsna_duree_assurance', period=period) + salaire_reference = individu('rsna_salaire_reference', period=period) + age = individu('age', period=period) rsna = parameters(period).retraite.rsna taux_annuite_base = rsna.taux_annuite_base taux_annuite_supplementaire = rsna.taux_annuite_supplementaire @@ -52,27 +92,101 @@ def formula(individu, period, parameters): periode_remplacement_base = rsna.periode_remplacement_base plaf_taux_pension = rsna.plaf_taux_pension smig = parameters(period).marche_travail.smig_48h - pension_min_sup = rsna.pension_minimale.sup pension_min_inf = rsna.pension_minimale.inf - - stage = trimestres_valides > 4 * duree_stage - pension_minimale = ( - stage * pension_min_sup + not_(stage) * pension_min_inf - ) - montant = pension_generique( - trimestres_valides, - salaire_reference, - taux_annuite_base, - taux_annuite_supplementaire, - duree_stage, - age_eligible, - periode_remplacement_base, - plaf_taux_pension, - ) - # eligibilite + stage = duree_assurance > 4 * duree_stage + pension_minimale = stage * pension_min_sup + not_(stage) * pension_min_inf + montant = pension_generique(duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension) eligibilite_age = age > age_eligible eligibilite = stage * eligibilite_age * (salaire_reference > 0) - # plafonnement montant_pension_percu = max_(montant, pension_minimale * smig) return eligibilite * montant_pension_percu + +class rsna_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period): + pension_brute_au_31_decembre = individu('rsna_pension_brute_au_31_decembre', period) + majoration_pension_au_31_decembre = individu('rsna_majoration_pension_au_31_decembre', period) + return pension_brute_au_31_decembre + majoration_pension_au_31_decembre + +class rsna_pension_brute(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute' + + def formula(individu, period, parameters): + NotImplementedError + +class rsna_pension_brute_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsna_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(period.start.year < annee_de_liquidation): + return individu.empty_array() + last_year = period.last_year + pension_brute_au_31_decembre_annee_precedente = individu('rsna_pension_brute_au_31_decembre', last_year) + revalorisation = parameters(period).rsna.revalorisation_pension_au_31_decembre + pension_brute = individu('rsna_pension_brute', period) + return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) + +class rsna_pension_servie(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension servie' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsna_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + pension_au_31_decembre_annee_precedente = individu('rsna_pension_au_31_decembre', last_year) + revalorisation = parameters(period).rsna.revalarisation_pension_servie + pension = individu('rsna_pension_au_31_decembre', period) + return revalorise(pension_au_31_decembre_annee_precedente, pension, annee_de_liquidation, revalorisation, period) + +class rsna_salaire_de_base(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Salaire de base (salaire brut)' + set_input = set_input_divide_by_period + +class rsna_salaire_de_reference(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = 'Salaire de référence' + +class rsna_salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period): + n = 10 + mean_over_largest = functools.partial(mean_over_k_largest, k=n) + salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('salaire', period=year) for year in range(period.start.year, period.start.year - n, -1)])) + return salaire_refererence + +class rsna_taux_de_liquidation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Taux de liquidation de la pension' + + def formula(individu, period, parameters): + decote = individu('rsna_decote', period) + surcote = individu('rsna_surcote', period) + taux_plein = parameters(period).rsna.taux_plein.taux_plein + return taux_plein * (1 - decote + surcote) \ No newline at end of file diff --git a/tests/formulas/pension_rsna.yaml b/tests/formulas/rsna_pension.yaml similarity index 94% rename from tests/formulas/pension_rsna.yaml rename to tests/formulas/rsna_pension.yaml index d8791e1..4ac5083 100644 --- a/tests/formulas/pension_rsna.yaml +++ b/tests/formulas/rsna_pension.yaml @@ -3,7 +3,7 @@ absolute_error_margin: 0.5 input: age: 60 - trimestres_valides: 50 + rsna_duree_assurance: 50 salaire: 1975: 12000 1976: 12000 @@ -46,6 +46,5 @@ 2013: 12000 2014: 12000 output: - trimestres_valides: 50 rsna_salaire_reference: 12000 rsna_pension: 5400 diff --git a/tests/formulas/salaire_reference_rsna.yaml b/tests/formulas/rsna_salaire_reference.yaml similarity index 94% rename from tests/formulas/salaire_reference_rsna.yaml rename to tests/formulas/rsna_salaire_reference.yaml index 852a402..f565e77 100644 --- a/tests/formulas/salaire_reference_rsna.yaml +++ b/tests/formulas/rsna_salaire_reference.yaml @@ -3,7 +3,7 @@ absolute_error_margin: 0.5 input: age: 60 - trimestres_valides: 50 + rsna_duree_assurance: 50 salaire: 1975: 12000 1976: 12000 @@ -46,5 +46,4 @@ 2013: 12000 2014: 12000 output: - trimestres_valides: 50 rsna_salaire_reference: 12000 From 5b23e2dff75f9804b6726215b58e21e47adbc5df Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 17:23:02 +0100 Subject: [PATCH 05/24] Fix tests --- openfisca_tunisia_pension/regimes/rsa.py | 3 - openfisca_tunisia_pension/regimes/rsna.py | 2 +- openfisca_tunisia_pension/variables/data.py | 14 ---- openfisca_tunisia_pension/variables/rsa.py | 73 --------------------- openfisca_tunisia_pension/variables/rsna.py | 2 +- tests/formulas/rsna_pension.yaml | 2 +- 6 files changed, 3 insertions(+), 93 deletions(-) delete mode 100644 openfisca_tunisia_pension/variables/rsa.py diff --git a/openfisca_tunisia_pension/regimes/rsa.py b/openfisca_tunisia_pension/regimes/rsa.py index c0b3b91..94722d2 100644 --- a/openfisca_tunisia_pension/regimes/rsa.py +++ b/openfisca_tunisia_pension/regimes/rsa.py @@ -6,13 +6,11 @@ from openfisca_tunisia_pension.entities import Individu from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -# from openfisca_tunisia_pension.tools import add_vectorial_timedelta, year_ import functools from numpy import ( apply_along_axis, - logical_not as not_, maximum as max_, vstack, ) @@ -50,7 +48,6 @@ def formula(individu, period): salaire_refererence = salaire * base_liquidation_rsa / base_declaration_rsa return salaire_refererence - class pension(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 00bc078..17de518 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -40,7 +40,7 @@ def formula(individu, period): mean_over_largest, axis = 0, arr = vstack([ - individu('salaire', period = year) + individu('regime_name_salaire_de_base', period = year) for year in range(period.start.year, period.start.year - n, -1) ]), ) diff --git a/openfisca_tunisia_pension/variables/data.py b/openfisca_tunisia_pension/variables/data.py index 8b666e5..0f78957 100644 --- a/openfisca_tunisia_pension/variables/data.py +++ b/openfisca_tunisia_pension/variables/data.py @@ -10,13 +10,6 @@ class age(Variable): definition_period = YEAR -class salaire(Variable): - value_type = float - entity = Individu - label = 'Salaires' - definition_period = YEAR - - class date_naissance(Variable): value_type = date default_value = date(1970, 1, 1) @@ -25,13 +18,6 @@ class date_naissance(Variable): definition_period = ETERNITY -class duree_assurance(Variable): - value_type = int - entity = Individu - label = 'Nombre de trimestres validés' - definition_period = YEAR - - class TypesRegimeSecuriteSociale(Enum): __order__ = 'rsna rsa rsaa rtns rtte re rtfr raci salarie_cnrps pensionne_cnrps' # Needed to preserve the enum order in Python 2 diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py deleted file mode 100644 index e7f6d26..0000000 --- a/openfisca_tunisia_pension/variables/rsa.py +++ /dev/null @@ -1,73 +0,0 @@ -import functools -from numpy import ( - apply_along_axis, - maximum as max_, - vstack, - ) - -from openfisca_core import periods -from openfisca_core.model_api import * -from openfisca_tunisia_pension.entities import Individu - - -class salaire_reference_rsa(Variable): - value_type = float - entity = Individu - label = 'Salaires de référence du régime des salariés agricoles' - definition_period = YEAR - - def formula(individu, period): - # TODO: gérer le nombre d'année - # TODO: plafonner les salaires à 2 fois le smag de l'année d'encaissement - base_declaration_rsa = 180 - base_liquidation_rsa = 300 - - n = 3 - mean_over_largest = functools.partial(mean_over_k_largest, k = n) - salaire = apply_along_axis( - mean_over_largest, - axis = 0, - arr = vstack([ - individu('salaire', period = periods.period('year', year)) - for year in range(period.start.year, period.start.year - n, -1) - ]), - ) - salaire_refererence = salaire * base_liquidation_rsa / base_declaration_rsa - return salaire_refererence - - -class rsa_pension(Variable): - value_type = float - entity = Individu - label = 'Salaires de référence du régime des salariés agricoles' - definition_period = YEAR - - def formula(individu, period, parameters): - rsa = parameters.retraite.rsa(period) - taux_annuite_base = rsa.taux_annuite_base - taux_annuite_supplementaire = rsa.taux_annuite_supplementaire - duree_stage = rsa.stage_requis - age_elig = rsa.age_legal - periode_remplacement_base = rsa.periode_remplacement_base - plaf_taux_pension = rsa.plaf_taux_pension - smag = parameters(period).marche_travail.smag * 25 - duree_stage_validee = duree_assurance > 4 * duree_stage - pension_min = rsa.pension_min - salaire_reference = individu('salaire_reference_rsa', period) - - montant = pension_generique( - duree_assurance, - sal_ref, - taux_annuite_base, - taux_annuite_supplementaire, - duree_stage, - age_elig, - periode_remplacement_base, - plaf_taux_pension - ) - - elig_age = age > age_elig - elig = duree_stage_validee * elig_age * (salaire_reference > 0) - montant_percu = max_(montant, pension_min * smag) - pension = elig * montant_percu - return pension diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index 9e01ac5..dff3f70 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -176,7 +176,7 @@ class rsna_salaire_reference(Variable): def formula(individu, period): n = 10 mean_over_largest = functools.partial(mean_over_k_largest, k=n) - salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('salaire', period=year) for year in range(period.start.year, period.start.year - n, -1)])) + salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('rsna_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) return salaire_refererence class rsna_taux_de_liquidation(Variable): diff --git a/tests/formulas/rsna_pension.yaml b/tests/formulas/rsna_pension.yaml index 4ac5083..b75395b 100644 --- a/tests/formulas/rsna_pension.yaml +++ b/tests/formulas/rsna_pension.yaml @@ -4,7 +4,7 @@ input: age: 60 rsna_duree_assurance: 50 - salaire: + rsna_salaire_de_base: 1975: 12000 1976: 12000 1977: 12000 From 8cf929208213c9e4c9b5a979ef59c8ed91de80a7 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Sat, 16 Nov 2024 17:23:09 +0100 Subject: [PATCH 06/24] Again --- tests/formulas/rsna_salaire_reference.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/formulas/rsna_salaire_reference.yaml b/tests/formulas/rsna_salaire_reference.yaml index f565e77..3e9ce9f 100644 --- a/tests/formulas/rsna_salaire_reference.yaml +++ b/tests/formulas/rsna_salaire_reference.yaml @@ -4,7 +4,7 @@ input: age: 60 rsna_duree_assurance: 50 - salaire: + rsna_salaire_de_base: 1975: 12000 1976: 12000 1977: 12000 From 49d7c5c3edb8299eebe4938170d09649cb09a6bb Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 10:17:23 +0100 Subject: [PATCH 07/24] Fix cnrps --- openfisca_tunisia_pension/regimes/cnrps.py | 100 +++++++++++++++++++ openfisca_tunisia_pension/variables/cnrps.py | 78 --------------- 2 files changed, 100 insertions(+), 78 deletions(-) create mode 100644 openfisca_tunisia_pension/regimes/cnrps.py delete mode 100644 openfisca_tunisia_pension/variables/cnrps.py diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py new file mode 100644 index 0000000..47cc34e --- /dev/null +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -0,0 +1,100 @@ +'''Régime de la Caisse nationale de retraite et de prévoyance sociale (CNRPS).''' + + +from openfisca_core.model_api import * + + +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites + + +import functools +from numpy import ( + apply_along_axis, + logical_not as not_, + maximum as max_, + vstack, + ) + +from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + + +class RegimeCNRPS(AbstractRegimeEnAnnuites): + name = 'Régime des salariés non agricoles' + variable_prefix = 'cnrps' + parameters_prefix = 'cnrps' + + class salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime de la CNRPS' + definition_period = YEAR + + def formula(individu, period): + '''3 dernières rémunérations ou les 2 plus élevées sur demande.''' + n = 40 + k = 2 + mean_over_largest = functools.partial(mean_over_k_largest, k = k) + moyenne_2_salaires_plus_eleves = apply_along_axis( + mean_over_largest, + axis = 0, + arr = vstack([ + individu('regime_name_salaire_de_base', period = year) + for year in range(period.start.year, period.start.year - n, -1) + ]), + ) + p = 3 + moyenne_3_derniers_salaires = sum( + individu('regime_name_salaire_de_base', period = year) + for year in range(period.start.year, period.start.year - p, -1) + ) / p + + salaire_refererence = max_( + moyenne_3_derniers_salaires, + moyenne_2_salaires_plus_eleves + ) + return salaire_refererence + + class pension(Variable): + value_type = float + entity = Individu + label = 'Pension des affiliés au régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('regime_name_duree_assurance', period = period) + salaire_reference = individu('regime_name_salaire_reference', period = period) + age = individu('age', period = period) + + cnrps = parameters(period).retraite.regime_name + taux_annuite_base = cnrps.taux_annuite_base + taux_annuite_supplementaire = cnrps.taux_annuite_supplementaire + duree_stage = cnrps.stage_derog + age_eligible = cnrps.age_dep_anticip + periode_remplacement_base = cnrps.periode_remplacement_base + plaf_taux_pension = cnrps.plaf_taux_pension + smig = parameters(period).marche_travail.smig_48h + + pension_min_sup = cnrps.pension_minimale.sup + pension_min_inf = cnrps.pension_minimale.inf + + stage = duree_assurance > 4 * duree_stage + pension_minimale = ( + stage * pension_min_sup + not_(stage) * pension_min_inf + ) + montant = pension_generique( + duree_assurance, + salaire_reference, + taux_annuite_base, + taux_annuite_supplementaire, + duree_stage, + age_eligible, + periode_remplacement_base, + plaf_taux_pension, + ) + # eligibilite + eligibilite_age = age > age_eligible + eligibilite = stage * eligibilite_age * (salaire_reference > 0) + # plafonnement + montant_pension_percu = max_(montant, pension_minimale * smig) + return eligibilite * montant_pension_percu diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py deleted file mode 100644 index dec0cc0..0000000 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ /dev/null @@ -1,78 +0,0 @@ -import functools -from numpy import ( - apply_along_axis, - logical_not as not_, - maximum as max_, - vstack, - ) - -from openfisca_core.model_api import * -from openfisca_tunisia_pension.entities import Individu -from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique - - -class cnrps_salaire_reference(Variable): - value_type = float - entity = Individu - label = 'Salaire de référence de la CNRPS' - definition_period = YEAR - - def formula(individu, period): - # TODO: gérer le nombre d'année n - # TODO: plafonner les salaires à 6 fois le smig de l'année d'encaissement - n = 10 - mean_over_largest = functools.partial(mean_over_k_largest, k = n) - salaire_refererence = apply_along_axis( - mean_over_largest, - axis = 0, - arr = vstack([ - individu('salaire', period = year) - for year in range(period.start.year, period.start.year - n, -1) - ]), - ) - return salaire_refererence - - -class cnrps_pension(Variable): - value_type = float - entity = Individu - label = 'Pension des affiliés au régime des salariés non agricoles' - definition_period = YEAR - - def formula(individu, period, parameters): - duree_assurance = individu('duree_assurance', period = period) - salaire_reference = individu('rsna_salaire_reference', period = period) - age = individu('age', period = period) - - rsna = parameters(period).retraite.rsna - taux_annuite_base = rsna.taux_annuite_base - taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - duree_stage = rsna.stage_derog - age_eligible = rsna.age_dep_anticip - periode_remplacement_base = rsna.periode_remplacement_base - plaf_taux_pension = rsna.plaf_taux_pension - smig = parameters(period).marche_travail.smig_48h - - pension_min_sup = rsna.pension_minimale.sup - pension_min_inf = rsna.pension_minimale.inf - - stage = duree_assurance > 4 * duree_stage - pension_minimale = ( - stage * pension_min_sup + not_(stage) * pension_min_inf - ) - montant = pension_generique( - duree_assurance, - salaire_reference, - taux_annuite_base, - taux_annuite_supplementaire, - duree_stage, - age_eligible, - periode_remplacement_base, - plaf_taux_pension, - ) - # eligibilite - eligibilite_age = age > age_eligible - eligibilite = stage * eligibilite_age * (salaire_reference > 0) - # plafonnement - montant_pension_percu = max_(montant, pension_minimale * smig) - return eligibilite * montant_pension_percu From efc14b3e1270a3dd5ae94bd35b93e5baceb45068 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 10:26:59 +0100 Subject: [PATCH 08/24] Fix config --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 1b0f35b..8abdeec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ ignore = ["E128","E251","F403","F405","E501","W503"] docstring-quotes = "single" inline-quotes = "single" multiline-quotes = "single" +exclude = "openfisca_tunisia_pension/variables/*.py" [tool.pep8] hang-closing = true From 7a573eb5d76765f5d12b0516007893b8b3d74ce4 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 11:54:23 +0100 Subject: [PATCH 09/24] Add cnrps tests --- openfisca_tunisia_pension/regimes/cnrps.py | 11 +- openfisca_tunisia_pension/regimes/rsa.py | 9 +- openfisca_tunisia_pension/regimes/rsna.py | 10 +- .../scripts_ast/script_ast.py | 4 +- openfisca_tunisia_pension/tools.py | 26 +++ openfisca_tunisia_pension/variables/cnrps.py | 197 ++++++++++++++++++ .../variables/helpers.py | 13 -- openfisca_tunisia_pension/variables/rsa.py | 193 +++++++++++++++++ openfisca_tunisia_pension/variables/rsna.py | 9 +- pyproject.toml | 2 +- .../cnrps/cnrps_salaire_reference.yaml | 100 +++++++++ tests/formulas/{ => rsna}/rsna_pension.yaml | 0 tests/formulas/rsna_salaire_reference.yaml | 49 ----- 13 files changed, 539 insertions(+), 84 deletions(-) create mode 100644 openfisca_tunisia_pension/tools.py create mode 100644 openfisca_tunisia_pension/variables/cnrps.py create mode 100644 openfisca_tunisia_pension/variables/rsa.py create mode 100644 tests/formulas/cnrps/cnrps_salaire_reference.yaml rename tests/formulas/{ => rsna}/rsna_pension.yaml (100%) delete mode 100644 tests/formulas/rsna_salaire_reference.yaml diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index 47cc34e..de10c09 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -8,7 +8,6 @@ from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -import functools from numpy import ( apply_along_axis, logical_not as not_, @@ -16,7 +15,8 @@ vstack, ) -from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique +from openfisca_tunisia_pension.variables.helpers import pension_generique +from openfisca_tunisia_pension.tools import make_mean_over_largest class RegimeCNRPS(AbstractRegimeEnAnnuites): @@ -34,14 +34,11 @@ def formula(individu, period): '''3 dernières rémunérations ou les 2 plus élevées sur demande.''' n = 40 k = 2 - mean_over_largest = functools.partial(mean_over_k_largest, k = k) + mean_over_largest = make_mean_over_largest(k) moyenne_2_salaires_plus_eleves = apply_along_axis( mean_over_largest, axis = 0, - arr = vstack([ - individu('regime_name_salaire_de_base', period = year) - for year in range(period.start.year, period.start.year - n, -1) - ]), + arr = vstack([individu('regime_name_salaire_de_base', period = year) for year in range(period.start.year, period.start.year - n, -1)]), ) p = 3 moyenne_3_derniers_salaires = sum( diff --git a/openfisca_tunisia_pension/regimes/rsa.py b/openfisca_tunisia_pension/regimes/rsa.py index 94722d2..02823ed 100644 --- a/openfisca_tunisia_pension/regimes/rsa.py +++ b/openfisca_tunisia_pension/regimes/rsa.py @@ -8,14 +8,15 @@ from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -import functools from numpy import ( apply_along_axis, maximum as max_, vstack, ) -from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + +from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.variables.helpers import pension_generique class RegimeRSA(AbstractRegimeEnAnnuites): @@ -35,8 +36,8 @@ def formula(individu, period): base_declaration_rsa = 180 base_liquidation_rsa = 300 - n = 3 - mean_over_largest = functools.partial(mean_over_k_largest, k = n) + k = 3 + mean_over_largest = make_mean_over_largest(k) salaire = apply_along_axis( mean_over_largest, axis = 0, diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 17de518..3221e56 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -9,7 +9,6 @@ # from openfisca_tunisia_pension.tools import add_vectorial_timedelta, year_ -import functools from numpy import ( apply_along_axis, logical_not as not_, @@ -17,7 +16,9 @@ vstack, ) -from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique + +from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.variables.helpers import pension_generique class RegimeRSNA(AbstractRegimeEnAnnuites): @@ -34,8 +35,9 @@ class salaire_reference(Variable): def formula(individu, period): # TODO: gérer le nombre d'année n # TODO: plafonner les salaires à 6 fois le smig de l'année d'encaissement - n = 10 - mean_over_largest = functools.partial(mean_over_k_largest, k = n) + k = 10 + mean_over_largest = make_mean_over_largest(k = k) + n = 40 salaire_refererence = apply_along_axis( mean_over_largest, axis = 0, diff --git a/openfisca_tunisia_pension/scripts_ast/script_ast.py b/openfisca_tunisia_pension/scripts_ast/script_ast.py index 843d3f9..c9aa253 100644 --- a/openfisca_tunisia_pension/scripts_ast/script_ast.py +++ b/openfisca_tunisia_pension/scripts_ast/script_ast.py @@ -214,8 +214,8 @@ def main(verbose = False): } for name in [ 'rsna', - # 'rsa', - # 'cnrps' + 'rsa', + 'cnrps' ] } diff --git a/openfisca_tunisia_pension/tools.py b/openfisca_tunisia_pension/tools.py new file mode 100644 index 0000000..219c07d --- /dev/null +++ b/openfisca_tunisia_pension/tools.py @@ -0,0 +1,26 @@ +'''Tools.''' + + +from numba import float32, int64, jit +import numpy as np + + +def make_mean_over_largest(k): + def mean_over_largest(vector): + return mean_over_k_nonzero_largest(vector, k = int(k)) + + return mean_over_largest + + +@jit(float32(float32[:], int64), nopython=True) +def mean_over_k_nonzero_largest(vector, k): + '''Return the mean over the k largest values of a vector.''' + if k == 0: + return 0 + nonzeros = (vector > 0.0).sum() + if k >= nonzeros: + return vector.sum() / (nonzeros + (nonzeros == 0)) + + z = -np.partition(-vector, kth = k) + upper_bound = min(k, nonzeros) + return z[:upper_bound].sum() / upper_bound diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py new file mode 100644 index 0000000..a1dafc8 --- /dev/null +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -0,0 +1,197 @@ +"""Abstract regimes definition.""" +from openfisca_core.model_api import * +from openfisca_tunisia_pension.entities import Individu +'Régime de la Caisse nationale de retraite et de prévoyance sociale (CNRPS).' +from openfisca_core.model_api import * +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites +from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack +from openfisca_tunisia_pension.variables.helpers import pension_generique +from openfisca_tunisia_pension.tools import make_mean_over_largest + +class cnrps_cotisation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'cotisation retraite employeur' + + def formula(individu, period, parameters): + NotImplementedError + +class cnrps_duree_assurance(Variable): + value_type = int + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (trimestres validés)" + +class cnrps_duree_assurance_annuelle(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (en trimestres validés l'année considérée)" + +class cnrps_liquidation_date(Variable): + value_type = date + entity = Individu + definition_period = ETERNITY + label = 'Date de liquidation' + default_value = date(2250, 12, 31) + +class cnrps_majoration_duree_assurance(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance" + + def formula(individu, period): + return individu('cnrps_majoration_duree_assurance_enfant', period) + individu('cnrps_majoration_duree_assurance_autre', period) + +class cnrps_majoration_duree_assurance_autre(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" + +class cnrps_majoration_pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension' + +class cnrps_majoration_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('cnrps_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + majoration_pension_au_31_decembre_annee_precedente = individu('cnrps_majoration_pension_au_31_decembre', last_year) + revalorisation = parameters(period).cnrps.revalorisation_pension_au_31_decembre + majoration_pension = individu('cnrps_majoration_pension', period) + return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) + +class cnrps_pension(Variable): + value_type = float + entity = Individu + label = 'Pension des affiliés au régime des salariés non agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('cnrps_duree_assurance', period=period) + salaire_reference = individu('cnrps_salaire_reference', period=period) + age = individu('age', period=period) + cnrps = parameters(period).retraite.cnrps + taux_annuite_base = cnrps.taux_annuite_base + taux_annuite_supplementaire = cnrps.taux_annuite_supplementaire + duree_stage = cnrps.stage_derog + age_eligible = cnrps.age_dep_anticip + periode_remplacement_base = cnrps.periode_remplacement_base + plaf_taux_pension = cnrps.plaf_taux_pension + smig = parameters(period).marche_travail.smig_48h + pension_min_sup = cnrps.pension_minimale.sup + pension_min_inf = cnrps.pension_minimale.inf + stage = duree_assurance > 4 * duree_stage + pension_minimale = stage * pension_min_sup + not_(stage) * pension_min_inf + montant = pension_generique(duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension) + eligibilite_age = age > age_eligible + eligibilite = stage * eligibilite_age * (salaire_reference > 0) + montant_pension_percu = max_(montant, pension_minimale * smig) + return eligibilite * montant_pension_percu + +class cnrps_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period): + pension_brute_au_31_decembre = individu('cnrps_pension_brute_au_31_decembre', period) + majoration_pension_au_31_decembre = individu('cnrps_majoration_pension_au_31_decembre', period) + return pension_brute_au_31_decembre + majoration_pension_au_31_decembre + +class cnrps_pension_brute(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute' + + def formula(individu, period, parameters): + NotImplementedError + +class cnrps_pension_brute_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('cnrps_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(period.start.year < annee_de_liquidation): + return individu.empty_array() + last_year = period.last_year + pension_brute_au_31_decembre_annee_precedente = individu('cnrps_pension_brute_au_31_decembre', last_year) + revalorisation = parameters(period).cnrps.revalorisation_pension_au_31_decembre + pension_brute = individu('cnrps_pension_brute', period) + return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) + +class cnrps_pension_servie(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension servie' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('cnrps_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + pension_au_31_decembre_annee_precedente = individu('cnrps_pension_au_31_decembre', last_year) + revalorisation = parameters(period).cnrps.revalarisation_pension_servie + pension = individu('cnrps_pension_au_31_decembre', period) + return revalorise(pension_au_31_decembre_annee_precedente, pension, annee_de_liquidation, revalorisation, period) + +class cnrps_salaire_de_base(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Salaire de base (salaire brut)' + set_input = set_input_divide_by_period + +class cnrps_salaire_de_reference(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = 'Salaire de référence' + +class cnrps_salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime de la CNRPS' + definition_period = YEAR + + def formula(individu, period): + """3 dernières rémunérations ou les 2 plus élevées sur demande.""" + n = 40 + k = 2 + mean_over_largest = make_mean_over_largest(k) + moyenne_2_salaires_plus_eleves = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) + p = 3 + moyenne_3_derniers_salaires = sum((individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - p, -1))) / p + salaire_refererence = max_(moyenne_3_derniers_salaires, moyenne_2_salaires_plus_eleves) + return salaire_refererence + +class cnrps_taux_de_liquidation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Taux de liquidation de la pension' + + def formula(individu, period, parameters): + decote = individu('cnrps_decote', period) + surcote = individu('cnrps_surcote', period) + taux_plein = parameters(period).cnrps.taux_plein.taux_plein + return taux_plein * (1 - decote + surcote) \ No newline at end of file diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index 6f45c3a..6776790 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -1,7 +1,6 @@ '''Helper functions''' -import bottleneck from numpy import minimum as min_ @@ -16,15 +15,3 @@ def pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_ ) montant = min_(taux_pension, plaf_taux_pension) * sal_ref return montant - - -def mean_over_k_largest(vector, k): - '''Return the mean over the k largest values of a vector''' - if k == 0: - return 0 - - if k <= len(vector): - return vector.sum() / len(vector) - - z = -bottleneck.partition(-vector, kth = k) - return z.sum() / k diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py new file mode 100644 index 0000000..5543fb7 --- /dev/null +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -0,0 +1,193 @@ +"""Abstract regimes definition.""" +from openfisca_core.model_api import * +from openfisca_tunisia_pension.entities import Individu +'Régime des salariés agricoles.' +from openfisca_core.model_api import * +from openfisca_core import periods +from openfisca_tunisia_pension.entities import Individu +from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites +from numpy import apply_along_axis, maximum as max_, vstack +from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.variables.helpers import pension_generique + +class rsa_cotisation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'cotisation retraite employeur' + + def formula(individu, period, parameters): + NotImplementedError + +class rsa_duree_assurance(Variable): + value_type = int + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (trimestres validés)" + +class rsa_duree_assurance_annuelle(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = "Durée d'assurance (en trimestres validés l'année considérée)" + +class rsa_liquidation_date(Variable): + value_type = date + entity = Individu + definition_period = ETERNITY + label = 'Date de liquidation' + default_value = date(2250, 12, 31) + +class rsa_majoration_duree_assurance(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance" + + def formula(individu, period): + return individu('rsa_majoration_duree_assurance_enfant', period) + individu('rsa_majoration_duree_assurance_autre', period) + +class rsa_majoration_duree_assurance_autre(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" + +class rsa_majoration_pension(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension' + +class rsa_majoration_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Majoration de pension au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsa_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + majoration_pension_au_31_decembre_annee_precedente = individu('rsa_majoration_pension_au_31_decembre', last_year) + revalorisation = parameters(period).rsa.revalorisation_pension_au_31_decembre + majoration_pension = individu('rsa_majoration_pension', period) + return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) + +class rsa_pension(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés agricoles' + definition_period = YEAR + + def formula(individu, period, parameters): + rsa = parameters(period).retraite.rsa + taux_annuite_base = rsa.taux_annuite_base + taux_annuite_supplementaire = rsa.taux_annuite_supplementaire + duree_stage = rsa.stage_requis + age_elig = rsa.age_legal + periode_remplacement_base = rsa.periode_remplacement_base + plaf_taux_pension = rsa.plaf_taux_pension + smag = parameters(period).marche_travail.smag * 25 + duree_stage_validee = duree_assurance > 4 * duree_stage + pension_min = rsa.pension_min + salaire_reference = individu('rsa_salaire_reference', period) + montant = pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_elig, periode_remplacement_base, plaf_taux_pension) + elig_age = age > age_elig + elig = duree_stage_validee * elig_age * (salaire_reference > 0) + montant_percu = max_(montant, pension_min * smag) + pension = elig * montant_percu + return pension + +class rsa_pension_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension' + + def formula(individu, period): + pension_brute_au_31_decembre = individu('rsa_pension_brute_au_31_decembre', period) + majoration_pension_au_31_decembre = individu('rsa_majoration_pension_au_31_decembre', period) + return pension_brute_au_31_decembre + majoration_pension_au_31_decembre + +class rsa_pension_brute(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute' + + def formula(individu, period, parameters): + NotImplementedError + +class rsa_pension_brute_au_31_decembre(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute au 31 décembre' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsa_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(period.start.year < annee_de_liquidation): + return individu.empty_array() + last_year = period.last_year + pension_brute_au_31_decembre_annee_precedente = individu('rsa_pension_brute_au_31_decembre', last_year) + revalorisation = parameters(period).rsa.revalorisation_pension_au_31_decembre + pension_brute = individu('rsa_pension_brute', period) + return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) + +class rsa_pension_servie(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension servie' + + def formula(individu, period, parameters): + annee_de_liquidation = individu('rsa_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 + if all(annee_de_liquidation > period.start.year): + return individu.empty_array() + last_year = period.last_year + pension_au_31_decembre_annee_precedente = individu('rsa_pension_au_31_decembre', last_year) + revalorisation = parameters(period).rsa.revalarisation_pension_servie + pension = individu('rsa_pension_au_31_decembre', period) + return revalorise(pension_au_31_decembre_annee_precedente, pension, annee_de_liquidation, revalorisation, period) + +class rsa_salaire_de_base(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Salaire de base (salaire brut)' + set_input = set_input_divide_by_period + +class rsa_salaire_de_reference(Variable): + value_type = float + entity = Individu + definition_period = ETERNITY + label = 'Salaire de référence' + +class rsa_salaire_reference(Variable): + value_type = float + entity = Individu + label = 'Salaires de référence du régime des salariés agricoles' + definition_period = YEAR + + def formula(individu, period): + base_declaration_rsa = 180 + base_liquidation_rsa = 300 + k = 3 + mean_over_largest = make_mean_over_largest(k) + salaire = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('salaire', period=periods.period('year', year)) for year in range(period.start.year, period.start.year - n, -1)])) + salaire_refererence = salaire * base_liquidation_rsa / base_declaration_rsa + return salaire_refererence + +class rsa_taux_de_liquidation(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Taux de liquidation de la pension' + + def formula(individu, period, parameters): + decote = individu('rsa_decote', period) + surcote = individu('rsa_surcote', period) + taux_plein = parameters(period).rsa.taux_plein.taux_plein + return taux_plein * (1 - decote + surcote) \ No newline at end of file diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index dff3f70..21cdc10 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -5,9 +5,9 @@ from openfisca_core.model_api import * from openfisca_tunisia_pension.entities import Individu from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -import functools from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack -from openfisca_tunisia_pension.variables.helpers import mean_over_k_largest, pension_generique +from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.variables.helpers import pension_generique class rsna_cotisation(Variable): value_type = float @@ -174,8 +174,9 @@ class rsna_salaire_reference(Variable): definition_period = YEAR def formula(individu, period): - n = 10 - mean_over_largest = functools.partial(mean_over_k_largest, k=n) + k = 10 + mean_over_largest = make_mean_over_largest(k=k) + n = 40 salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('rsna_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) return salaire_refererence diff --git a/pyproject.toml b/pyproject.toml index 8abdeec..cb483b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ ] requires-python = ">= 3.9" dependencies = [ - 'bottleneck >=1.4.2, <2.0.0', + "numba>=0.54,<1.0.0", 'numpy >=1.24.3, <2', 'openfisca-core[web-api] >=41.5.0, <41.5.3', 'scipy >= 0.12', diff --git a/tests/formulas/cnrps/cnrps_salaire_reference.yaml b/tests/formulas/cnrps/cnrps_salaire_reference.yaml new file mode 100644 index 0000000..29b5254 --- /dev/null +++ b/tests/formulas/cnrps/cnrps_salaire_reference.yaml @@ -0,0 +1,100 @@ +# - name: "Individu salarié 12000 DT par an toute sa carrière" +# period: 2014 +# absolute_error_margin: 0.5 +# input: +# age: 60 +# cnrps_duree_assurance: 50 +# cnrps_salaire_de_base: +# 1975: 12000 +# 1976: 12000 +# 1977: 12000 +# 1978: 12000 +# 1979: 12000 +# 1980: 12000 +# 1981: 12000 +# 1982: 12000 +# 1983: 12000 +# 1984: 12000 +# 1985: 12000 +# 1986: 12000 +# 1987: 12000 +# 1988: 12000 +# 1989: 12000 +# 1990: 12000 +# 1991: 12000 +# 1992: 12000 +# 1993: 12000 +# 1994: 12000 +# 1995: 12000 +# 1996: 12000 +# 1997: 12000 +# 1998: 12000 +# 1999: 12000 +# 2000: 12000 +# 2001: 12000 +# 2002: 12000 +# 2003: 12000 +# 2004: 12000 +# 2005: 12000 +# 2006: 12000 +# 2007: 12000 +# 2008: 12000 +# 2009: 12000 +# 2010: 12000 +# 2011: 12000 +# 2012: 12000 +# 2013: 15000 +# 2014: 18000 +# output: +# cnrps_salaire_reference: 15000 + + +- name: "Individu salarié 12000 DT par an toute sa carrière" + period: 2014 + absolute_error_margin: 0.5 + input: + age: 60 + cnrps_duree_assurance: 50 + cnrps_salaire_de_base: + 1975: 12000 + 1976: 12000 + 1977: 12000 + 1978: 12000 + 1979: 12000 + 1980: 12000 + 1981: 12000 + 1982: 12000 + 1983: 12000 + 1984: 12000 + 1985: 12000 + 1986: 12000 + 1987: 12000 + 1988: 12000 + 1989: 12000 + 1990: 12000 + 1991: 12000 + 1992: 12000 + 1993: 12000 + 1994: 12000 + 1995: 12000 + 1996: 12000 + 1997: 12000 + 1998: 12000 + 1999: 20000 + 2000: 20000 + 2001: 20000 + 2002: 12000 + 2003: 12000 + 2004: 12000 + 2005: 12000 + 2006: 12000 + 2007: 12000 + 2008: 12000 + 2009: 12000 + 2010: 12000 + 2011: 12000 + 2012: 12000 + 2013: 15000 + 2014: 18000 + output: + cnrps_salaire_reference: 20000 diff --git a/tests/formulas/rsna_pension.yaml b/tests/formulas/rsna/rsna_pension.yaml similarity index 100% rename from tests/formulas/rsna_pension.yaml rename to tests/formulas/rsna/rsna_pension.yaml diff --git a/tests/formulas/rsna_salaire_reference.yaml b/tests/formulas/rsna_salaire_reference.yaml deleted file mode 100644 index 3e9ce9f..0000000 --- a/tests/formulas/rsna_salaire_reference.yaml +++ /dev/null @@ -1,49 +0,0 @@ -- name: "Individu salarié 12000 DT par an toute sa carrière" - period: 2011 - absolute_error_margin: 0.5 - input: - age: 60 - rsna_duree_assurance: 50 - rsna_salaire_de_base: - 1975: 12000 - 1976: 12000 - 1977: 12000 - 1978: 12000 - 1979: 12000 - 1980: 12000 - 1981: 12000 - 1982: 12000 - 1983: 12000 - 1984: 12000 - 1985: 12000 - 1986: 12000 - 1987: 12000 - 1988: 12000 - 1989: 12000 - 1990: 12000 - 1991: 12000 - 1992: 12000 - 1993: 12000 - 1994: 12000 - 1995: 12000 - 1996: 12000 - 1997: 12000 - 1998: 12000 - 1999: 12000 - 2000: 12000 - 2001: 12000 - 2002: 12000 - 2003: 12000 - 2004: 12000 - 2005: 12000 - 2006: 12000 - 2007: 12000 - 2008: 12000 - 2009: 12000 - 2010: 12000 - 2011: 12000 - 2012: 12000 - 2013: 12000 - 2014: 12000 - output: - rsna_salaire_reference: 12000 From 760bb884ee59710de12b76e31160a110bb94d895 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 15:05:56 +0100 Subject: [PATCH 10/24] Start modifying pension_generique --- .../parameters/marche_travail/smig_40h.yaml | 2 +- .../parameters/marche_travail/smig_48h.yaml | 2 +- .../retraite/rsna/age_dep_anticip.yaml | 4 +- .../parameters/retraite/rsna/age_legal.yaml | 4 +- .../retraite/rsna/pension_minimale/index.yaml | 2 +- .../retraite/rsna/pension_minimale/inf.yaml | 2 + .../retraite/rsna/pension_minimale/sup.yaml | 2 + .../rsna/periode_remplacement_base.yaml | 4 +- .../parameters/retraite/rsna/stage_derog.yaml | 4 +- .../retraite/rsna/stage_requis.yaml | 4 +- openfisca_tunisia_pension/units.yaml | 6 ++ .../variables/helpers.py | 57 ++++++++++++++++--- 12 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 openfisca_tunisia_pension/units.yaml diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml index 749b185..726bbd5 100644 --- a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml @@ -1,4 +1,4 @@ -description: SMIG 40h +description: Smig 40h unit: currency values: 1995-05-01: diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml index 7ef4fba..0665d7b 100644 --- a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml @@ -1,4 +1,4 @@ -description: SMIG 48h +description: Smig 48h unit: currency values: 1995-05-01: diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/age_dep_anticip.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/age_dep_anticip.yaml index 051cbd9..6d35e32 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/age_dep_anticip.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/age_dep_anticip.yaml @@ -1,4 +1,6 @@ description: Age minimum de départ à la retraite anticipée values: 1974-01-01: - value: 50.0 + value: 50 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/age_legal.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/age_legal.yaml index 71c8a6e..efce31f 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/age_legal.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/age_legal.yaml @@ -1,4 +1,6 @@ description: Age légal de de départ à la retraite values: 1974-01-01: - value: 60.0 + value: 60 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/index.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/index.yaml index ad1832d..e978e81 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/index.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/index.yaml @@ -1 +1 @@ -description: Pension minimale (en part de SMIG) +description: Pension minimale (en part de Smig) diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml index 5f9da9c..56c1af8 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml @@ -3,3 +3,5 @@ unit: /1 values: 1974-01-01: value: 0.5 +metadata: + unit: Smig diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml index 285ec01..6c6433d 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml @@ -3,3 +3,5 @@ unit: /1 values: 1974-01-01: value: 0.66666 +metadata: + unit: Smig diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml index b7ef915..1ee84da 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml @@ -1,4 +1,6 @@ description: Période de remplacement de base values: 1974-01-01: - value: 10.0 + value: 10 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/stage_derog.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/stage_derog.yaml index e72d94e..9e8b242 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/stage_derog.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/stage_derog.yaml @@ -1,4 +1,6 @@ description: Durée du stage dérogatoire values: 1974-01-01: - value: 5.0 + value: 5 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/stage_requis.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/stage_requis.yaml index 9effa62..e80d608 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/stage_requis.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/stage_requis.yaml @@ -1,4 +1,6 @@ description: Durée normale du stage requis values: 1974-01-01: - value: 10.0 + value: 10 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/units.yaml b/openfisca_tunisia_pension/units.yaml new file mode 100644 index 0000000..a1d97ed --- /dev/null +++ b/openfisca_tunisia_pension/units.yaml @@ -0,0 +1,6 @@ +- name: smig + label: + one: Smig + other: Smigs + # parameter: marche_travail.salaire_minimum.smig. + ratio: true diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index 6776790..5571e76 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -4,14 +4,57 @@ from numpy import minimum as min_ + + + def pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_elig, periode_remplacement_base, plaf_taux_pension): - taux_pension = ( - (duree_assurance < 4 * periode_remplacement_base) * (duree_assurance / 4) * taux_annuite_base - + (duree_assurance >= 4 * periode_remplacement_base) * ( - taux_annuite_base * periode_remplacement_base - + (duree_assurance / 4 - periode_remplacement_base) * taux_annuite_supplementaire + + bareme_annuite_en_trimestres = [ + { + 'threshold': 0, + 'annuity_rate': taux_annuite_base, + }, + { + 'threshold': periode_remplacement_base, + 'annuity_rate': taux_annuite_supplementaire, + }, + { + 'threshold': 40, + 'annuity_rate': 0, + }, + ] + + taux_pension_test = 0.0 + first = True + for bracket in bareme_annuite_en_trimestres: + if first: + lower_threshold = bracket['threshold'] + between_threshold_annuity_rate = bracket['annuity_rate'] + first = False + continue + + upper_threshold = bracket['threshold'] + + print(f'duree_assurance: {duree_assurance / 4}, lower_threshold: {lower_threshold}, upper_threshold: {upper_threshold}, taux_pension: {taux_pension_test}') + taux_pension_test += max( + 0, + min( + (duree_assurance / 4 - lower_threshold), + (upper_threshold - lower_threshold) + ) * between_threshold_annuity_rate ) - ) - montant = min_(taux_pension, plaf_taux_pension) * sal_ref + + lower_threshold = upper_threshold + between_threshold_annuity_rate = bracket['annuity_rate'] + + # taux_pension = ( + # (duree_assurance < 4 * periode_remplacement_base) * (duree_assurance / 4) * taux_annuite_base + # + (duree_assurance >= 4 * periode_remplacement_base) * ( + # taux_annuite_base * periode_remplacement_base + # + (duree_assurance / 4 - periode_remplacement_base) * taux_annuite_supplementaire + # ) + # ) + + montant = min_(taux_pension_test, plaf_taux_pension) * sal_ref return montant From 256c2951493822376d786f99d5c12f3ffbda4967 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 15:57:14 +0100 Subject: [PATCH 11/24] Add bareme_annuite --- .../retraite/cnrps/bareme_annuite.yaml | 29 +++++++++++++++++++ ...uite_maximum => taux_annuite_maximum.yaml} | 3 +- .../cnrps/taux_annuite_periode_base.yaml | 2 +- .../taux_annuite_periode_supplemetaire.yaml | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml rename openfisca_tunisia_pension/parameters/retraite/cnrps/{taux_annuite_maximum => taux_annuite_maximum.yaml} (77%) diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml new file mode 100644 index 0000000..32863ed --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml @@ -0,0 +1,29 @@ +description: Taux d'annuité par trimestre validé +brackets: +- threshold: + 1959-02-01: + value: 0 + rate: + 1959-02-01: + value: 0.005 +- threshold: + 1959-02-01: + value: 40 + rate: + 1959-02-01: + value: 0.0075 +- threshold: + 1959-02-01: + value: 80 + rate: + 1959-02-01: + value: 0.005 +- threshold: + 1959-02-01: + value: 160 + rate: + 1959-02-01: + value: 0 +metadata: + threshold_unit: trimestre + rate_unit: /1 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml similarity index 77% rename from openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum rename to openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml index 6a99e35..7d45ec9 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml @@ -1,5 +1,6 @@ description: Taux d'annuité maximal -unit: /1 values: 1959-02-01: value: 0.9 +metadata: + unit: /1 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml index 13dec9e..a85c568 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml @@ -2,4 +2,4 @@ description: Taux d'annuité de la période de base (allant de la 1ère à la 10 unit: /1 values: 1959-02-01: - value: 0.05 + value: 0.005 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml index 43f6a96..ac14a9b 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml @@ -2,4 +2,4 @@ description: Taux d'annuité de la période supplémentaire (allant de la 11e à unit: /1 values: 1959-02-01: - value: 0.075 + value: 0.0075 From 4d0416ebbbd22d47aa26140d2a87ca19ccdba7c1 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 16:28:55 +0100 Subject: [PATCH 12/24] =?UTF-8?q?Move=20to=20bar=C3=A8mes=20annuit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../retraite/rsna/bareme_annuite.yaml | 23 ++++++++ openfisca_tunisia_pension/regimes/regime.py | 8 +-- openfisca_tunisia_pension/variables/cnrps.py | 8 +-- openfisca_tunisia_pension/variables/rsa.py | 8 +-- openfisca_tunisia_pension/variables/rsna.py | 8 +-- tests/formulas/cnrps/cnrps_pension.yaml | 55 +++++++++++++++++++ 6 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml create mode 100644 tests/formulas/cnrps/cnrps_pension.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml new file mode 100644 index 0000000..2499bd5 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml @@ -0,0 +1,23 @@ +description: Taux d'annuité par trimestre validé +brackets: +- threshold: + 1960-01-01: + value: 0 + rate: + 1960-01-01: + value: 0.01 +- threshold: + 1960-01-01: + value: 40 + rate: + 1960-01-01: + value: 0.005 +- threshold: + 1960-01-01: + value: 160 + rate: + 1960-01-01: + value: 0 +metadata: + threshold_unit: trimestre + rate_unit: /1 diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py index a2e1109..0fdb049 100644 --- a/openfisca_tunisia_pension/regimes/regime.py +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -228,10 +228,10 @@ class taux_de_liquidation(Variable): label = 'Taux de liquidation de la pension' def formula(individu, period, parameters): - decote = individu('regime_name_decote', period) - surcote = individu('regime_name_surcote', period) - taux_plein = parameters(period).regime_name.taux_plein.taux_plein - return taux_plein * (1 - decote + surcote) + bareme_annuite = parameters(period).retraite.regime_name.bareme_annuite + duree_assurance = individu('regime_name_duree_assurance', period) + taux_annuite = bareme_annuite.calc(duree_assurance) + return taux_annuite # def revalorise(variable_31_decembre_annee_precedente, variable_originale, annee_de_liquidation, revalorisation, period): diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index a1dafc8..218c716 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -191,7 +191,7 @@ class cnrps_taux_de_liquidation(Variable): label = 'Taux de liquidation de la pension' def formula(individu, period, parameters): - decote = individu('cnrps_decote', period) - surcote = individu('cnrps_surcote', period) - taux_plein = parameters(period).cnrps.taux_plein.taux_plein - return taux_plein * (1 - decote + surcote) \ No newline at end of file + bareme_annuite = parameters(period).retraite.cnrps.bareme_annuite + duree_assurance = individu('cnrps_duree_assurance', period) + taux_annuite = bareme_annuite.calc(duree_assurance) + return taux_annuite \ No newline at end of file diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index 5543fb7..eb0d422 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -187,7 +187,7 @@ class rsa_taux_de_liquidation(Variable): label = 'Taux de liquidation de la pension' def formula(individu, period, parameters): - decote = individu('rsa_decote', period) - surcote = individu('rsa_surcote', period) - taux_plein = parameters(period).rsa.taux_plein.taux_plein - return taux_plein * (1 - decote + surcote) \ No newline at end of file + bareme_annuite = parameters(period).retraite.rsa.bareme_annuite + duree_assurance = individu('rsa_duree_assurance', period) + taux_annuite = bareme_annuite.calc(duree_assurance) + return taux_annuite \ No newline at end of file diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index 21cdc10..52d610b 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -187,7 +187,7 @@ class rsna_taux_de_liquidation(Variable): label = 'Taux de liquidation de la pension' def formula(individu, period, parameters): - decote = individu('rsna_decote', period) - surcote = individu('rsna_surcote', period) - taux_plein = parameters(period).rsna.taux_plein.taux_plein - return taux_plein * (1 - decote + surcote) \ No newline at end of file + bareme_annuite = parameters(period).retraite.rsna.bareme_annuite + duree_assurance = individu('rsna_duree_assurance', period) + taux_annuite = bareme_annuite.calc(duree_assurance) + return taux_annuite \ No newline at end of file diff --git a/tests/formulas/cnrps/cnrps_pension.yaml b/tests/formulas/cnrps/cnrps_pension.yaml new file mode 100644 index 0000000..dd6e584 --- /dev/null +++ b/tests/formulas/cnrps/cnrps_pension.yaml @@ -0,0 +1,55 @@ +- name: "5 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 5 * 4 + output: + cnrps_taux_de_liquidation: .1 + +- name: "10 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 10 * 4 + output: + cnrps_taux_de_liquidation: .2 + +- name: "13 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 13 * 4 + output: + cnrps_taux_de_liquidation: .2 + .09 + +- name: "21 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 21 * 4 + output: + cnrps_taux_de_liquidation: .5 + .02 + +- name: "31 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 31 * 4 + output: + cnrps_taux_de_liquidation: .5 + .22 + +- name: "40 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 40 * 4 + output: + cnrps_taux_de_liquidation: .9 + +- name: "50 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 0.5 + input: + cnrps_duree_assurance: 50 * 4 + output: + cnrps_taux_de_liquidation: .9 From f4300cf2d0ffb346dfdc45d257e7c56b577c5718 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 16:34:39 +0100 Subject: [PATCH 13/24] Add parameters validation --- .github/workflows/tax-benefit.yml | 93 +++++++++++++++++++++++++++++ .github/workflows/validate_yaml.yml | 15 +++++ 2 files changed, 108 insertions(+) create mode 100644 .github/workflows/tax-benefit.yml create mode 100644 .github/workflows/validate_yaml.yml diff --git a/.github/workflows/tax-benefit.yml b/.github/workflows/tax-benefit.yml new file mode 100644 index 0000000..30ae73c --- /dev/null +++ b/.github/workflows/tax-benefit.yml @@ -0,0 +1,93 @@ +name: Validate, integrate & deploy to tax-benefit.org + +on: + - push + - workflow_dispatch + +jobs: + validate_yaml: + uses: tax-benefit/actions/.github/workflows/validate_yaml.yml@v2.1.0 + with: + parameters_path: "openfisca_tunisia_pension/parameters" + secrets: + token: ${{ secrets.CONTROL_CENTER_TOKEN }} + + deploy_parameters: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Clone Legislation Parameters Explorer + run: git clone https://git.leximpact.dev/leximpact/legislation-parameters-explorer.git + - name: Install Node.js version LTS + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + - name: Install viewer dependencies + run: npm install + working-directory: legislation-parameters-explorer/packages/viewer + - name: Configure viewer + run: | + rm -f .env + cat > .env << EOF + # Customizations to apply to the site (theme, URLs…) + CUSTOMIZATION="openfisca" + + DBNOMICS_DATASET_CODE="openfisca_tunisia_pension" + DBNOMICS_PROVIDER_CODE="OpenFisca" + DBNOMICS_URL="https://db.nomics.world/" + + EDITOR_URL="https://editor.parameters.tn.tax-benefit.org/" + + EXPORT_CSV=true + EXPORT_JSON=false + EXPORT_XLSX=true + + # Path of directory containing legislation parameters of country + PARAMETERS_DIR="../../../openfisca_tunisia_pension/parameters/" + + # Description of parameters remote repository + PARAMETERS_AUTHOR_EMAIL="editor.parameters.tn@tax-benefit.org" + PARAMETERS_AUTHOR_NAME="Éditeur des paramètres d'OpenFisca-Tunisia-Pension" + PARAMETERS_BRANCH="main" + PARAMETERS_FORGE_DOMAIN_NAME="github.com" + PARAMETERS_FORGE_TYPE="GitHub" + PARAMETERS_GROUP="openfisca" + PARAMETERS_PROJECT="openfisca-tunisia-pension" + PARAMETERS_PROJECT_DIR="openfisca_tunisia_pension/parameters" + + SHOW_LAST_BREADCRUMB_ITEM = false + + TABLE_OF_CONTENTS_DIR="../../../openfisca_tunisia_pension/tables/" + + TITLE="OpenFisca-Tunisia-Pension - الجباية المفتوحة تونس" + + # Path of file containing units used by French legislation parameters + UNITS_FILE_PATH="../../../openfisca_tunisia_pension/units.yaml" + EOF + working-directory: legislation-parameters-explorer/packages/viewer + - name: Initialize .svelte-kit directory of viewer + run: npx svelte-kit sync + working-directory: legislation-parameters-explorer/packages/viewer + - name: Generate data of viewer + run: npx tsx src/scripts/generate_data.ts + working-directory: legislation-parameters-explorer/packages/viewer + - name: Build viewer + run: npm run build + working-directory: legislation-parameters-explorer/packages/viewer + - name: Configure ssh for deployment to server + uses: tanmancan/action-setup-ssh-agent-key@1.0.0 + with: + ssh-auth-sock: /tmp/my_auth.sock + ssh-private-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_PRIVATE_KEY }} + ssh-public-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_KNOWN_HOSTS }} + - name: Deploy to Server using rsync + run: rsync -az --delete -e "ssh -J ssh-proxy@parameters.tn.tax-benefit.org:2222" build/ parameters.tn.tax-benefit.org@10.131.0.2:public_html/ + working-directory: legislation-parameters-explorer/packages/viewer + + deploy_simulator: + uses: tax-benefit/actions/.github/workflows/deploy.yml@v2.1.0 + with: + python_package: "openfisca_tunisia_pension" + secrets: + token: ${{ secrets.CONTROL_CENTER_TOKEN }} diff --git a/.github/workflows/validate_yaml.yml b/.github/workflows/validate_yaml.yml new file mode 100644 index 0000000..c01770a --- /dev/null +++ b/.github/workflows/validate_yaml.yml @@ -0,0 +1,15 @@ +name: Validate YAML + +on: + push: + workflow_dispatch: + pull_request: + types: [opened, reopened] + +jobs: + validate_yaml: + uses: tax-benefit/actions/.github/workflows/validate_yaml.yml@v1 + with: + parameters_path: "openfisca_tunisia_pension/parameters" + secrets: + token: ${{ secrets.CONTROL_CENTER_TOKEN }} From 85e76e69228aa4fb65cf38983e9f330856173601 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 16:44:50 +0100 Subject: [PATCH 14/24] Add units --- openfisca_tunisia_pension/units.yaml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/openfisca_tunisia_pension/units.yaml b/openfisca_tunisia_pension/units.yaml index a1d97ed..314c02f 100644 --- a/openfisca_tunisia_pension/units.yaml +++ b/openfisca_tunisia_pension/units.yaml @@ -1,6 +1,34 @@ +- name: /1 + label: + one: pourcent + other: pourcents + ratio: true + short_label: "%" +- name: currency + label: + one: Dinar + other: Dinars + short_label: DT +- name: day + label: + one: jour + other: jours +- name: month + label: mois +- name: year + label: + one: année + other: années + short_label: + one: an + other: ans - name: smig label: one: Smig other: Smigs # parameter: marche_travail.salaire_minimum.smig. ratio: true +- name: trimestre + label: + one: trimestre + other: trimestres From b8bb98dad7f3ac2f687f1051a7b6bd97908a82e8 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Mon, 18 Nov 2024 16:58:56 +0100 Subject: [PATCH 15/24] Test taux_de_liquidatin RSNA et CNRPS --- .../retraite/rsna/bareme_annuite.yaml | 2 +- ..._pension.yaml => taux_de_liquidation.yaml} | 14 ++--- tests/formulas/rsna/taux_de_liquidation.yaml | 55 +++++++++++++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) rename tests/formulas/cnrps/{cnrps_pension.yaml => taux_de_liquidation.yaml} (81%) create mode 100644 tests/formulas/rsna/taux_de_liquidation.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml index 2499bd5..8c3d208 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml @@ -14,7 +14,7 @@ brackets: value: 0.005 - threshold: 1960-01-01: - value: 160 + value: 120 rate: 1960-01-01: value: 0 diff --git a/tests/formulas/cnrps/cnrps_pension.yaml b/tests/formulas/cnrps/taux_de_liquidation.yaml similarity index 81% rename from tests/formulas/cnrps/cnrps_pension.yaml rename to tests/formulas/cnrps/taux_de_liquidation.yaml index dd6e584..3645a8c 100644 --- a/tests/formulas/cnrps/cnrps_pension.yaml +++ b/tests/formulas/cnrps/taux_de_liquidation.yaml @@ -1,6 +1,6 @@ - name: "5 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 5 * 4 output: @@ -8,7 +8,7 @@ - name: "10 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 10 * 4 output: @@ -16,7 +16,7 @@ - name: "13 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 13 * 4 output: @@ -24,7 +24,7 @@ - name: "21 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 21 * 4 output: @@ -32,7 +32,7 @@ - name: "31 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 31 * 4 output: @@ -40,7 +40,7 @@ - name: "40 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 40 * 4 output: @@ -48,7 +48,7 @@ - name: "50 ans de trimetres CNRPS" period: 2011 - absolute_error_margin: 0.5 + absolute_error_margin: 1e-10 input: cnrps_duree_assurance: 50 * 4 output: diff --git a/tests/formulas/rsna/taux_de_liquidation.yaml b/tests/formulas/rsna/taux_de_liquidation.yaml new file mode 100644 index 0000000..ac772c4 --- /dev/null +++ b/tests/formulas/rsna/taux_de_liquidation.yaml @@ -0,0 +1,55 @@ +- name: "5 ans de trimetres CNSS" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 5 * 4 + output: + rsna_taux_de_liquidation: .2 + +- name: "10 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 10 * 4 + output: + rsna_taux_de_liquidation: .4 + +- name: "13 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 13 * 4 + output: + rsna_taux_de_liquidation: .4 + .06 + +- name: "21 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 21 * 4 + output: + rsna_taux_de_liquidation: .4 + .22 + +- name: "31 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 31 * 4 + output: + rsna_taux_de_liquidation: .8 + +- name: "40 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 40 * 4 + output: + rsna_taux_de_liquidation: .8 + +- name: "50 ans de trimetres CNSS RSNA" + period: 2011 + absolute_error_margin: 1e-10 + input: + rsna_duree_assurance: 50 * 4 + output: + rsna_taux_de_liquidation: .8 From ba13806f2d39a21c6e4c98f0e0286a48be738836 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Tue, 19 Nov 2024 11:49:53 +0100 Subject: [PATCH 16/24] =?UTF-8?q?Add=20bar=C3=A8me=201985=20for=20CNRPS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../retraite/cnrps/bareme_annuite.yaml | 8 ++++ .../retraite/rsna/bareme_annuite.yaml | 5 ++- openfisca_tunisia_pension/regimes/cnrps.py | 24 ++++++++++++ openfisca_tunisia_pension/regimes/regime.py | 37 +++++++++++++++++++ openfisca_tunisia_pension/regimes/rsna.py | 30 ++++++++++++++- openfisca_tunisia_pension/variables/cnrps.py | 24 +++++++++++- .../variables/helpers.py | 1 + openfisca_tunisia_pension/variables/rsa.py | 24 +++++++++++- openfisca_tunisia_pension/variables/rsna.py | 34 ++++++++++++++++- tests/formulas/cnrps/taux_de_liquidation.yaml | 34 +++++++++++++++++ 10 files changed, 215 insertions(+), 6 deletions(-) diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml index 32863ed..2c529c8 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml @@ -8,15 +8,23 @@ brackets: value: 0.005 - threshold: 1959-02-01: + value: null + 1985-01-01: value: 40 rate: 1959-02-01: + value: null + 1985-01-01: value: 0.0075 - threshold: 1959-02-01: + value: null + 1985-01-01: value: 80 rate: 1959-02-01: + value: null + 1985-01-01: value: 0.005 - threshold: 1959-02-01: diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml index 8c3d208..ff5af33 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/bareme_annuite.yaml @@ -1,4 +1,4 @@ -description: Taux d'annuité par trimestre validé +description: Taux d'annuité par trimestre validé du régime des salariés non agricoles (RSNA) de la CNSS brackets: - threshold: 1960-01-01: @@ -21,3 +21,6 @@ brackets: metadata: threshold_unit: trimestre rate_unit: /1 + reference: + 1960-01-01: + title: Loi n°60-33 du 14 Décembre 1960 instituant un régime d'invalidité de vieillesse et de survie et un régime d'allocation de vieillesse et de survie dans le secteur non agricole. diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index de10c09..eb80250 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -19,6 +19,29 @@ from openfisca_tunisia_pension.tools import make_mean_over_largest +# Avant 1985 + +# La pension d’ancienneté pour cette modalité le droit est acquis lorsque la double condition +# - de 60 ans d’âge +# - et 30ans de services effectifs civils ou militaires est remplie. +# Sont dispensés de la condition d’âge les agents : +# - admis à la retraite d’office ; +# - révoqués sans suspension des droits à la pension ; +# - licenciés pour suppression d’emplois; +# - admis à la retraite pour incapacité physique ; +# - admis à la retraite pour insuffisance professionnelle. + +# La pension proportionnelle, dont le droit est acquis : +# - Sans conditions d’âge ni de durée de services aux agents mis à la retraite pour incapacité physique imputable et non imputable aux services ; +# - Sans conditions de durée de services : +# - aux agents mis à la retraite pour limite d’âge ; +# - licenciés pour suppression d’emploi et ayant plus de 15ans de services ; +# - aux femmes mères de 3 enfants âgés de moins de 16 ans ; +# - Sans conditions d’âge +# - aux agents licenciés pour insuffisance professionnelle ; +# - Sur demande ou d’office aux agents de plus de 50 ans et plus de 20 ans de services. + + class RegimeCNRPS(AbstractRegimeEnAnnuites): name = 'Régime des salariés non agricoles' variable_prefix = 'cnrps' @@ -30,6 +53,7 @@ class salaire_reference(Variable): label = 'Salaires de référence du régime de la CNRPS' definition_period = YEAR + # TODO: Il semblerait que c'était les 6 deniers mois en 2011 voir manuel CNRPS def formula(individu, period): '''3 dernières rémunérations ou les 2 plus élevées sur demande.''' n = 40 diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py index 0fdb049..cefabeb 100644 --- a/openfisca_tunisia_pension/regimes/regime.py +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -162,6 +162,25 @@ def formula(individu, period): majoration_pension_au_31_decembre = individu('regime_name_majoration_pension_au_31_decembre', period) return pension_brute_au_31_decembre + majoration_pension_au_31_decembre + class pension_brute(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension brute' + + def formula(individu, period, parameters): + taux_de_liquidation = individu('regime_name_taux_de_liquidation', period) + salaire_de_reference = individu('regime_name_salaire_de_reference', period) + pension_minimale = individu('regime_name_pension_minimale', period) + pension_maximale = individu('regime_name_pension_maximale', period) + return min_( + pension_maximale, + max_( + taux_de_liquidation * salaire_de_reference, + pension_minimale + ) + ) + class pension_brute_au_31_decembre(Variable): value_type = float entity = Individu @@ -185,6 +204,24 @@ def formula(individu, period, parameters): period, ) + class pension_maximale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + + class pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError + class pension_servie(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 3221e56..6d5df7c 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -26,6 +26,16 @@ class RegimeRSNA(AbstractRegimeEnAnnuites): variable_prefix = 'rsna' parameters_prefix = 'rsna' + class RSNATypesRaisonDepartAnticipe(Enum): + __order__ = 'non_concerne licenciement_economique usure_prematuree_organisme mere_3_enfants convenance_personnelle' + non_concerne = 'Non concerné' + # A partir de 50 ans : + licenciement_economique = 'Licenciement économique avec au minimum 60 mois de cotisations (20 trimestres)' + usure_prematuree_organisme = "Usure prématurée de l'organisme médicalement constatée avec au minimum 60 mois de cotisations (20 trimestres)" + mere_3_enfants = "Femme salariée, mère de 3 enfants en vie, justifiant d'au moins 180 mois de cotisations (60 trimestres)" + # A partir de 55 ans : + convenance_personnelle = 'Convenance personnelle, avec 360 mois de cotisations (120 trimestres)' + class salaire_reference(Variable): value_type = float entity = Individu @@ -62,7 +72,6 @@ def formula(individu, period, parameters): rsna = parameters(period).retraite.regime_name taux_annuite_base = rsna.taux_annuite_base taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - duree_stage = rsna.stage_derog age_eligible = rsna.age_dep_anticip periode_remplacement_base = rsna.periode_remplacement_base plaf_taux_pension = rsna.plaf_taux_pension @@ -71,6 +80,7 @@ def formula(individu, period, parameters): pension_min_sup = rsna.pension_minimale.sup pension_min_inf = rsna.pension_minimale.inf + duree_stage = rsna.stage_derog stage = duree_assurance > 4 * duree_stage pension_minimale = ( stage * pension_min_sup + not_(stage) * pension_min_inf @@ -91,3 +101,21 @@ def formula(individu, period, parameters): # plafonnement montant_pension_percu = max_(montant, pension_minimale * smig) return eligibilite * montant_pension_percu + + class pension_maximale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + + class pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index 218c716..9c108c3 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -120,7 +120,11 @@ class cnrps_pension_brute(Variable): label = 'Pension brute' def formula(individu, period, parameters): - NotImplementedError + taux_de_liquidation = individu('cnrps_taux_de_liquidation', period) + salaire_de_reference = individu('cnrps_salaire_de_reference', period) + pension_minimale = individu('cnrps_pension_minimale', period) + pension_maximale = individu('cnrps_pension_maximale', period) + return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) class cnrps_pension_brute_au_31_decembre(Variable): value_type = float @@ -138,6 +142,24 @@ def formula(individu, period, parameters): pension_brute = individu('cnrps_pension_brute', period) return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) +class cnrps_pension_maximale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + +class cnrps_pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError + class cnrps_pension_servie(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index 5571e76..f007e72 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -5,6 +5,7 @@ +def pension_from_bareme_annuite(bareme_annuite_en_trimestres) def pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index eb0d422..d5f8078 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -118,7 +118,11 @@ class rsa_pension_brute(Variable): label = 'Pension brute' def formula(individu, period, parameters): - NotImplementedError + taux_de_liquidation = individu('rsa_taux_de_liquidation', period) + salaire_de_reference = individu('rsa_salaire_de_reference', period) + pension_minimale = individu('rsa_pension_minimale', period) + pension_maximale = individu('rsa_pension_maximale', period) + return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) class rsa_pension_brute_au_31_decembre(Variable): value_type = float @@ -136,6 +140,24 @@ def formula(individu, period, parameters): pension_brute = individu('rsa_pension_brute', period) return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) +class rsa_pension_maximale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + +class rsa_pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError + class rsa_pension_servie(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index 52d610b..b1e8f80 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -9,6 +9,14 @@ from openfisca_tunisia_pension.tools import make_mean_over_largest from openfisca_tunisia_pension.variables.helpers import pension_generique +class rsna_RSNATypesRaisonDepartAnticipe(Enum): + __order__ = 'non_concerne licenciement_economique usure_prematuree_organisme mere_3_enfants convenance_personnelle' + non_concerne = 'Non concerné' + licenciement_economique = 'Licenciement économique avec au minimum 60 mois de cotisations (20 trimestres)' + usure_prematuree_organisme = "Usure prématurée de l'organisme médicalement constatée avec au minimum 60 mois de cotisations (20 trimestres)" + mere_3_enfants = "Femme salariée, mère de 3 enfants en vie, justifiant d'au moins 180 mois de cotisations (60 trimestres)" + convenance_personnelle = 'Convenance personnelle, avec 360 mois de cotisations (120 trimestres)' + class rsna_cotisation(Variable): value_type = float entity = Individu @@ -87,13 +95,13 @@ def formula(individu, period, parameters): rsna = parameters(period).retraite.rsna taux_annuite_base = rsna.taux_annuite_base taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - duree_stage = rsna.stage_derog age_eligible = rsna.age_dep_anticip periode_remplacement_base = rsna.periode_remplacement_base plaf_taux_pension = rsna.plaf_taux_pension smig = parameters(period).marche_travail.smig_48h pension_min_sup = rsna.pension_minimale.sup pension_min_inf = rsna.pension_minimale.inf + duree_stage = rsna.stage_derog stage = duree_assurance > 4 * duree_stage pension_minimale = stage * pension_min_sup + not_(stage) * pension_min_inf montant = pension_generique(duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension) @@ -120,7 +128,11 @@ class rsna_pension_brute(Variable): label = 'Pension brute' def formula(individu, period, parameters): - NotImplementedError + taux_de_liquidation = individu('rsna_taux_de_liquidation', period) + salaire_de_reference = individu('rsna_salaire_de_reference', period) + pension_minimale = individu('rsna_pension_minimale', period) + pension_maximale = individu('rsna_pension_maximale', period) + return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) class rsna_pension_brute_au_31_decembre(Variable): value_type = float @@ -138,6 +150,24 @@ def formula(individu, period, parameters): pension_brute = individu('rsna_pension_brute', period) return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) +class rsna_pension_maximale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + +class rsna_pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError + class rsna_pension_servie(Variable): value_type = float entity = Individu diff --git a/tests/formulas/cnrps/taux_de_liquidation.yaml b/tests/formulas/cnrps/taux_de_liquidation.yaml index 3645a8c..4a10902 100644 --- a/tests/formulas/cnrps/taux_de_liquidation.yaml +++ b/tests/formulas/cnrps/taux_de_liquidation.yaml @@ -53,3 +53,37 @@ cnrps_duree_assurance: 50 * 4 output: cnrps_taux_de_liquidation: .9 + +# Avant 1985 + +- name: "21 ans de trimetres CNRPS" + period: 1980 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 21 * 4 + output: + cnrps_taux_de_liquidation: .42 + +- name: "31 ans de trimetres CNRPS" + period: 1980 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 31 * 4 + output: + cnrps_taux_de_liquidation: .62 + +- name: "40 ans de trimetres CNRPS" + period: 1980 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 40 * 4 + output: + cnrps_taux_de_liquidation: .8 + +- name: "45 ans de trimetres CNRPS" + period: 1980 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 45 * 4 + output: + cnrps_taux_de_liquidation: .8 From c319ab3f932e49fcbacdc875218f3d51b7ea6e05 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Tue, 19 Nov 2024 11:55:50 +0100 Subject: [PATCH 17/24] Only validate parameter. Stop deployment. --- .github/workflows/tax-benefit.yml | 136 +++++++++++++++--------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/.github/workflows/tax-benefit.yml b/.github/workflows/tax-benefit.yml index 30ae73c..6181748 100644 --- a/.github/workflows/tax-benefit.yml +++ b/.github/workflows/tax-benefit.yml @@ -12,82 +12,82 @@ jobs: secrets: token: ${{ secrets.CONTROL_CENTER_TOKEN }} - deploy_parameters: - runs-on: ubuntu-latest + # deploy_parameters: + # runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Clone Legislation Parameters Explorer - run: git clone https://git.leximpact.dev/leximpact/legislation-parameters-explorer.git - - name: Install Node.js version LTS - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - - name: Install viewer dependencies - run: npm install - working-directory: legislation-parameters-explorer/packages/viewer - - name: Configure viewer - run: | - rm -f .env - cat > .env << EOF - # Customizations to apply to the site (theme, URLs…) - CUSTOMIZATION="openfisca" + # steps: + # - uses: actions/checkout@v4 + # - name: Clone Legislation Parameters Explorer + # run: git clone https://git.leximpact.dev/leximpact/legislation-parameters-explorer.git + # - name: Install Node.js version LTS + # uses: actions/setup-node@v4 + # with: + # node-version: 'lts/*' + # - name: Install viewer dependencies + # run: npm install + # working-directory: legislation-parameters-explorer/packages/viewer + # - name: Configure viewer + # run: | + # rm -f .env + # cat > .env << EOF + # # Customizations to apply to the site (theme, URLs…) + # CUSTOMIZATION="openfisca" - DBNOMICS_DATASET_CODE="openfisca_tunisia_pension" - DBNOMICS_PROVIDER_CODE="OpenFisca" - DBNOMICS_URL="https://db.nomics.world/" + # DBNOMICS_DATASET_CODE="openfisca_tunisia_pension" + # DBNOMICS_PROVIDER_CODE="OpenFisca" + # DBNOMICS_URL="https://db.nomics.world/" - EDITOR_URL="https://editor.parameters.tn.tax-benefit.org/" + # EDITOR_URL="https://editor.parameters.tn.tax-benefit.org/" - EXPORT_CSV=true - EXPORT_JSON=false - EXPORT_XLSX=true + # EXPORT_CSV=true + # EXPORT_JSON=false + # EXPORT_XLSX=true - # Path of directory containing legislation parameters of country - PARAMETERS_DIR="../../../openfisca_tunisia_pension/parameters/" + # # Path of directory containing legislation parameters of country + # PARAMETERS_DIR="../../../openfisca_tunisia_pension/parameters/" - # Description of parameters remote repository - PARAMETERS_AUTHOR_EMAIL="editor.parameters.tn@tax-benefit.org" - PARAMETERS_AUTHOR_NAME="Éditeur des paramètres d'OpenFisca-Tunisia-Pension" - PARAMETERS_BRANCH="main" - PARAMETERS_FORGE_DOMAIN_NAME="github.com" - PARAMETERS_FORGE_TYPE="GitHub" - PARAMETERS_GROUP="openfisca" - PARAMETERS_PROJECT="openfisca-tunisia-pension" - PARAMETERS_PROJECT_DIR="openfisca_tunisia_pension/parameters" + # # Description of parameters remote repository + # PARAMETERS_AUTHOR_EMAIL="editor.parameters.tn@tax-benefit.org" + # PARAMETERS_AUTHOR_NAME="Éditeur des paramètres d'OpenFisca-Tunisia-Pension" + # PARAMETERS_BRANCH="main" + # PARAMETERS_FORGE_DOMAIN_NAME="github.com" + # PARAMETERS_FORGE_TYPE="GitHub" + # PARAMETERS_GROUP="openfisca" + # PARAMETERS_PROJECT="openfisca-tunisia-pension" + # PARAMETERS_PROJECT_DIR="openfisca_tunisia_pension/parameters" - SHOW_LAST_BREADCRUMB_ITEM = false + # SHOW_LAST_BREADCRUMB_ITEM = false - TABLE_OF_CONTENTS_DIR="../../../openfisca_tunisia_pension/tables/" + # TABLE_OF_CONTENTS_DIR="../../../openfisca_tunisia_pension/tables/" - TITLE="OpenFisca-Tunisia-Pension - الجباية المفتوحة تونس" + # TITLE="OpenFisca-Tunisia-Pension - الجباية المفتوحة تونس" - # Path of file containing units used by French legislation parameters - UNITS_FILE_PATH="../../../openfisca_tunisia_pension/units.yaml" - EOF - working-directory: legislation-parameters-explorer/packages/viewer - - name: Initialize .svelte-kit directory of viewer - run: npx svelte-kit sync - working-directory: legislation-parameters-explorer/packages/viewer - - name: Generate data of viewer - run: npx tsx src/scripts/generate_data.ts - working-directory: legislation-parameters-explorer/packages/viewer - - name: Build viewer - run: npm run build - working-directory: legislation-parameters-explorer/packages/viewer - - name: Configure ssh for deployment to server - uses: tanmancan/action-setup-ssh-agent-key@1.0.0 - with: - ssh-auth-sock: /tmp/my_auth.sock - ssh-private-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_PRIVATE_KEY }} - ssh-public-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_KNOWN_HOSTS }} - - name: Deploy to Server using rsync - run: rsync -az --delete -e "ssh -J ssh-proxy@parameters.tn.tax-benefit.org:2222" build/ parameters.tn.tax-benefit.org@10.131.0.2:public_html/ - working-directory: legislation-parameters-explorer/packages/viewer + # # Path of file containing units used by French legislation parameters + # UNITS_FILE_PATH="../../../openfisca_tunisia_pension/units.yaml" + # EOF + # working-directory: legislation-parameters-explorer/packages/viewer + # - name: Initialize .svelte-kit directory of viewer + # run: npx svelte-kit sync + # working-directory: legislation-parameters-explorer/packages/viewer + # - name: Generate data of viewer + # run: npx tsx src/scripts/generate_data.ts + # working-directory: legislation-parameters-explorer/packages/viewer + # - name: Build viewer + # run: npm run build + # working-directory: legislation-parameters-explorer/packages/viewer + # - name: Configure ssh for deployment to server + # uses: tanmancan/action-setup-ssh-agent-key@1.0.0 + # with: + # ssh-auth-sock: /tmp/my_auth.sock + # ssh-private-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_PRIVATE_KEY }} + # ssh-public-key: ${{ secrets.PARAMETERS_EXPLORER_SSH_KNOWN_HOSTS }} + # - name: Deploy to Server using rsync + # run: rsync -az --delete -e "ssh -J ssh-proxy@parameters.tn.tax-benefit.org:2222" build/ parameters.tn.tax-benefit.org@10.131.0.2:public_html/ + # working-directory: legislation-parameters-explorer/packages/viewer - deploy_simulator: - uses: tax-benefit/actions/.github/workflows/deploy.yml@v2.1.0 - with: - python_package: "openfisca_tunisia_pension" - secrets: - token: ${{ secrets.CONTROL_CENTER_TOKEN }} + # deploy_simulator: + # uses: tax-benefit/actions/.github/workflows/deploy.yml@v2.1.0 + # with: + # python_package: "openfisca_tunisia_pension" + # secrets: + # token: ${{ secrets.CONTROL_CENTER_TOKEN }} From fd188458060cecca227454adb33b8a3e66b7cba6 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Wed, 20 Nov 2024 09:26:34 +0100 Subject: [PATCH 18/24] More parameters --- .../cnrps/age_legal/civil/cadre_commun.yaml | 6 ++++++ .../cnrps/age_legal/civil/cadres_actifs.yaml | 14 ++++++++++++++ .../age_legal/civil/enseignants_du_superieur.yaml | 10 ++++++++++ openfisca_tunisia_pension/regimes/cnrps.py | 14 ++++++++++++++ openfisca_tunisia_pension/variables/helpers.py | 4 ---- 5 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadre_commun.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadres_actifs.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadre_commun.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadre_commun.yaml new file mode 100644 index 0000000..528d57e --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadre_commun.yaml @@ -0,0 +1,6 @@ +description: Age légal de de départ à la retraite pour le cadre commun de la CNRPS +values: + 1959-02-01: + value: 60 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadres_actifs.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadres_actifs.yaml new file mode 100644 index 0000000..4ff4600 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/cadres_actifs.yaml @@ -0,0 +1,14 @@ +description: Age légal de de départ à la retraite pour certains cadres actifs et ouvriers +values: + 1959-02-01: + value: 55 +metadata: + unit: year +documentation: |- + Il s'agit + - des ouvriers exerçant dans le cadre commun des taches pénibles et insalubres soumis aux conditions prévues par le décret décret n° 1177 du 24 septembre 1985 + - les cadres actifs des forces de sécurité intérieure et de la garde nationale + - les cadres actifs exerçant dans : + - les sociétés de transport + - la Société nationale des chemins de fer tunisiens (SNCFT) + - la Société tunisienne de l’électricité et du gaz (STEG) diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml new file mode 100644 index 0000000..473d396 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml @@ -0,0 +1,10 @@ +description: Age légal de de départ à la retraite pour certains enseignants du supérieur +values: + 1959-02-01: + value: 60 +metadata: + unit: year +documentation: |- + Les enseignants concernés sont: + - les professeurs de l’enseignement supérieur et les maîtres de conférences de l’enseignement supérieur aux établissements universitaires et aux établissements de recherche scientifique civils et militaires, + - les professeurs hospitalo-universitaires et les maîtres de conférences agrégés hospitalo-universitaires diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index eb80250..79413b7 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -42,6 +42,20 @@ # - Sur demande ou d’office aux agents de plus de 50 ans et plus de 20 ans de services. +# Après 1985 + +# Le départ à la retraite est prononcé : +# Lors de l'atteinte de l'âge légal de mise à retraite ; +# Avant l'atteinte de cet âge: +# a/ en cas d'invalidité physique ; +# b/ sur demande ; +# c/ en cas de démission ; +# d/ à l'initiative de l'employeur pour insuffisance professionnelle de l'agent ; +# e/ en cas de révocation ; +# f/ sur demande pour les mères de trois enfants; +# g/ d’office. + + class RegimeCNRPS(AbstractRegimeEnAnnuites): name = 'Régime des salariés non agricoles' variable_prefix = 'cnrps' diff --git a/openfisca_tunisia_pension/variables/helpers.py b/openfisca_tunisia_pension/variables/helpers.py index f007e72..e2a8f01 100644 --- a/openfisca_tunisia_pension/variables/helpers.py +++ b/openfisca_tunisia_pension/variables/helpers.py @@ -4,10 +4,6 @@ from numpy import minimum as min_ - -def pension_from_bareme_annuite(bareme_annuite_en_trimestres) - - def pension_generique(duree_assurance, sal_ref, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_elig, periode_remplacement_base, plaf_taux_pension): From 02b9d9af75eb40a32e72105d3ec7d4763256ee9c Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Wed, 20 Nov 2024 11:59:37 +0100 Subject: [PATCH 19/24] Fix bareme_annuite --- .../parameters/retraite/cnrps/bareme_annuite.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml index 2c529c8..363c3b3 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/bareme_annuite.yaml @@ -8,29 +8,25 @@ brackets: value: 0.005 - threshold: 1959-02-01: - value: null + value: 160 1985-01-01: value: 40 rate: 1959-02-01: - value: null + value: 0 1985-01-01: value: 0.0075 - threshold: - 1959-02-01: - value: null 1985-01-01: value: 80 rate: - 1959-02-01: - value: null 1985-01-01: value: 0.005 - threshold: - 1959-02-01: + 1985-01-01: value: 160 rate: - 1959-02-01: + 1985-01-01: value: 0 metadata: threshold_unit: trimestre From 674fae02a44e776a3c14a4597519d40172d7799c Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Wed, 20 Nov 2024 17:17:38 +0100 Subject: [PATCH 20/24] More tests --- openfisca_tunisia_pension/regimes/cnrps.py | 19 +++- openfisca_tunisia_pension/regimes/regime.py | 107 ++++++------------ openfisca_tunisia_pension/tools.py | 28 +++++ openfisca_tunisia_pension/variables/cnrps.py | 70 ++---------- openfisca_tunisia_pension/variables/rsa.py | 50 +------- openfisca_tunisia_pension/variables/rsna.py | 32 +----- .../cnrps/cnrps_salaire_de_reference.yaml | 101 +++++++++++++++++ .../cnrps/cnrps_salaire_reference.yaml | 100 ---------------- tests/formulas/cnrps/pension.noyaml | 0 tests/test_tools.py | 18 +++ 10 files changed, 210 insertions(+), 315 deletions(-) create mode 100644 tests/formulas/cnrps/cnrps_salaire_de_reference.yaml delete mode 100644 tests/formulas/cnrps/cnrps_salaire_reference.yaml create mode 100644 tests/formulas/cnrps/pension.noyaml create mode 100644 tests/test_tools.py diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index 79413b7..ffb7cef 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -16,7 +16,7 @@ ) from openfisca_tunisia_pension.variables.helpers import pension_generique -from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.tools import make_mean_over_consecutive_largest # Avant 1985 @@ -61,7 +61,13 @@ class RegimeCNRPS(AbstractRegimeEnAnnuites): variable_prefix = 'cnrps' parameters_prefix = 'cnrps' - class salaire_reference(Variable): + class salaire_de_reference_calcule_sur_demande(Variable): + value_type = bool + entity = Individu + label = "Le salaire de référence du régime de la CNRPS est calculé à la demande de l'agent sur ses meilleures années" + definition_period = ETERNITY + + class salaire_de_reference(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime de la CNRPS' @@ -72,7 +78,7 @@ def formula(individu, period): '''3 dernières rémunérations ou les 2 plus élevées sur demande.''' n = 40 k = 2 - mean_over_largest = make_mean_over_largest(k) + mean_over_largest = make_mean_over_consecutive_largest(k) moyenne_2_salaires_plus_eleves = apply_along_axis( mean_over_largest, axis = 0, @@ -84,9 +90,10 @@ def formula(individu, period): for year in range(period.start.year, period.start.year - p, -1) ) / p - salaire_refererence = max_( + salaire_refererence = where( + individu('regime_name_salaire_de_reference_calcule_sur_demande', period), + moyenne_2_salaires_plus_eleves, moyenne_3_derniers_salaires, - moyenne_2_salaires_plus_eleves ) return salaire_refererence @@ -98,7 +105,7 @@ class pension(Variable): def formula(individu, period, parameters): duree_assurance = individu('regime_name_duree_assurance', period = period) - salaire_reference = individu('regime_name_salaire_reference', period = period) + salaire_reference = individu('regime_name_salaire_de_reference', period = period) age = individu('age', period = period) cnrps = parameters(period).retraite.regime_name diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py index cefabeb..8649ad5 100644 --- a/openfisca_tunisia_pension/regimes/regime.py +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -2,7 +2,7 @@ from openfisca_core.model_api import * -# from openfisca_core.errors.variable_not_found_error import VariableNotFoundError +from openfisca_core.errors.variable_not_found_error import VariableNotFoundError # Import the Entities specifically defined for this tax and benefit system from openfisca_tunisia_pension.entities import Individu @@ -148,79 +148,55 @@ class pension(Variable): def formula(individu, period): pension_brute = individu('regime_name_pension_brute', period) - majoration_pension = individu('regime_name_majoration_pension', period) - return pension_brute + majoration_pension - - class pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension' - - def formula(individu, period): - pension_brute_au_31_decembre = individu('regime_name_pension_brute_au_31_decembre', period) - majoration_pension_au_31_decembre = individu('regime_name_majoration_pension_au_31_decembre', period) - return pension_brute_au_31_decembre + majoration_pension_au_31_decembre - - class pension_brute(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension brute' - - def formula(individu, period, parameters): - taux_de_liquidation = individu('regime_name_taux_de_liquidation', period) - salaire_de_reference = individu('regime_name_salaire_de_reference', period) - pension_minimale = individu('regime_name_pension_minimale', period) - pension_maximale = individu('regime_name_pension_maximale', period) + try: + pension_minimale = individu('regime_name_pension_minimale', period) + except VariableNotFoundError: + pension_minimale = 0 + try: + pension_maximale = individu('regime_name_pension_maximale', period) + except VariableNotFoundError: + return max_( + pension_brute, + pension_minimale + ) return min_( pension_maximale, max_( - taux_de_liquidation * salaire_de_reference, + pension_brute, pension_minimale ) ) - class pension_brute_au_31_decembre(Variable): + class pension_brute(Variable): value_type = float entity = Individu definition_period = YEAR - label = 'Pension brute au 31 décembre' + label = 'Pension brute' def formula(individu, period, parameters): - annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - # Raccouci pour arrêter les calculs dans le passé quand toutes les liquidations ont lieu dans le futur - if all(period.start.year < annee_de_liquidation): - return individu.empty_array() - last_year = period.last_year - pension_brute_au_31_decembre_annee_precedente = individu('regime_name_pension_brute_au_31_decembre', last_year) - revalorisation = parameters(period).regime_name.revalorisation_pension_au_31_decembre - pension_brute = individu('regime_name_pension_brute', period) - return revalorise( - pension_brute_au_31_decembre_annee_precedente, - pension_brute, - annee_de_liquidation, - revalorisation, - period, - ) + taux_de_liquidation = individu('regime_name_taux_de_liquidation', period) + salaire_de_reference = individu('regime_name_salaire_de_reference', period) + return taux_de_liquidation * salaire_de_reference, - class pension_maximale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension maximale' + # class pension_maximale(Variable): + # value_type = float + # default_value = np.inf # Pas de pension maximale par défaut + # entity = Individu + # definition_period = YEAR + # label = 'Pension maximale' - def formula(individu, period, parameters): - NotImplementedError + # def formula(individu, period, parameters): + # NotImplementedError - class pension_minimale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension minimale' + # class pension_minimale(Variable): + # value_type = float + # default_value = 0 # Pas de pension minimale par défaut, elle est à zéro + # entity = Individu + # definition_period = YEAR + # label = 'Pension minimale' - def formula(individu, period, parameters): - NotImplementedError + # def formula(individu, period, parameters): + # NotImplementedError class pension_servie(Variable): value_type = float @@ -269,18 +245,3 @@ def formula(individu, period, parameters): duree_assurance = individu('regime_name_duree_assurance', period) taux_annuite = bareme_annuite.calc(duree_assurance) return taux_annuite - - -# def revalorise(variable_31_decembre_annee_precedente, variable_originale, annee_de_liquidation, revalorisation, period): -# return select( -# [ -# annee_de_liquidation > period.start.year, -# annee_de_liquidation == period.start.year, -# annee_de_liquidation < period.start.year, -# ], -# [ -# 0, -# variable_originale, -# variable_31_decembre_annee_precedente * revalorisation -# ] -# ) diff --git a/openfisca_tunisia_pension/tools.py b/openfisca_tunisia_pension/tools.py index 219c07d..a361a98 100644 --- a/openfisca_tunisia_pension/tools.py +++ b/openfisca_tunisia_pension/tools.py @@ -12,6 +12,13 @@ def mean_over_largest(vector): return mean_over_largest +def make_mean_over_consecutive_largest(k): + def mean_over_consecutive_largest(vector): + return mean_over_k_consecutive_largest(vector, k = int(k)) + + return mean_over_consecutive_largest + + @jit(float32(float32[:], int64), nopython=True) def mean_over_k_nonzero_largest(vector, k): '''Return the mean over the k largest values of a vector.''' @@ -24,3 +31,24 @@ def mean_over_k_nonzero_largest(vector, k): z = -np.partition(-vector, kth = k) upper_bound = min(k, nonzeros) return z[:upper_bound].sum() / upper_bound + + +@jit(float32(float32[:], int64), nopython=True) +def mean_over_k_consecutive_largest(vector, k): + '''Return the mean over the k largest consecutive values of a vector.''' + if k == 0: + return 0 + nonzeros = (vector > 0.0).sum() + if k >= nonzeros: + return vector.sum() / (nonzeros + (nonzeros == 0)) + + if k == 1: + return vector.max() + + n = len(vector) + mean = np.zeros(n + 1 - k, dtype = np.float32) + for p in range(n + 1 - k): + for i in range(k): + mean[p] += vector[p + i] + mean[p] = mean[p] / k + return mean.max() diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index 9c108c3..5d626ad 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -1,5 +1,6 @@ """Abstract regimes definition.""" from openfisca_core.model_api import * +from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu 'Régime de la Caisse nationale de retraite et de prévoyance sociale (CNRPS).' from openfisca_core.model_api import * @@ -7,7 +8,7 @@ from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack from openfisca_tunisia_pension.variables.helpers import pension_generique -from openfisca_tunisia_pension.tools import make_mean_over_largest +from openfisca_tunisia_pension.tools import make_mean_over_consecutive_largest class cnrps_cotisation(Variable): value_type = float @@ -82,7 +83,7 @@ class cnrps_pension(Variable): def formula(individu, period, parameters): duree_assurance = individu('cnrps_duree_assurance', period=period) - salaire_reference = individu('cnrps_salaire_reference', period=period) + salaire_reference = individu('cnrps_salaire_de_reference', period=period) age = individu('age', period=period) cnrps = parameters(period).retraite.cnrps taux_annuite_base = cnrps.taux_annuite_base @@ -102,17 +103,6 @@ def formula(individu, period, parameters): montant_pension_percu = max_(montant, pension_minimale * smig) return eligibilite * montant_pension_percu -class cnrps_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension' - - def formula(individu, period): - pension_brute_au_31_decembre = individu('cnrps_pension_brute_au_31_decembre', period) - majoration_pension_au_31_decembre = individu('cnrps_majoration_pension_au_31_decembre', period) - return pension_brute_au_31_decembre + majoration_pension_au_31_decembre - class cnrps_pension_brute(Variable): value_type = float entity = Individu @@ -122,43 +112,7 @@ class cnrps_pension_brute(Variable): def formula(individu, period, parameters): taux_de_liquidation = individu('cnrps_taux_de_liquidation', period) salaire_de_reference = individu('cnrps_salaire_de_reference', period) - pension_minimale = individu('cnrps_pension_minimale', period) - pension_maximale = individu('cnrps_pension_maximale', period) - return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) - -class cnrps_pension_brute_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension brute au 31 décembre' - - def formula(individu, period, parameters): - annee_de_liquidation = individu('cnrps_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(period.start.year < annee_de_liquidation): - return individu.empty_array() - last_year = period.last_year - pension_brute_au_31_decembre_annee_precedente = individu('cnrps_pension_brute_au_31_decembre', last_year) - revalorisation = parameters(period).cnrps.revalorisation_pension_au_31_decembre - pension_brute = individu('cnrps_pension_brute', period) - return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) - -class cnrps_pension_maximale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension maximale' - - def formula(individu, period, parameters): - NotImplementedError - -class cnrps_pension_minimale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension minimale' - - def formula(individu, period, parameters): - NotImplementedError + return (taux_de_liquidation * salaire_de_reference,) class cnrps_pension_servie(Variable): value_type = float @@ -184,12 +138,6 @@ class cnrps_salaire_de_base(Variable): set_input = set_input_divide_by_period class cnrps_salaire_de_reference(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = 'Salaire de référence' - -class cnrps_salaire_reference(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime de la CNRPS' @@ -199,13 +147,19 @@ def formula(individu, period): """3 dernières rémunérations ou les 2 plus élevées sur demande.""" n = 40 k = 2 - mean_over_largest = make_mean_over_largest(k) + mean_over_largest = make_mean_over_consecutive_largest(k) moyenne_2_salaires_plus_eleves = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) p = 3 moyenne_3_derniers_salaires = sum((individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - p, -1))) / p - salaire_refererence = max_(moyenne_3_derniers_salaires, moyenne_2_salaires_plus_eleves) + salaire_refererence = where(individu('cnrps_salaire_de_reference_calcule_sur_demande', period), moyenne_2_salaires_plus_eleves, moyenne_3_derniers_salaires) return salaire_refererence +class cnrps_salaire_de_reference_calcule_sur_demande(Variable): + value_type = bool + entity = Individu + label = "Le salaire de référence du régime de la CNRPS est calculé à la demande de l'agent sur ses meilleures années" + definition_period = ETERNITY + class cnrps_taux_de_liquidation(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index d5f8078..7033e70 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -1,5 +1,6 @@ """Abstract regimes definition.""" from openfisca_core.model_api import * +from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu 'Régime des salariés agricoles.' from openfisca_core.model_api import * @@ -100,17 +101,6 @@ def formula(individu, period, parameters): pension = elig * montant_percu return pension -class rsa_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension' - - def formula(individu, period): - pension_brute_au_31_decembre = individu('rsa_pension_brute_au_31_decembre', period) - majoration_pension_au_31_decembre = individu('rsa_majoration_pension_au_31_decembre', period) - return pension_brute_au_31_decembre + majoration_pension_au_31_decembre - class rsa_pension_brute(Variable): value_type = float entity = Individu @@ -120,43 +110,7 @@ class rsa_pension_brute(Variable): def formula(individu, period, parameters): taux_de_liquidation = individu('rsa_taux_de_liquidation', period) salaire_de_reference = individu('rsa_salaire_de_reference', period) - pension_minimale = individu('rsa_pension_minimale', period) - pension_maximale = individu('rsa_pension_maximale', period) - return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) - -class rsa_pension_brute_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension brute au 31 décembre' - - def formula(individu, period, parameters): - annee_de_liquidation = individu('rsa_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(period.start.year < annee_de_liquidation): - return individu.empty_array() - last_year = period.last_year - pension_brute_au_31_decembre_annee_precedente = individu('rsa_pension_brute_au_31_decembre', last_year) - revalorisation = parameters(period).rsa.revalorisation_pension_au_31_decembre - pension_brute = individu('rsa_pension_brute', period) - return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) - -class rsa_pension_maximale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension maximale' - - def formula(individu, period, parameters): - NotImplementedError - -class rsa_pension_minimale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension minimale' - - def formula(individu, period, parameters): - NotImplementedError + return (taux_de_liquidation * salaire_de_reference,) class rsa_pension_servie(Variable): value_type = float diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index b1e8f80..d17e12c 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -1,5 +1,6 @@ """Abstract regimes definition.""" from openfisca_core.model_api import * +from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu 'Régime des salariés non agricoles.' from openfisca_core.model_api import * @@ -110,17 +111,6 @@ def formula(individu, period, parameters): montant_pension_percu = max_(montant, pension_minimale * smig) return eligibilite * montant_pension_percu -class rsna_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension' - - def formula(individu, period): - pension_brute_au_31_decembre = individu('rsna_pension_brute_au_31_decembre', period) - majoration_pension_au_31_decembre = individu('rsna_majoration_pension_au_31_decembre', period) - return pension_brute_au_31_decembre + majoration_pension_au_31_decembre - class rsna_pension_brute(Variable): value_type = float entity = Individu @@ -130,25 +120,7 @@ class rsna_pension_brute(Variable): def formula(individu, period, parameters): taux_de_liquidation = individu('rsna_taux_de_liquidation', period) salaire_de_reference = individu('rsna_salaire_de_reference', period) - pension_minimale = individu('rsna_pension_minimale', period) - pension_maximale = individu('rsna_pension_maximale', period) - return min_(pension_maximale, max_(taux_de_liquidation * salaire_de_reference, pension_minimale)) - -class rsna_pension_brute_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension brute au 31 décembre' - - def formula(individu, period, parameters): - annee_de_liquidation = individu('rsna_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(period.start.year < annee_de_liquidation): - return individu.empty_array() - last_year = period.last_year - pension_brute_au_31_decembre_annee_precedente = individu('rsna_pension_brute_au_31_decembre', last_year) - revalorisation = parameters(period).rsna.revalorisation_pension_au_31_decembre - pension_brute = individu('rsna_pension_brute', period) - return revalorise(pension_brute_au_31_decembre_annee_precedente, pension_brute, annee_de_liquidation, revalorisation, period) + return (taux_de_liquidation * salaire_de_reference,) class rsna_pension_maximale(Variable): value_type = float diff --git a/tests/formulas/cnrps/cnrps_salaire_de_reference.yaml b/tests/formulas/cnrps/cnrps_salaire_de_reference.yaml new file mode 100644 index 0000000..39dc4c7 --- /dev/null +++ b/tests/formulas/cnrps/cnrps_salaire_de_reference.yaml @@ -0,0 +1,101 @@ +- name: "Individu salarié 12000 DT par an toute sa carrière sauf accélération en fin" + period: 2014 + absolute_error_margin: 0.5 + input: + age: 60 + cnrps_duree_assurance: 50 + cnrps_salaire_de_base: + 1975: 12000 + 1976: 12000 + 1977: 12000 + 1978: 12000 + 1979: 12000 + 1980: 12000 + 1981: 12000 + 1982: 12000 + 1983: 12000 + 1984: 12000 + 1985: 12000 + 1986: 12000 + 1987: 12000 + 1988: 12000 + 1989: 12000 + 1990: 12000 + 1991: 12000 + 1992: 12000 + 1993: 12000 + 1994: 12000 + 1995: 12000 + 1996: 12000 + 1997: 12000 + 1998: 12000 + 1999: 12000 + 2000: 12000 + 2001: 12000 + 2002: 12000 + 2003: 12000 + 2004: 12000 + 2005: 12000 + 2006: 12000 + 2007: 12000 + 2008: 12000 + 2009: 12000 + 2010: 12000 + 2011: 12000 + 2012: 12000 + 2013: 12500 + 2014: 13000 + output: + cnrps_salaire_de_reference: 12500 + + +- name: "Individu fonctionnaire 2 années à 20000 supérieure à tous le reste de sa carrière" + period: 2014 + absolute_error_margin: 0.5 + input: + age: 60 + cnrps_duree_assurance: 50 + cnrps_salaire_de_reference_calcule_sur_demande: true + cnrps_salaire_de_base: + 1975: 12000 + 1976: 12000 + 1977: 12000 + 1978: 12000 + 1979: 12000 + 1980: 12000 + 1981: 12000 + 1982: 12000 + 1983: 12000 + 1984: 12000 + 1985: 12000 + 1986: 12000 + 1987: 12000 + 1988: 12000 + 1989: 12000 + 1990: 12000 + 1991: 12000 + 1992: 12000 + 1993: 12000 + 1994: 12000 + 1995: 12000 + 1996: 12000 + 1997: 12000 + 1998: 12000 + 1999: 20000 + 2000: 20000 + 2001: 20000 + 2002: 12000 + 2003: 12000 + 2004: 12000 + 2005: 12000 + 2006: 12000 + 2007: 12000 + 2008: 12000 + 2009: 12000 + 2010: 12000 + 2011: 12000 + 2012: 12000 + 2013: 15000 + 2014: 18000 + output: + cnrps_salaire_de_reference: 20000 diff --git a/tests/formulas/cnrps/cnrps_salaire_reference.yaml b/tests/formulas/cnrps/cnrps_salaire_reference.yaml deleted file mode 100644 index 29b5254..0000000 --- a/tests/formulas/cnrps/cnrps_salaire_reference.yaml +++ /dev/null @@ -1,100 +0,0 @@ -# - name: "Individu salarié 12000 DT par an toute sa carrière" -# period: 2014 -# absolute_error_margin: 0.5 -# input: -# age: 60 -# cnrps_duree_assurance: 50 -# cnrps_salaire_de_base: -# 1975: 12000 -# 1976: 12000 -# 1977: 12000 -# 1978: 12000 -# 1979: 12000 -# 1980: 12000 -# 1981: 12000 -# 1982: 12000 -# 1983: 12000 -# 1984: 12000 -# 1985: 12000 -# 1986: 12000 -# 1987: 12000 -# 1988: 12000 -# 1989: 12000 -# 1990: 12000 -# 1991: 12000 -# 1992: 12000 -# 1993: 12000 -# 1994: 12000 -# 1995: 12000 -# 1996: 12000 -# 1997: 12000 -# 1998: 12000 -# 1999: 12000 -# 2000: 12000 -# 2001: 12000 -# 2002: 12000 -# 2003: 12000 -# 2004: 12000 -# 2005: 12000 -# 2006: 12000 -# 2007: 12000 -# 2008: 12000 -# 2009: 12000 -# 2010: 12000 -# 2011: 12000 -# 2012: 12000 -# 2013: 15000 -# 2014: 18000 -# output: -# cnrps_salaire_reference: 15000 - - -- name: "Individu salarié 12000 DT par an toute sa carrière" - period: 2014 - absolute_error_margin: 0.5 - input: - age: 60 - cnrps_duree_assurance: 50 - cnrps_salaire_de_base: - 1975: 12000 - 1976: 12000 - 1977: 12000 - 1978: 12000 - 1979: 12000 - 1980: 12000 - 1981: 12000 - 1982: 12000 - 1983: 12000 - 1984: 12000 - 1985: 12000 - 1986: 12000 - 1987: 12000 - 1988: 12000 - 1989: 12000 - 1990: 12000 - 1991: 12000 - 1992: 12000 - 1993: 12000 - 1994: 12000 - 1995: 12000 - 1996: 12000 - 1997: 12000 - 1998: 12000 - 1999: 20000 - 2000: 20000 - 2001: 20000 - 2002: 12000 - 2003: 12000 - 2004: 12000 - 2005: 12000 - 2006: 12000 - 2007: 12000 - 2008: 12000 - 2009: 12000 - 2010: 12000 - 2011: 12000 - 2012: 12000 - 2013: 15000 - 2014: 18000 - output: - cnrps_salaire_reference: 20000 diff --git a/tests/formulas/cnrps/pension.noyaml b/tests/formulas/cnrps/pension.noyaml new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_tools.py b/tests/test_tools.py new file mode 100644 index 0000000..dd17b13 --- /dev/null +++ b/tests/test_tools.py @@ -0,0 +1,18 @@ +'''Tests of tools.''' + + +import numpy as np + + +from openfisca_tunisia_pension.tools import ( + mean_over_k_consecutive_largest, + ) + + +def test_mean_over_consecutive_largest(): + array = np.array([1] * 5 + [100] * 5 + [1000] * 5).astype(np.float32) + print(array) + assert mean_over_k_consecutive_largest(array, 1) == 1000 + assert mean_over_k_consecutive_largest(array, 3) == 1000 + assert mean_over_k_consecutive_largest(array, 5) == 1000 + assert mean_over_k_consecutive_largest(array, 6) == 850 From 30cda9a1cb925e4c4804d4343e91c3ff1edb6f33 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Thu, 21 Nov 2024 14:29:40 +0100 Subject: [PATCH 21/24] Enhance pension calculation and clean --- .../indemnite_complementaire_provisoire.yaml | 10 + .../parameters/marche_travail/index.yaml | 2 +- .../majoration_smig_40h_mensuel.yaml | 9 + .../majoration_smig_48h_mensuel.yaml | 9 + .../salaire_de_base_40h_horaire.yaml | 29 +++ .../salaire_de_base_40h_mensuel.yaml | 29 +++ .../salaire_de_base_48h_horaire.yaml | 29 +++ .../salaire_de_base_48h_mensuel.yaml | 29 +++ .../parameters/marche_travail/smag.yaml | 7 - .../marche_travail/smag_journalier.yaml | 179 +++++++++++++++++ .../parameters/marche_travail/smig_40h.yaml | 43 ---- .../marche_travail/smig_40h_horaire.yaml | 150 ++++++++++++++ .../marche_travail/smig_40h_mensuel.yaml | 165 ++++++++++++++++ .../parameters/marche_travail/smig_48h.yaml | 43 ---- .../marche_travail/smig_48h_horaire.yaml | 186 ++++++++++++++++++ .../marche_travail/smig_48h_mensuel.yaml | 165 ++++++++++++++++ .../cnrps/duree_de_service_minimale.yaml | 6 + .../allocation_vieillesse.yaml | 9 + .../duree_service_allocation_vieillesse.yaml | 6 + .../cnrps/pension_minimale/index.yaml | 1 + .../pension_minimale/minimum_garanti.yaml | 8 + .../retraite/cnrps/taux_annuite_maximum.yaml | 6 - .../cnrps/taux_annuite_periode_base.yaml | 5 - .../taux_annuite_periode_supplemetaire.yaml | 5 - .../rsna/periode_remplacement_base.yaml | 6 - .../retraite/rsna/plaf_taux_pension.yaml | 5 - .../retraite/rsna/taux_annuite_base.yaml | 5 - .../rsna/taux_annuite_supplementaire.yaml | 5 - openfisca_tunisia_pension/regimes/cnrps.py | 82 ++++---- openfisca_tunisia_pension/regimes/regime.py | 91 +++------ openfisca_tunisia_pension/regimes/rsna.py | 157 ++++++++------- openfisca_tunisia_pension/variables/cnrps.py | 109 +++++----- openfisca_tunisia_pension/variables/rsa.py | 63 +++--- openfisca_tunisia_pension/variables/rsna.py | 102 ++++------ tests/formulas/cnrps/pension.noyaml | 0 tests/formulas/cnrps/pension.yaml | 36 ++++ tests/formulas/cnrps/pension_minimale.yaml | 34 ++++ ...ference.yaml => salaire_de_reference.yaml} | 0 .../rsna/{rsna_pension.yaml => pension.yaml} | 2 +- tests/test_tools.py | 2 +- 40 files changed, 1383 insertions(+), 446 deletions(-) create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/indemnite_complementaire_provisoire.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_40h_mensuel.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_48h_mensuel.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_horaire.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_mensuel.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_horaire.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_mensuel.yaml delete mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smag.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smag_journalier.yaml delete mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_40h_horaire.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_40h_mensuel.yaml delete mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_48h_horaire.yaml create mode 100644 openfisca_tunisia_pension/parameters/marche_travail/smig_48h_mensuel.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/duree_de_service_minimale.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/allocation_vieillesse.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/duree_service_allocation_vieillesse.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/index.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/minimum_garanti.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/rsna/plaf_taux_pension.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_base.yaml delete mode 100644 openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml delete mode 100644 tests/formulas/cnrps/pension.noyaml create mode 100644 tests/formulas/cnrps/pension.yaml create mode 100644 tests/formulas/cnrps/pension_minimale.yaml rename tests/formulas/cnrps/{cnrps_salaire_de_reference.yaml => salaire_de_reference.yaml} (100%) rename tests/formulas/rsna/{rsna_pension.yaml => pension.yaml} (96%) diff --git a/openfisca_tunisia_pension/parameters/marche_travail/indemnite_complementaire_provisoire.yaml b/openfisca_tunisia_pension/parameters/marche_travail/indemnite_complementaire_provisoire.yaml new file mode 100644 index 0000000..56a9d2e --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/indemnite_complementaire_provisoire.yaml @@ -0,0 +1,10 @@ +description: Indemnité Complémentaire Provisoire (ICP) - montant par mois +values: + 1981-04-07: + value: 10 +metadata: + unit: currency + reference: + 1981-04-07: + title: Décret n° 81-437 du 7 avril 1981 +documentation: Le smic est composé du salaire de base et de cette indemnité complémentaire provisoire et de sa majoration diff --git a/openfisca_tunisia_pension/parameters/marche_travail/index.yaml b/openfisca_tunisia_pension/parameters/marche_travail/index.yaml index febec99..9bbeab9 100644 --- a/openfisca_tunisia_pension/parameters/marche_travail/index.yaml +++ b/openfisca_tunisia_pension/parameters/marche_travail/index.yaml @@ -1 +1 @@ -description: Paramètres généraux +description: Salaires minimum diff --git a/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_40h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_40h_mensuel.yaml new file mode 100644 index 0000000..b489a18 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_40h_mensuel.yaml @@ -0,0 +1,9 @@ +description: Majoration du salaire minimum interprofessionnel garanti (Smig) au régime de 40h dans les secteurs non agricoles - montant par mois +values: + 1982-03-16: + value: 20 +metadata: + unit: currency + reference: + 1982-03-16: + title: Décret n° 82-501 du 16 mars 1982 diff --git a/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_48h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_48h_mensuel.yaml new file mode 100644 index 0000000..8f447b7 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/majoration_smig_48h_mensuel.yaml @@ -0,0 +1,9 @@ +description: Majoration du Salaire minimum interprofessionnel garanti (Smig) au régime de 48h dans les secteurs non agricoles - montant par mois +values: + 1982-03-16: + value: 20.368 +metadata: + unit: currency + reference: + 1982-03-16: + title: Décret n° 82-501 du 16 mars 1982 diff --git a/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_horaire.yaml b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_horaire.yaml new file mode 100644 index 0000000..9fde401 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_horaire.yaml @@ -0,0 +1,29 @@ +description: salaire de base horaire - régime 40h par semaine +values: + 2008-07-01: + value: 1.084 + 2009-08-01: + value: 1.126 + 2010-07-01: + value: 1.183 + 2011-05-01: + value: 1.248 + 2012-07-01: + value: 1.324 + 2014-05-01: + value: 1.411 +metadata: + unit: currency + reference: + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf diff --git a/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_mensuel.yaml new file mode 100644 index 0000000..5c9baf9 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_40h_mensuel.yaml @@ -0,0 +1,29 @@ +description: salaire de base mensuel - régime 40h par semaine +values: + 2008-07-01: + value: 187.88 + 2009-08-01: + value: 195.16 + 2010-07-01: + value: 205.04 + 2011-05-01: + value: 216.306 + 2012-07-01: + value: 229.479 + 2014-05-01: + value: 244.559 +metadata: + unit: currency + reference: + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf diff --git a/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_horaire.yaml b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_horaire.yaml new file mode 100644 index 0000000..48bd530 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_horaire.yaml @@ -0,0 +1,29 @@ +description: salaire de base horaire - régime 48h par semaine +values: + 2008-07-01: + value: 1.065 + 2009-08-01: + value: 1.107 + 2010-07-01: + value: 1.164 + 2011-05-01: + value: 1.229 + 2012-07-01: + value: 1.305 + 2014-05-01: + value: 1.392 +metadata: + unit: currency + reference: + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf diff --git a/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_mensuel.yaml new file mode 100644 index 0000000..cd281c3 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/salaire_de_base_48h_mensuel.yaml @@ -0,0 +1,29 @@ +description: salaire de base mensuel - régime 48h par semaine +values: + 2008-07-01: + value: 221.52 + 2009-08-01: + value: 230.256 + 2010-07-01: + value: 242.112 + 2011-05-01: + value: 255.632 + 2012-07-01: + value: 271.44 + 2014-05-01: + value: 289.536 +metadata: + unit: currency + reference: + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 - http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smag.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smag.yaml deleted file mode 100644 index 48738d9..0000000 --- a/openfisca_tunisia_pension/parameters/marche_travail/smag.yaml +++ /dev/null @@ -1,7 +0,0 @@ -description: SMAG journalier -unit: currency -values: - 2010-07-01: - value: 8.38 - 2011-07-01: - value: 9.0 diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smag_journalier.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smag_journalier.yaml new file mode 100644 index 0000000..50e3a63 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/smag_journalier.yaml @@ -0,0 +1,179 @@ +description: Salaire Minimum Agricole Garanti (SMAG) - montant par jour +values: + 1966-01-01: + value: 0.385 + 1968-05-01: + value: 0.5 + 1969-11-01: + value: 0.55 + 1971-05-01: + value: 0.6 + 1974-06-01: + value: 0.8 + 1975-06-01: + value: 0.9 + 1977-05-01: + value: 1.2 + 1978-05-01: + value: 1.332 + 1979-05-01: + value: 1.44 + 1980-02-01: + value: 1.483 + 1980-05-01: + value: 1.631 + 1981-04-01: + value: 2 + 1982-02-01: + value: 2.4 + 1983-01-01: + value: 2.64 + 1986-07-01: + value: 2.9 + 1987-11-01: + value: 3.05 + 1988-04-01: + value: 3.2 + 1989-08-01: + value: 3.315 + 1990-01-01: + value: 3.661 + 1991-08-01: + value: 3.761 + 1992-05-01: + value: 3.961 + 1992-08-01: + value: 4.061 + 1993-05-01: + value: 4.261 + 1993-08-01: + value: 4.361 + 1994-08-01: + value: 4.461 + 1995-05-01: + value: 4.661 + 1996-05-01: + value: 4.861 + 1996-09-09: + value: 4.961 + 1997-07-20: + value: 5.061 + 1997-11-07: + value: 5.209 + 1998-08-20: + value: 5.309 + 1999-05-01: + value: 5.509 + 1999-08-19: + value: 5.609 + 2000-05-01: + value: 5.809 + 2001-07-01: + value: 6.059 + 2002-07-01: + value: 6.259 + 2003-07-01: + value: 6.509 + 2004-07-01: + value: 6.709 + 2005-09-01: + value: 6.909 + 2006-07-01: + value: 7.129 + 2007-07-01: + value: 7.379 + 2008-07-01: + value: 7.749 + 2009-08-01: + value: 8.019 + 2010-07-01: + value: 8.38 + 2011-05-01: + value: 9 + 2012-07-01: + value: 10.608 + 2012-12-01: + value: 11.608 + 2014-08-11: + value: 12.304 + 2015-11-09: + value: 13 + 2017-06-05: + value: 13.736 + 2018-05-01: + value: 14.56 + 2019-05-01: + value: 15.504 +metadata: + unit: currency + reference: + 1990-01-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1991-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1992-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1992-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1993-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1993-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1994-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1995-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1996-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1996-09-09: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1997-07-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1997-11-07: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1998-08-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1999-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 1999-08-19: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2000-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2001-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2002-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2003-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2004-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2005-09-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2006-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2007-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2008-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2009-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2010-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmagFR.pdf + 2014-08-11: + title: Décret n°2014-2908 du 11 Août 2014 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429083.pdf + 2015-11-09: + title: Décret n°2015-1763 du 09 Novembre 2015 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2015/2015F/091/Tf2015017623.pdf + 2017-06-05: + title: Décret n°2017-669 du 05 Juin 2017 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2017/2017F/045/Tf20176693.pdf + 2018-05-01: + title: Décret gouvernemental n°2018-673 du 07 août 2018 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2018/2018F/064/Tf20186723.pdf + 2019-05-01: + title: Décret gouvernemental n° 2019-455 du 28 mai 2019 + href: http://www.legislation.tn/fr/detailtexte/Décret%20Gouvernemental-num-2019-455-du----jort-2019-043__20190430045532?shorten=m5lK +documentation: |- + Salaire minimum agricole garanti par journée de travail effectif pour les travailleurs des deux sexes âgés de 18 ans au moins + الأجر الأدنى الفلاحي المضمون للعمال من الجنسين البالغين من العمر 18 سنة على الأقل عن كل يوم عمل فعلي diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml deleted file mode 100644 index 726bbd5..0000000 --- a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h.yaml +++ /dev/null @@ -1,43 +0,0 @@ -description: Smig 40h -unit: currency -values: - 1995-05-01: - value: 105.024 - 1996-05-01: - value: 110.051 - 1996-09-09: - value: 112.132 - 1997-07-20: - value: 114.211 - 1997-11-08: - value: 119.237 - 1998-08-20: - value: 121.664 - 1999-05-01: - value: 126.691 - 1999-08-19: - value: 128.771 - 2000-05-11: - value: 133.795 - 2001-08-01: - value: 140.905 - 2002-07-01: - value: 146.799 - 2003-07-01: - value: 153.906 - 2004-07-01: - value: 159.8 - 2005-09-01: - value: 164.827 - 2006-07-01: - value: 170.721 - 2007-07-01: - value: 177.828 - 2008-07-01: - value: 187.88 - 2009-08-01: - value: 195.16 - 2010-07-01: - value: 205.04 - 2011-05-01: - value: 216.306 diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_horaire.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_horaire.yaml new file mode 100644 index 0000000..44708ed --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_horaire.yaml @@ -0,0 +1,150 @@ +description: Salaire minimum interprofessionnel garanti (Smig) horaire - régime 40h par semaine +values: + 1990-01-01: + value: 0.621 + 1991-08-01: + value: 0.633 + 1992-05-01: + value: 0.671 + 1992-08-01: + value: 0.683 + 1993-05-01: + value: 0.721 + 1993-08-01: + value: 0.733 + 1994-08-01: + value: 0.745 + 1995-05-01: + value: 0.779 + 1996-05-01: + value: 0.808 + 1996-09-09: + value: 0.82 + 1997-07-20: + value: 0.832 + 1997-11-07: + value: 0.861 + 1998-08-20: + value: 0.875 + 1999-05-01: + value: 0.904 + 1999-08-19: + value: 0.916 + 2000-05-01: + value: 0.945 + 2001-07-01: + value: 0.986 + 2002-07-01: + value: 1.02 + 2003-07-01: + value: 1.061 + 2004-07-01: + value: 1.095 + 2005-09-01: + value: 1.124 + 2006-07-01: + value: 1.158 + 2007-07-01: + value: 1.199 + 2008-07-01: + value: 1.257 + 2009-08-01: + value: 1.299 + 2010-07-01: + value: 1.356 + 2011-05-01: + value: 1.421 + 2012-07-01: + value: 1.497 + 2014-05-01: + value: 1.584 + 2015-05-01: + value: 1.671 + 2016-08-01: + value: 1.763 + 2018-05-01: + value: 1.866 + 2019-05-01: + value: 1.984 +metadata: + unit: currency + reference: + 1990-01-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1991-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1992-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1992-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1993-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1993-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1994-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1995-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1996-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1996-09-09: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1997-07-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1997-11-07: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1998-08-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1999-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1999-08-19: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2000-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2001-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2002-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2003-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2004-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2005-09-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2006-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2007-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf + 2015-05-01: + title: Décret n°2015-1762 du 09 Novembre 2015 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2015/2015F/091/Tf2015017623.pdf + 2016-08-01: + title: Décret n°2017-668 du 05 Juin 2017 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2017/2017F/045/Tf20176683.pdf + 2018-05-01: + title: Décret gouvernemental n° 2018-672 du 07 août 2018 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2018/2018F/064/Tf20186723.pdf + 2019-05-01: + title: Décret gouvernemental n°2019-454 du 28 mai 2019 + href: http://www.legislation.tn/fr/detailtexte/Décret%20Gouvernemental-num-2019-454-du----jort-2019-043__20190430045432?shorten=m5lq +documentation: |- + Salaire minimum interprofessionnel garanti (Smig) dans les secteurs non agricoles pour les travailleurs des deux sexes âgés de 18 ans au moins + الأجر الأدنى المضمون لمختلف المهن في القطاعات غير الفلاحية للعمال من الجنسين البالغين من العمر 18 سنة على الأقل diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_mensuel.yaml new file mode 100644 index 0000000..2414580 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_40h_mensuel.yaml @@ -0,0 +1,165 @@ +description: Salaire minimum interprofessionnel garanti (Smig) mensuel - régime 40h par semaine +values: + 1975-06-01: + value: 25.133 + 1980-05-01: + value: 45.586 + 1982-02-01: + value: 45.586 + 1990-01-01: + value: 107.706 + 1991-08-01: + value: 109.706 + 1992-05-01: + value: 116.318 + 1992-08-01: + value: 118.398 + 1993-05-01: + value: 124.971 + 1993-08-01: + value: 127.051 + 1994-08-01: + value: 129.131 + 1995-05-01: + value: 135.024 + 1996-05-01: + value: 140.051 + 1996-09-09: + value: 142.131 + 1997-07-20: + value: 144.211 + 1997-11-07: + value: 149.237 + 1998-08-20: + value: 151.664 + 1999-05-01: + value: 156.691 + 1999-08-19: + value: 158.771 + 2000-05-01: + value: 163.798 + 2001-07-01: + value: 170.905 + 2002-07-01: + value: 176.799 + 2003-07-01: + value: 183.906 + 2004-07-01: + value: 189.8 + 2005-09-01: + value: 194.827 + 2006-07-01: + value: 200.721 + 2007-07-01: + value: 207.828 + 2008-07-01: + value: 217.88 + 2009-08-01: + value: 225.16 + 2010-07-01: + value: 235.04 + 2011-05-01: + value: 246.306 + 2012-07-01: + value: 259.479 + 2014-05-01: + value: 274.559 + 2015-05-01: + value: 289.639 + 2016-08-01: + value: 305.586 + 2018-05-01: + value: 323.439 + 2019-05-01: + value: 343.892 +metadata: + unit: currency + reference: + 1975-06-01: + title: Décret n°75-357 du 03 Juin 1975 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1975/1975F/Jo03875.pdf + 1980-05-01: + title: Décret n°80-609 du 19 Mai 1980 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1980/1980F/Jo03180.pdf + 1982-02-01: + title: Décret n°80-609 du 19 Mai 1980 + Décret n°82-501 du 16 Mars 1982 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1982/1982F/Jo01982.pdf + 1990-01-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1991-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1992-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1992-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1993-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1993-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1994-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1995-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1996-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1996-09-09: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1997-07-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1997-11-07: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1998-08-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1999-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 1999-08-19: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2000-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2001-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2002-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2003-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2004-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2005-09-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2006-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2007-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig40FR.pdf + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf + 2015-05-01: + title: Décret n°2015-1762 du 09 Novembre 2015 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2015/2015F/091/Tf2015017623.pdf + 2016-08-01: + title: Décret n°2017-668 du 05 Juin 2017 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2017/2017F/045/Tf20176683.pdf + 2018-05-01: + title: Décret gouvernemental n°2018-672 du 07 août 2018 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2018/2018F/064/Tf20186723.pdf + 2019-05-01: + title: Décret gouvernemental n°2019-454 du 28 mai 2019 + href: http://www.legislation.tn/fr/detailtexte/Décret%20Gouvernemental-num-2019-454-du----jort-2019-043__20190430045432?shorten=m5lq +documentation: |- + Salaire minimum interprofessionnel garanti dans les secteurs non agricoles pour les travailleurs des deux sexes âgés de 18 ans au moins + الأجر الأدنى المضمون لمختلف المهن في القطاعات غير الفلاحية للعمال من الجنسين البالغين من العمر 18 سنة على الأقل diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml deleted file mode 100644 index 0665d7b..0000000 --- a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h.yaml +++ /dev/null @@ -1,43 +0,0 @@ -description: Smig 48h -unit: currency -values: - 1995-05-01: - value: 123.76 - 1996-05-01: - value: 129.792 - 1996-09-09: - value: 131.872 - 1997-07-20: - value: 133.952 - 1997-11-08: - value: 139.984 - 1998-08-20: - value: 142.48 - 1999-05-01: - value: 148.512 - 1999-08-19: - value: 150.592 - 2000-05-11: - value: 156.624 - 2001-08-01: - value: 165.152 - 2002-07-01: - value: 172.224 - 2003-07-01: - value: 180.752 - 2004-07-01: - value: 187.824 - 2005-09-01: - value: 193.856 - 2006-07-01: - value: 200.928 - 2007-07-01: - value: 209.456 - 2008-07-01: - value: 221.52 - 2009-08-01: - value: 230.256 - 2010-07-01: - value: 242.111 - 2011-05-01: - value: 255.632 diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_horaire.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_horaire.yaml new file mode 100644 index 0000000..ce24891 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_horaire.yaml @@ -0,0 +1,186 @@ +description: Salaire minimum interprofessionnel garanti (Smig) horaire - régime 48h par semaine +values: + 1961-04-01: + value: 0.076 + 1966-01-01: + value: 0.084 + 1968-05-01: + value: 0.084 + 1971-05-01: + value: 0.104 + 1974-01-01: + value: 0.13 + 1975-06-01: + value: 0.145 + 1977-02-01: + value: 0.193 + 1978-05-01: + value: 0.21425 + 1979-05-01: + value: 0.232 + 1980-02-01: + value: 0.23896 + 1980-05-01: + value: 0.263 + 1981-04-01: + value: 0.311 + 1982-02-01: + value: 0.409 + 1983-01-01: + value: 0.457 + 1986-07-01: + value: 0.481 + 1987-11-01: + value: 0.505 + 1988-04-01: + value: 0.529 + 1989-08-01: + value: 0.543 + 1990-01-01: + value: 0.591 + 1991-08-01: + value: 0.601 + 1992-05-01: + value: 0.639 + 1992-08-01: + value: 0.649 + 1993-05-01: + value: 0.687 + 1993-08-01: + value: 0.697 + 1994-08-01: + value: 0.707 + 1995-05-01: + value: 0.741 + 1996-05-01: + value: 0.77 + 1996-09-09: + value: 0.78 + 1997-07-20: + value: 0.79 + 1997-11-07: + value: 0.819 + 1998-08-20: + value: 0.831 + 1999-05-01: + value: 0.86 + 1999-08-19: + value: 0.87 + 2000-05-01: + value: 0.899 + 2001-07-01: + value: 0.94 + 2002-07-01: + value: 0.974 + 2003-07-01: + value: 1.015 + 2004-07-01: + value: 1.049 + 2005-09-01: + value: 1.078 + 2006-07-01: + value: 1.112 + 2007-07-01: + value: 1.153 + 2008-07-01: + value: 1.211 + 2009-08-01: + value: 1.253 + 2010-07-01: + value: 1.31 + 2011-05-01: + value: 1.375 + 2012-07-01: + value: 1.451 + 2014-05-01: + value: 1.538 + 2015-05-01: + value: 1.625 + 2016-08-01: + value: 1.717 + 2018-05-01: + value: 1.82 + 2019-05-01: + value: 1.938 +metadata: + unit: currency + reference: + 1990-01-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1991-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1992-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1992-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1993-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1993-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1994-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1995-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1996-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1996-09-09: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1997-07-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1997-11-07: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1998-08-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1999-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1999-08-19: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2000-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2001-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2002-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2003-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2004-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2005-09-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2006-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2007-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf + 2015-05-01: + title: Décret n°2015-1762 du 09 Novembre 2015 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2015/2015F/091/Tf2015017623.pdf + 2016-08-01: + title: Décret n°2017-668 du 05 Juin 2017 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2017/2017F/045/Tf20176683.pdf + 2018-05-01: + title: Décret gouvernemental n°2018-672 du 07 août 2018 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2018/2018F/064/Tf20186723.pdf + 2019-05-01: + title: Décret gouvernemental n°2019-454 du 28 mai 2019 + href: http://www.legislation.tn/fr/detailtexte/Décret%20Gouvernemental-num-2019-454-du----jort-2019-043__20190430045432?shorten=m5lq +documentation: |- + Salaire minimum interprofessionnel garanti (Smig) dans les secteurs non agricoles pour les travailleurs des deux sexes âgés de 18 ans au moins + الأجر الأدنى المضمون لمختلف المهن في القطاعات غير الفلاحية للعمال من الجنسين البالغين من العمر 18 سنة على الأقل diff --git a/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_mensuel.yaml b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_mensuel.yaml new file mode 100644 index 0000000..8e2eb28 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/marche_travail/smig_48h_mensuel.yaml @@ -0,0 +1,165 @@ +description: Salaire minimum interprofessionnel garanti (Smig) mensuel - régime 48h par semaine +values: + 1975-06-01: + value: 30.16 + 1980-05-01: + value: 54.704 + 1982-02-01: + value: 54.704 + 1990-01-01: + value: 123.016 + 1991-08-01: + value: 125.016 + 1992-05-01: + value: 132.912 + 1992-08-01: + value: 134.992 + 1993-05-01: + value: 142.896 + 1993-08-01: + value: 144.976 + 1994-08-01: + value: 147.056 + 1995-05-01: + value: 154.128 + 1996-05-01: + value: 160.16 + 1996-09-09: + value: 162.24 + 1997-07-20: + value: 164.32 + 1997-11-07: + value: 170.352 + 1998-08-20: + value: 172.848 + 1999-05-01: + value: 178.88 + 1999-08-19: + value: 180.96 + 2000-05-01: + value: 186.992 + 2001-07-01: + value: 195.52 + 2002-07-01: + value: 202.592 + 2003-07-01: + value: 211.12 + 2004-07-01: + value: 218.192 + 2005-09-01: + value: 224.224 + 2006-07-01: + value: 231.296 + 2007-07-01: + value: 239.824 + 2008-07-01: + value: 251.888 + 2009-08-01: + value: 260.624 + 2010-07-01: + value: 272.48 + 2011-05-01: + value: 286 + 2012-07-01: + value: 301.808 + 2014-05-01: + value: 319.904 + 2015-05-01: + value: 338 + 2016-08-01: + value: 357.136 + 2018-05-01: + value: 378.56 + 2019-05-01: + value: 403.104 +metadata: + unit: currency + reference: + 1975-06-01: + title: Décret n°75-357 du 03 Juin 1975 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1975/1975F/Jo03875.pdf + 1980-05-01: + title: Décret n°80-609 du 19 Mai 1980 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1980/1980F/Jo03180.pdf + 1982-02-01: + title: Décret n°80-609 du 19 Mai 1980 + Décret n°82-501 du 16 Mars 1982 + href: http://www.legislation.tn/sites/default/files/journal-officiel/1982/1982F/Jo01982.pdf + 1990-01-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1991-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1992-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1992-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1993-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1993-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1994-08-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1995-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1996-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1996-09-09: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1997-07-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1997-11-07: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1998-08-20: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1999-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 1999-08-19: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2000-05-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2001-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2002-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2003-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2004-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2005-09-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2006-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2007-07-01: + href: http://www.social.tn/fileadmin/user1/doc/pdftravail/evosmig48FR.pdf + 2008-07-01: + title: Décret n°2008-2072 du 02 Juin 2008 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2008/2008F/046/TF200820723.pdf + 2009-08-01: + title: Décret n°2009-2257 du 14 Juillet 2009 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2009/2009F/062/TF200922573.pdf + 2010-07-01: + title: Décret n°2010-1746 du 17 Juillet 2010 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2010/2010F/058/TF201017463.pdf + 2011-05-01: + title: Décret n°2011-679 du 09 Juin 2011 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2011/2011F/042/TF20116793.pdf + 2012-07-01: + title: Décret n°2012-1981 du 20 Septembre 2012 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2012/2012F/077/TF201219813.pdf + 2014-05-01: + title: Décret n°2014-2907 du 11 Août 2014 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2014/2014F/066/Tf201429073.pdf + 2015-05-01: + title: Décret n°2015-1762 du 09 Novembre 2015 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2015/2015F/091/Tf2015017623.pdf + 2016-08-01: + title: Décret n°2017-668 du 05 Juin 2017 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2017/2017F/045/Tf20176683.pdf + 2018-05-01: + title: Décret gouvernemental n°2018-672 du 07 août 2018 + href: http://www.legislation.tn/sites/default/files/fraction-journal-officiel/2018/2018F/064/Tf20186723.pdf + 2019-05-01: + title: Décret gouvernemental n°2019-454 du 28 mai 2019 + href: http://www.legislation.tn/fr/detailtexte/Décret%20Gouvernemental-num-2019-454-du----jort-2019-043__20190430045432?shorten=m5lq +documentation: |- + Salaire minimum interprofessionnel garanti (Smig) dans les secteurs non agricoles pour les travailleurs des deux sexes âgés de 18 ans au moins + الأجر الأدنى المضمون لمختلف المهن في القطاعات غير الفلاحية للعمال من الجنسين البالغين من العمر 18 سنة على الأقل diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/duree_de_service_minimale.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/duree_de_service_minimale.yaml new file mode 100644 index 0000000..87b2ce1 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/duree_de_service_minimale.yaml @@ -0,0 +1,6 @@ +description: Durée de service minimale requise pour prétendre à une pension de retraite +values: + 1974-01-01: + value: 15 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/allocation_vieillesse.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/allocation_vieillesse.yaml new file mode 100644 index 0000000..cfce86e --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/allocation_vieillesse.yaml @@ -0,0 +1,9 @@ +description: Allocation de vieillesse (en parts du Smig) +values: + 1959-02-01: + value: 0.5 +metadata: + unit: Smig +documentation: + L'allocation de vieillesse est octroyée aux cotisants ne pouvant bénéficier d'une pension de retraite mais + qui justifient d'une période d'activité d'au moins 5 ans diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/duree_service_allocation_vieillesse.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/duree_service_allocation_vieillesse.yaml new file mode 100644 index 0000000..68d57e0 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/duree_service_allocation_vieillesse.yaml @@ -0,0 +1,6 @@ +description: Durée de service minimale requise pour prétendre à une allocation de vieillesse +values: + 1974-01-01: + value: 5 +metadata: + unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/index.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/index.yaml new file mode 100644 index 0000000..e978e81 --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/index.yaml @@ -0,0 +1 @@ +description: Pension minimale (en part de Smig) diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/minimum_garanti.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/minimum_garanti.yaml new file mode 100644 index 0000000..1cf779a --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/pension_minimale/minimum_garanti.yaml @@ -0,0 +1,8 @@ +description: Pension minimale garanti de la CNRPS +values: + 1974-01-01: + value: 0.66666 +metadata: + unit: Smig +documentation: + Pension minimale servie aux cotisants justifiant d'une durée suffisante pour prétendre à une pension de retraite diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml deleted file mode 100644 index 7d45ec9..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_maximum.yaml +++ /dev/null @@ -1,6 +0,0 @@ -description: Taux d'annuité maximal -values: - 1959-02-01: - value: 0.9 -metadata: - unit: /1 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml deleted file mode 100644 index a85c568..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_base.yaml +++ /dev/null @@ -1,5 +0,0 @@ -description: Taux d'annuité de la période de base (allant de la 1ère à la 10e année liquidable) par trimestre -unit: /1 -values: - 1959-02-01: - value: 0.005 diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml deleted file mode 100644 index ac14a9b..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/taux_annuite_periode_supplemetaire.yaml +++ /dev/null @@ -1,5 +0,0 @@ -description: Taux d'annuité de la période supplémentaire (allant de la 11e à la 20e année liquidable) par trimestre -unit: /1 -values: - 1959-02-01: - value: 0.0075 diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml deleted file mode 100644 index 1ee84da..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/periode_remplacement_base.yaml +++ /dev/null @@ -1,6 +0,0 @@ -description: Période de remplacement de base -values: - 1974-01-01: - value: 10 -metadata: - unit: year diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/plaf_taux_pension.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/plaf_taux_pension.yaml deleted file mode 100644 index 4e7ab90..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/plaf_taux_pension.yaml +++ /dev/null @@ -1,5 +0,0 @@ -description: Plafonnement du taux de pension -unit: /1 -values: - 1974-01-01: - value: 0.8 diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_base.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_base.yaml deleted file mode 100644 index f320ab2..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_base.yaml +++ /dev/null @@ -1,5 +0,0 @@ -description: Taux d'annuité de base -unit: /1 -values: - 1974-01-01: - value: 0.04 diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml deleted file mode 100644 index 88edad4..0000000 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/taux_annuite_supplementaire.yaml +++ /dev/null @@ -1,5 +0,0 @@ -description: Taux d'annuité supplémentaire -unit: /1 -values: - 1974-01-01: - value: 0.02 diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index ffb7cef..189400b 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -10,12 +10,9 @@ from numpy import ( apply_along_axis, - logical_not as not_, - maximum as max_, vstack, ) -from openfisca_tunisia_pension.variables.helpers import pension_generique from openfisca_tunisia_pension.tools import make_mean_over_consecutive_largest @@ -97,46 +94,55 @@ def formula(individu, period): ) return salaire_refererence - class pension(Variable): + # class pension_maximale(Variable): + # value_type = float + # default_value = np.inf # Pas de pension maximale par défaut + # entity = Individu + # definition_period = YEAR + # label = 'Pension maximale' + + # def formula(individu, period, parameters): + # NotImplementedError + + class pension_minimale(Variable): value_type = float + default_value = 0 # Pas de pension minimale par défaut, elle est à zéro + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + cnrps = parameters(period).retraite.regime_name + pension_minimale = cnrps.pension_minimale + duree_de_service_minimale = cnrps.duree_de_service_minimale + # TODO Annualiser le Smig + smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel + duree_assurance = individu('regime_name_duree_assurance', period) + return apply_thresholds( + duree_assurance / 4, + [ + pension_minimale.duree_service_allocation_vieillesse, + duree_de_service_minimale, + ], + [ + 0, + pension_minimale.allocation_vieillesse * smig_annuel, + pension_minimale.minimum_garanti * smig_annuel, + ] + + ) + + class eligible(Variable): + value_type = bool entity = Individu - label = 'Pension des affiliés au régime des salariés non agricoles' + label = "L'individu est éligible à une pension CNRPS" definition_period = YEAR def formula(individu, period, parameters): duree_assurance = individu('regime_name_duree_assurance', period = period) - salaire_reference = individu('regime_name_salaire_de_reference', period = period) + salaire_de_reference = individu('regime_name_salaire_de_reference', period = period) age = individu('age', period = period) - cnrps = parameters(period).retraite.regime_name - taux_annuite_base = cnrps.taux_annuite_base - taux_annuite_supplementaire = cnrps.taux_annuite_supplementaire - duree_stage = cnrps.stage_derog - age_eligible = cnrps.age_dep_anticip - periode_remplacement_base = cnrps.periode_remplacement_base - plaf_taux_pension = cnrps.plaf_taux_pension - smig = parameters(period).marche_travail.smig_48h - - pension_min_sup = cnrps.pension_minimale.sup - pension_min_inf = cnrps.pension_minimale.inf - - stage = duree_assurance > 4 * duree_stage - pension_minimale = ( - stage * pension_min_sup + not_(stage) * pension_min_inf - ) - montant = pension_generique( - duree_assurance, - salaire_reference, - taux_annuite_base, - taux_annuite_supplementaire, - duree_stage, - age_eligible, - periode_remplacement_base, - plaf_taux_pension, - ) - # eligibilite - eligibilite_age = age > age_eligible - eligibilite = stage * eligibilite_age * (salaire_reference > 0) - # plafonnement - montant_pension_percu = max_(montant, pension_minimale * smig) - return eligibilite * montant_pension_percu + duree_de_service_minimale_accomplie = duree_assurance > 4 * cnrps.duree_de_service_minimale + critere_age_verifie = age >= cnrps.age_legal.civil.cadre_commun + return duree_de_service_minimale_accomplie * critere_age_verifie * (salaire_de_reference > 0) diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py index 8649ad5..ab7db87 100644 --- a/openfisca_tunisia_pension/regimes/regime.py +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -1,5 +1,7 @@ '''Abstract regimes definition.''' +import numpy as np + from openfisca_core.model_api import * from openfisca_core.errors.variable_not_found_error import VariableNotFoundError @@ -93,52 +95,14 @@ class duree_assurance_annuelle(Variable): definition_period = YEAR label = "Durée d'assurance (en trimestres validés l'année considérée)" - class majoration_duree_assurance(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance" - - def formula(individu, period): - return ( - individu('regime_name_majoration_duree_assurance_enfant', period) - + individu('regime_name_majoration_duree_assurance_autre', period) - ) - - class majoration_duree_assurance_autre(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" - - class majoration_pension(Variable): - value_type = float + class eligible(Variable): + value_type = bool entity = Individu + label = "L'individu est éligible à une pension" definition_period = YEAR - label = 'Majoration de pension' - - class majoration_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Majoration de pension au 31 décembre' def formula(individu, period, parameters): - annee_de_liquidation = individu('regime_name_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - # Raccouci pour arrêter les calculs dans le passé quand toutes les liquidations ont lieu dans le futur - if all(annee_de_liquidation > period.start.year): - return individu.empty_array() - last_year = period.last_year - majoration_pension_au_31_decembre_annee_precedente = individu('regime_name_majoration_pension_au_31_decembre', last_year) - revalorisation = parameters(period).regime_name.revalorisation_pension_au_31_decembre - majoration_pension = individu('regime_name_majoration_pension', period) - return revalorise( - majoration_pension_au_31_decembre_annee_precedente, - majoration_pension, - annee_de_liquidation, - revalorisation, - period, - ) + NotImplementedError class pension(Variable): value_type = float @@ -148,18 +112,19 @@ class pension(Variable): def formula(individu, period): pension_brute = individu('regime_name_pension_brute', period) + eligible = individu('regime_name_eligible', period) try: pension_minimale = individu('regime_name_pension_minimale', period) except VariableNotFoundError: pension_minimale = 0 try: pension_maximale = individu('regime_name_pension_maximale', period) - except VariableNotFoundError: + except (VariableNotFoundError, NotImplementedError): return max_( pension_brute, pension_minimale ) - return min_( + return eligible * min_( pension_maximale, max_( pension_brute, @@ -178,25 +143,25 @@ def formula(individu, period, parameters): salaire_de_reference = individu('regime_name_salaire_de_reference', period) return taux_de_liquidation * salaire_de_reference, - # class pension_maximale(Variable): - # value_type = float - # default_value = np.inf # Pas de pension maximale par défaut - # entity = Individu - # definition_period = YEAR - # label = 'Pension maximale' - - # def formula(individu, period, parameters): - # NotImplementedError - - # class pension_minimale(Variable): - # value_type = float - # default_value = 0 # Pas de pension minimale par défaut, elle est à zéro - # entity = Individu - # definition_period = YEAR - # label = 'Pension minimale' - - # def formula(individu, period, parameters): - # NotImplementedError + class pension_maximale(Variable): + value_type = float + default_value = np.inf # Pas de pension maximale par défaut + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + + class pension_minimale(Variable): + value_type = float + # default_value = 0 # Pas de pension minimale par défaut, elle est à zéro + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError class pension_servie(Variable): value_type = float diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 6d5df7c..00fa636 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -11,14 +11,11 @@ from numpy import ( apply_along_axis, - logical_not as not_, - maximum as max_, vstack, ) from openfisca_tunisia_pension.tools import make_mean_over_largest -from openfisca_tunisia_pension.variables.helpers import pension_generique class RegimeRSNA(AbstractRegimeEnAnnuites): @@ -36,7 +33,97 @@ class RSNATypesRaisonDepartAnticipe(Enum): # A partir de 55 ans : convenance_personnelle = 'Convenance personnelle, avec 360 mois de cotisations (120 trimestres)' - class salaire_reference(Variable): + + class eligible(Variable): + value_type = bool + entity = Individu + label = "L'individu est éligible à une pension CNRPS" + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('regime_name_duree_assurance', period = period) + salaire_de_reference = individu('regime_name_salaire_de_reference', period = period) + age = individu('age', period = period) + rsna = parameters(period).retraite.regime_name + duree_stage_accomplie = duree_assurance > 4 * rsna.stage_requis + critere_age_verifie = age >= rsna.age_legal + return duree_stage_accomplie * critere_age_verifie * (salaire_de_reference > 0) + + # class pension(Variable): + # value_type = float + # entity = Individu + # label = 'Pension des affiliés au régime des salariés non agricoles' + # definition_period = YEAR + + # def formula(individu, period, parameters): + # duree_assurance = individu('regime_name_duree_assurance', period = period) + # salaire_reference = individu('regime_name_salaire_reference', period = period) + # age = individu('age', period = period) + + # rsna = parameters(period).retraite.regime_name + # taux_annuite_base = rsna.taux_annuite_base + # taux_annuite_supplementaire = rsna.taux_annuite_supplementaire + # age_eligible = rsna.age_dep_anticip + # periode_remplacement_base = rsna.periode_remplacement_base + # plaf_taux_pension = rsna.plaf_taux_pension + # smig = parameters(period).marche_travail.smig_48h + + # pension_min_sup = rsna.pension_minimale.sup + # pension_min_inf = rsna.pension_minimale.inf + + # duree_stage = rsna.stage_derog + # stage = duree_assurance > 4 * duree_stage + # pension_minimale = ( + # stage * pension_min_sup + not_(stage) * pension_min_inf + # ) + # montant = pension_generique( + # duree_assurance, + # salaire_reference, + # taux_annuite_base, + # taux_annuite_supplementaire, + # duree_stage, + # age_eligible, + # periode_remplacement_base, + # plaf_taux_pension, + # ) + # # eligibilite + # eligibilite_age = age > age_eligible + # eligibilite = stage * eligibilite_age * (salaire_reference > 0) + # # plafonnement + # montant_pension_percu = max_(montant, pension_minimale * smig) + # return eligibilite * montant_pension_percu + + + + class pension_minimale(Variable): + value_type = float + default_value = 0 # Pas de pension minimale par défaut, elle est à zéro + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + rsna = parameters(period).retraite.regime_name + pension_minimale = rsna.pension_minimale + # TODO Annualiser le Smig + smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel + duree_assurance = individu('regime_name_duree_assurance', period) + # TODO: vérifier et corriger + return apply_thresholds( + duree_assurance / 4, + [ + rsna.stage_derog, + rsna.stage_requis, + ], + [ + 0, + pension_minimale.inf * smig_annuel, + pension_minimale.sup * smig_annuel, + ] + + ) + + class salaire_de_reference(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime des salariés non agricoles' @@ -57,65 +144,3 @@ def formula(individu, period): ]), ) return salaire_refererence - - class pension(Variable): - value_type = float - entity = Individu - label = 'Pension des affiliés au régime des salariés non agricoles' - definition_period = YEAR - - def formula(individu, period, parameters): - duree_assurance = individu('regime_name_duree_assurance', period = period) - salaire_reference = individu('regime_name_salaire_reference', period = period) - age = individu('age', period = period) - - rsna = parameters(period).retraite.regime_name - taux_annuite_base = rsna.taux_annuite_base - taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - age_eligible = rsna.age_dep_anticip - periode_remplacement_base = rsna.periode_remplacement_base - plaf_taux_pension = rsna.plaf_taux_pension - smig = parameters(period).marche_travail.smig_48h - - pension_min_sup = rsna.pension_minimale.sup - pension_min_inf = rsna.pension_minimale.inf - - duree_stage = rsna.stage_derog - stage = duree_assurance > 4 * duree_stage - pension_minimale = ( - stage * pension_min_sup + not_(stage) * pension_min_inf - ) - montant = pension_generique( - duree_assurance, - salaire_reference, - taux_annuite_base, - taux_annuite_supplementaire, - duree_stage, - age_eligible, - periode_remplacement_base, - plaf_taux_pension, - ) - # eligibilite - eligibilite_age = age > age_eligible - eligibilite = stage * eligibilite_age * (salaire_reference > 0) - # plafonnement - montant_pension_percu = max_(montant, pension_minimale * smig) - return eligibilite * montant_pension_percu - - class pension_maximale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension maximale' - - def formula(individu, period, parameters): - NotImplementedError - - class pension_minimale(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Pension minimale' - - def formula(individu, period, parameters): - NotImplementedError diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index 5d626ad..2576439 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -1,4 +1,5 @@ """Abstract regimes definition.""" +import numpy as np from openfisca_core.model_api import * from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu @@ -6,8 +7,7 @@ from openfisca_core.model_api import * from openfisca_tunisia_pension.entities import Individu from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack -from openfisca_tunisia_pension.variables.helpers import pension_generique +from numpy import apply_along_axis, vstack from openfisca_tunisia_pension.tools import make_mean_over_consecutive_largest class cnrps_cotisation(Variable): @@ -31,6 +31,21 @@ class cnrps_duree_assurance_annuelle(Variable): definition_period = YEAR label = "Durée d'assurance (en trimestres validés l'année considérée)" +class cnrps_eligible(Variable): + value_type = bool + entity = Individu + label = "L'individu est éligible à une pension CNRPS" + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('cnrps_duree_assurance', period=period) + salaire_de_reference = individu('cnrps_salaire_de_reference', period=period) + age = individu('age', period=period) + cnrps = parameters(period).retraite.cnrps + duree_de_service_minimale_accomplie = duree_assurance > 4 * cnrps.duree_de_service_minimale + critere_age_verifie = age >= cnrps.age_legal.civil.cadre_commun + return duree_de_service_minimale_accomplie * critere_age_verifie * (salaire_de_reference > 0) + class cnrps_liquidation_date(Variable): value_type = date entity = Individu @@ -38,81 +53,69 @@ class cnrps_liquidation_date(Variable): label = 'Date de liquidation' default_value = date(2250, 12, 31) -class cnrps_majoration_duree_assurance(Variable): - value_type = float +class cnrps_majoration_pension(Variable): + value_type = int entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance" - - def formula(individu, period): - return individu('cnrps_majoration_duree_assurance_enfant', period) + individu('cnrps_majoration_duree_assurance_autre', period) + definition_period = MONTH + label = 'Majoration de pension' -class cnrps_majoration_duree_assurance_autre(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" + def formula(individu, period, parameters): + NotImplementedError -class cnrps_majoration_pension(Variable): +class cnrps_pension(Variable): value_type = float entity = Individu definition_period = YEAR - label = 'Majoration de pension' + label = 'Pension' -class cnrps_majoration_pension_au_31_decembre(Variable): + def formula(individu, period): + pension_brute = individu('cnrps_pension_brute', period) + eligible = individu('cnrps_eligible', period) + try: + pension_minimale = individu('cnrps_pension_minimale', period) + except VariableNotFoundError: + pension_minimale = 0 + try: + pension_maximale = individu('cnrps_pension_maximale', period) + except (VariableNotFoundError, NotImplementedError): + return max_(pension_brute, pension_minimale) + return eligible * min_(pension_maximale, max_(pension_brute, pension_minimale)) + +class cnrps_pension_brute(Variable): value_type = float entity = Individu definition_period = YEAR - label = 'Majoration de pension au 31 décembre' + label = 'Pension brute' def formula(individu, period, parameters): - annee_de_liquidation = individu('cnrps_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(annee_de_liquidation > period.start.year): - return individu.empty_array() - last_year = period.last_year - majoration_pension_au_31_decembre_annee_precedente = individu('cnrps_majoration_pension_au_31_decembre', last_year) - revalorisation = parameters(period).cnrps.revalorisation_pension_au_31_decembre - majoration_pension = individu('cnrps_majoration_pension', period) - return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) + taux_de_liquidation = individu('cnrps_taux_de_liquidation', period) + salaire_de_reference = individu('cnrps_salaire_de_reference', period) + return (taux_de_liquidation * salaire_de_reference,) -class cnrps_pension(Variable): +class cnrps_pension_maximale(Variable): value_type = float + default_value = np.inf entity = Individu - label = 'Pension des affiliés au régime des salariés non agricoles' definition_period = YEAR + label = 'Pension maximale' def formula(individu, period, parameters): - duree_assurance = individu('cnrps_duree_assurance', period=period) - salaire_reference = individu('cnrps_salaire_de_reference', period=period) - age = individu('age', period=period) - cnrps = parameters(period).retraite.cnrps - taux_annuite_base = cnrps.taux_annuite_base - taux_annuite_supplementaire = cnrps.taux_annuite_supplementaire - duree_stage = cnrps.stage_derog - age_eligible = cnrps.age_dep_anticip - periode_remplacement_base = cnrps.periode_remplacement_base - plaf_taux_pension = cnrps.plaf_taux_pension - smig = parameters(period).marche_travail.smig_48h - pension_min_sup = cnrps.pension_minimale.sup - pension_min_inf = cnrps.pension_minimale.inf - stage = duree_assurance > 4 * duree_stage - pension_minimale = stage * pension_min_sup + not_(stage) * pension_min_inf - montant = pension_generique(duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension) - eligibilite_age = age > age_eligible - eligibilite = stage * eligibilite_age * (salaire_reference > 0) - montant_pension_percu = max_(montant, pension_minimale * smig) - return eligibilite * montant_pension_percu + NotImplementedError -class cnrps_pension_brute(Variable): +class cnrps_pension_minimale(Variable): value_type = float + default_value = 0 entity = Individu definition_period = YEAR - label = 'Pension brute' + label = 'Pension minimale' def formula(individu, period, parameters): - taux_de_liquidation = individu('cnrps_taux_de_liquidation', period) - salaire_de_reference = individu('cnrps_salaire_de_reference', period) - return (taux_de_liquidation * salaire_de_reference,) + cnrps = parameters(period).retraite.cnrps + pension_minimale = cnrps.pension_minimale + duree_de_service_minimale = cnrps.duree_de_service_minimale + smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel + duree_assurance = individu('cnrps_duree_assurance', period) + return apply_thresholds(duree_assurance / 4, [pension_minimale.duree_service_allocation_vieillesse, duree_de_service_minimale], [0, pension_minimale.allocation_vieillesse * smig_annuel, pension_minimale.minimum_garanti * smig_annuel]) class cnrps_pension_servie(Variable): value_type = float diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index 7033e70..3ac1739 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -1,4 +1,5 @@ """Abstract regimes definition.""" +import numpy as np from openfisca_core.model_api import * from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu @@ -32,6 +33,15 @@ class rsa_duree_assurance_annuelle(Variable): definition_period = YEAR label = "Durée d'assurance (en trimestres validés l'année considérée)" +class rsa_eligible(Variable): + value_type = bool + entity = Individu + label = "L'individu est éligible à une pension" + definition_period = YEAR + + def formula(individu, period, parameters): + NotImplementedError + class rsa_liquidation_date(Variable): value_type = date entity = Individu @@ -39,42 +49,14 @@ class rsa_liquidation_date(Variable): label = 'Date de liquidation' default_value = date(2250, 12, 31) -class rsa_majoration_duree_assurance(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance" - - def formula(individu, period): - return individu('rsa_majoration_duree_assurance_enfant', period) + individu('rsa_majoration_duree_assurance_autre', period) - -class rsa_majoration_duree_assurance_autre(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" - class rsa_majoration_pension(Variable): - value_type = float + value_type = int entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Majoration de pension' -class rsa_majoration_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Majoration de pension au 31 décembre' - def formula(individu, period, parameters): - annee_de_liquidation = individu('rsa_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(annee_de_liquidation > period.start.year): - return individu.empty_array() - last_year = period.last_year - majoration_pension_au_31_decembre_annee_precedente = individu('rsa_majoration_pension_au_31_decembre', last_year) - revalorisation = parameters(period).rsa.revalorisation_pension_au_31_decembre - majoration_pension = individu('rsa_majoration_pension', period) - return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) + NotImplementedError class rsa_pension(Variable): value_type = float @@ -112,6 +94,25 @@ def formula(individu, period, parameters): salaire_de_reference = individu('rsa_salaire_de_reference', period) return (taux_de_liquidation * salaire_de_reference,) +class rsa_pension_maximale(Variable): + value_type = float + default_value = np.inf + entity = Individu + definition_period = YEAR + label = 'Pension maximale' + + def formula(individu, period, parameters): + NotImplementedError + +class rsa_pension_minimale(Variable): + value_type = float + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + NotImplementedError + class rsa_pension_servie(Variable): value_type = float entity = Individu diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index d17e12c..f6676a6 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -1,4 +1,5 @@ """Abstract regimes definition.""" +import numpy as np from openfisca_core.model_api import * from openfisca_core.errors.variable_not_found_error import VariableNotFoundError from openfisca_tunisia_pension.entities import Individu @@ -6,9 +7,8 @@ from openfisca_core.model_api import * from openfisca_tunisia_pension.entities import Individu from openfisca_tunisia_pension.regimes.regime import AbstractRegimeEnAnnuites -from numpy import apply_along_axis, logical_not as not_, maximum as max_, vstack +from numpy import apply_along_axis, vstack from openfisca_tunisia_pension.tools import make_mean_over_largest -from openfisca_tunisia_pension.variables.helpers import pension_generique class rsna_RSNATypesRaisonDepartAnticipe(Enum): __order__ = 'non_concerne licenciement_economique usure_prematuree_organisme mere_3_enfants convenance_personnelle' @@ -39,6 +39,21 @@ class rsna_duree_assurance_annuelle(Variable): definition_period = YEAR label = "Durée d'assurance (en trimestres validés l'année considérée)" +class rsna_eligible(Variable): + value_type = bool + entity = Individu + label = "L'individu est éligible à une pension CNRPS" + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('rsna_duree_assurance', period=period) + salaire_de_reference = individu('rsna_salaire_de_reference', period=period) + age = individu('age', period=period) + rsna = parameters(period).retraite.rsna + duree_stage_accomplie = duree_assurance > 4 * rsna.stage_requis + critere_age_verifie = age >= rsna.age_legal + return duree_stage_accomplie * critere_age_verifie * (salaire_de_reference > 0) + class rsna_liquidation_date(Variable): value_type = date entity = Individu @@ -46,70 +61,33 @@ class rsna_liquidation_date(Variable): label = 'Date de liquidation' default_value = date(2250, 12, 31) -class rsna_majoration_duree_assurance(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance" - - def formula(individu, period): - return individu('rsna_majoration_duree_assurance_enfant', period) + individu('rsna_majoration_duree_assurance_autre', period) - -class rsna_majoration_duree_assurance_autre(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = "Majoration de durée d'assurance autre que celle attribuée au motif des enfants" - class rsna_majoration_pension(Variable): - value_type = float + value_type = int entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Majoration de pension' -class rsna_majoration_pension_au_31_decembre(Variable): - value_type = float - entity = Individu - definition_period = YEAR - label = 'Majoration de pension au 31 décembre' - def formula(individu, period, parameters): - annee_de_liquidation = individu('rsna_liquidation_date', period).astype('datetime64[Y]').astype(int) + 1970 - if all(annee_de_liquidation > period.start.year): - return individu.empty_array() - last_year = period.last_year - majoration_pension_au_31_decembre_annee_precedente = individu('rsna_majoration_pension_au_31_decembre', last_year) - revalorisation = parameters(period).rsna.revalorisation_pension_au_31_decembre - majoration_pension = individu('rsna_majoration_pension', period) - return revalorise(majoration_pension_au_31_decembre_annee_precedente, majoration_pension, annee_de_liquidation, revalorisation, period) + NotImplementedError class rsna_pension(Variable): value_type = float entity = Individu - label = 'Pension des affiliés au régime des salariés non agricoles' definition_period = YEAR + label = 'Pension' - def formula(individu, period, parameters): - duree_assurance = individu('rsna_duree_assurance', period=period) - salaire_reference = individu('rsna_salaire_reference', period=period) - age = individu('age', period=period) - rsna = parameters(period).retraite.rsna - taux_annuite_base = rsna.taux_annuite_base - taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - age_eligible = rsna.age_dep_anticip - periode_remplacement_base = rsna.periode_remplacement_base - plaf_taux_pension = rsna.plaf_taux_pension - smig = parameters(period).marche_travail.smig_48h - pension_min_sup = rsna.pension_minimale.sup - pension_min_inf = rsna.pension_minimale.inf - duree_stage = rsna.stage_derog - stage = duree_assurance > 4 * duree_stage - pension_minimale = stage * pension_min_sup + not_(stage) * pension_min_inf - montant = pension_generique(duree_assurance, salaire_reference, taux_annuite_base, taux_annuite_supplementaire, duree_stage, age_eligible, periode_remplacement_base, plaf_taux_pension) - eligibilite_age = age > age_eligible - eligibilite = stage * eligibilite_age * (salaire_reference > 0) - montant_pension_percu = max_(montant, pension_minimale * smig) - return eligibilite * montant_pension_percu + def formula(individu, period): + pension_brute = individu('rsna_pension_brute', period) + eligible = individu('rsna_eligible', period) + try: + pension_minimale = individu('rsna_pension_minimale', period) + except VariableNotFoundError: + pension_minimale = 0 + try: + pension_maximale = individu('rsna_pension_maximale', period) + except (VariableNotFoundError, NotImplementedError): + return max_(pension_brute, pension_minimale) + return eligible * min_(pension_maximale, max_(pension_brute, pension_minimale)) class rsna_pension_brute(Variable): value_type = float @@ -124,6 +102,7 @@ def formula(individu, period, parameters): class rsna_pension_maximale(Variable): value_type = float + default_value = np.inf entity = Individu definition_period = YEAR label = 'Pension maximale' @@ -133,12 +112,17 @@ def formula(individu, period, parameters): class rsna_pension_minimale(Variable): value_type = float + default_value = 0 entity = Individu definition_period = YEAR label = 'Pension minimale' def formula(individu, period, parameters): - NotImplementedError + rsna = parameters(period).retraite.rsna + pension_minimale = rsna.pension_minimale + smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel + duree_assurance = individu('rsna_duree_assurance', period) + return apply_thresholds(duree_assurance / 4, [rsna.stage_derog, rsna.stage_requis], [0, pension_minimale.inf * smig_annuel, pension_minimale.sup * smig_annuel]) class rsna_pension_servie(Variable): value_type = float @@ -164,12 +148,6 @@ class rsna_salaire_de_base(Variable): set_input = set_input_divide_by_period class rsna_salaire_de_reference(Variable): - value_type = float - entity = Individu - definition_period = ETERNITY - label = 'Salaire de référence' - -class rsna_salaire_reference(Variable): value_type = float entity = Individu label = 'Salaires de référence du régime des salariés non agricoles' diff --git a/tests/formulas/cnrps/pension.noyaml b/tests/formulas/cnrps/pension.noyaml deleted file mode 100644 index e69de29..0000000 diff --git a/tests/formulas/cnrps/pension.yaml b/tests/formulas/cnrps/pension.yaml new file mode 100644 index 0000000..f4ecddd --- /dev/null +++ b/tests/formulas/cnrps/pension.yaml @@ -0,0 +1,36 @@ +- name: "3 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-4 + input: + cnrps_duree_assurance: 3 * 4 + cnrps_salaire_de_reference: 1000 + output: + cnrps_pension: 0 + + +- name: "7 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 7 * 4 + cnrps_salaire_de_reference: 1000 + output: + cnrps_pension_minimale: 0.5 * 235.04 * 12 + + +- name: "12 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 12 * 4 + output: + cnrps_pension_minimale: 0.5 * 235.04 * 12 + + +- name: "17 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 17 * 4 + output: + cnrps_pension_minimale: 0.66666 * 235.04 * 12 diff --git a/tests/formulas/cnrps/pension_minimale.yaml b/tests/formulas/cnrps/pension_minimale.yaml new file mode 100644 index 0000000..7eb63e1 --- /dev/null +++ b/tests/formulas/cnrps/pension_minimale.yaml @@ -0,0 +1,34 @@ +- name: "3 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-4 + input: + cnrps_duree_assurance: 3 * 4 + output: + cnrps_pension_minimale: 0 + + +- name: "7 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 7 * 4 + output: + cnrps_pension_minimale: 0.5 * 235.04 * 12 + + +- name: "12 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 12 * 4 + output: + cnrps_pension_minimale: 0.5 * 235.04 * 12 + + +- name: "17 ans de trimetres CNRPS" + period: 2011 + absolute_error_margin: 1e-10 + input: + cnrps_duree_assurance: 17 * 4 + output: + cnrps_pension_minimale: 0.66666 * 235.04 * 12 diff --git a/tests/formulas/cnrps/cnrps_salaire_de_reference.yaml b/tests/formulas/cnrps/salaire_de_reference.yaml similarity index 100% rename from tests/formulas/cnrps/cnrps_salaire_de_reference.yaml rename to tests/formulas/cnrps/salaire_de_reference.yaml diff --git a/tests/formulas/rsna/rsna_pension.yaml b/tests/formulas/rsna/pension.yaml similarity index 96% rename from tests/formulas/rsna/rsna_pension.yaml rename to tests/formulas/rsna/pension.yaml index b75395b..3ade7ac 100644 --- a/tests/formulas/rsna/rsna_pension.yaml +++ b/tests/formulas/rsna/pension.yaml @@ -46,5 +46,5 @@ 2013: 12000 2014: 12000 output: - rsna_salaire_reference: 12000 + rsna_salaire_de_reference: 12000 rsna_pension: 5400 diff --git a/tests/test_tools.py b/tests/test_tools.py index dd17b13..93e2c79 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -11,7 +11,7 @@ def test_mean_over_consecutive_largest(): array = np.array([1] * 5 + [100] * 5 + [1000] * 5).astype(np.float32) - print(array) + assert mean_over_k_consecutive_largest(array, 1) == 1000 assert mean_over_k_consecutive_largest(array, 3) == 1000 assert mean_over_k_consecutive_largest(array, 5) == 1000 From 8f09d079e589e1efd238472cf3e0acff5ff76525 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Thu, 21 Nov 2024 14:52:35 +0100 Subject: [PATCH 22/24] Clean --- openfisca_tunisia_pension/regimes/rsna.py | 49 +---------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 00fa636..357b6d3 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -33,7 +33,6 @@ class RSNATypesRaisonDepartAnticipe(Enum): # A partir de 55 ans : convenance_personnelle = 'Convenance personnelle, avec 360 mois de cotisations (120 trimestres)' - class eligible(Variable): value_type = bool entity = Individu @@ -45,56 +44,10 @@ def formula(individu, period, parameters): salaire_de_reference = individu('regime_name_salaire_de_reference', period = period) age = individu('age', period = period) rsna = parameters(period).retraite.regime_name - duree_stage_accomplie = duree_assurance > 4 * rsna.stage_requis + duree_stage_accomplie = duree_assurance > 4 * rsna.stage_requis critere_age_verifie = age >= rsna.age_legal return duree_stage_accomplie * critere_age_verifie * (salaire_de_reference > 0) - # class pension(Variable): - # value_type = float - # entity = Individu - # label = 'Pension des affiliés au régime des salariés non agricoles' - # definition_period = YEAR - - # def formula(individu, period, parameters): - # duree_assurance = individu('regime_name_duree_assurance', period = period) - # salaire_reference = individu('regime_name_salaire_reference', period = period) - # age = individu('age', period = period) - - # rsna = parameters(period).retraite.regime_name - # taux_annuite_base = rsna.taux_annuite_base - # taux_annuite_supplementaire = rsna.taux_annuite_supplementaire - # age_eligible = rsna.age_dep_anticip - # periode_remplacement_base = rsna.periode_remplacement_base - # plaf_taux_pension = rsna.plaf_taux_pension - # smig = parameters(period).marche_travail.smig_48h - - # pension_min_sup = rsna.pension_minimale.sup - # pension_min_inf = rsna.pension_minimale.inf - - # duree_stage = rsna.stage_derog - # stage = duree_assurance > 4 * duree_stage - # pension_minimale = ( - # stage * pension_min_sup + not_(stage) * pension_min_inf - # ) - # montant = pension_generique( - # duree_assurance, - # salaire_reference, - # taux_annuite_base, - # taux_annuite_supplementaire, - # duree_stage, - # age_eligible, - # periode_remplacement_base, - # plaf_taux_pension, - # ) - # # eligibilite - # eligibilite_age = age > age_eligible - # eligibilite = stage * eligibilite_age * (salaire_reference > 0) - # # plafonnement - # montant_pension_percu = max_(montant, pension_minimale * smig) - # return eligibilite * montant_pension_percu - - - class pension_minimale(Variable): value_type = float default_value = 0 # Pas de pension minimale par défaut, elle est à zéro From fa65f6d2450f7327b837145a00790cdb0edbcf30 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Thu, 21 Nov 2024 15:00:02 +0100 Subject: [PATCH 23/24] lint yaml --- tests/formulas/cnrps/salaire_de_reference.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/formulas/cnrps/salaire_de_reference.yaml b/tests/formulas/cnrps/salaire_de_reference.yaml index 39dc4c7..885347c 100644 --- a/tests/formulas/cnrps/salaire_de_reference.yaml +++ b/tests/formulas/cnrps/salaire_de_reference.yaml @@ -1,4 +1,4 @@ -- name: "Individu salarié 12000 DT par an toute sa carrière sauf accélération en fin" +- name: "Fonctionnaires 12000 DT par an avec accélération en fin" period: 2014 absolute_error_margin: 0.5 input: @@ -49,7 +49,7 @@ cnrps_salaire_de_reference: 12500 -- name: "Individu fonctionnaire 2 années à 20000 supérieure à tous le reste de sa carrière" +- name: "Fonctionnaire 2 années à 20000 supérieures au reste de sa carrière" period: 2014 absolute_error_margin: 0.5 input: From b76726533637e614d615fd3caf57cb916166ee27 Mon Sep 17 00:00:00 2001 From: Mahdi Ben Jelloul Date: Fri, 13 Dec 2024 12:19:56 +0100 Subject: [PATCH 24/24] Fix tests --- .../civil/enseignants_du_superieur.yaml | 11 ++- .../retraite/cnrps/age_legal/civil/index.yaml | 7 ++ .../retraite/cnrps/age_legal/index.yaml | 6 ++ .../parameters/retraite/rsna/index.yaml | 11 ++- .../retraite/rsna/pension_minimale/inf.yaml | 2 +- .../retraite/rsna/pension_minimale/sup.yaml | 2 +- openfisca_tunisia_pension/regimes/cnrps.py | 99 ++++++++++--------- openfisca_tunisia_pension/regimes/regime.py | 2 +- openfisca_tunisia_pension/regimes/rsna.py | 2 +- openfisca_tunisia_pension/variables/cnrps.py | 15 ++- openfisca_tunisia_pension/variables/rsa.py | 2 +- openfisca_tunisia_pension/variables/rsna.py | 4 +- pyproject.toml | 2 +- 13 files changed, 101 insertions(+), 64 deletions(-) create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/index.yaml create mode 100644 openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/index.yaml diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml index 473d396..1524ab0 100644 --- a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/enseignants_du_superieur.yaml @@ -1,10 +1,13 @@ -description: Age légal de de départ à la retraite pour certains enseignants du supérieur +description: Age de départ à la retraite pour certains enseignants du supérieur values: - 1959-02-01: - value: 60 + 2019-04-01: + value: 65 metadata: unit: year documentation: |- + Loi n° 2009-20 du 13 avril 2009, portant dispositions exceptionnelles relatives à la retraite des professeurs de l’enseignement supérieur Les enseignants concernés sont: - - les professeurs de l’enseignement supérieur et les maîtres de conférences de l’enseignement supérieur aux établissements universitaires et aux établissements de recherche scientifique civils et militaires, + - les professeurs de l’enseignement supérieur et les maîtres de conférences de l’enseignement supérieur rattachés aux établissements universitaires et aux établissements de recherche scientifique civils et militaires - les professeurs hospitalo-universitaires et les maîtres de conférences agrégés hospitalo-universitaires + + Néanmoins, ils peuvent être maintenus en activité par décret jusqu’à l’âge de soixante-dix (70) ans au maximum. diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/index.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/index.yaml new file mode 100644 index 0000000..f852b9b --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/civil/index.yaml @@ -0,0 +1,7 @@ +description: Âge de départ à la retraite dans le service public civil +metadata: + short_label: Âge de départ des civils + order: + - cadre_commun + - cadre_actifs + - ensegnants_du_superieur diff --git a/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/index.yaml b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/index.yaml new file mode 100644 index 0000000..879694e --- /dev/null +++ b/openfisca_tunisia_pension/parameters/retraite/cnrps/age_legal/index.yaml @@ -0,0 +1,6 @@ +description: Âge de départ à la retraite +metadata: + short_label: Âge de départ + order: + - civil + - militaire diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/index.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/index.yaml index 25c6e14..697be71 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/index.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/index.yaml @@ -1 +1,10 @@ -description: Régime des salariés non agricoles +description: Régime des salariés non agricoles (RSNA) +metadata: + short_label: RSNA + order: + - age_legal + - age_dep_anticipe + - stage_requis + - stage_derog + - bareme_annuite + - pension_minimale diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml index 56c1af8..5df32b9 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/inf.yaml @@ -4,4 +4,4 @@ values: 1974-01-01: value: 0.5 metadata: - unit: Smig + unit: smig diff --git a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml index 6c6433d..e258635 100644 --- a/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml +++ b/openfisca_tunisia_pension/parameters/retraite/rsna/pension_minimale/sup.yaml @@ -4,4 +4,4 @@ values: 1974-01-01: value: 0.66666 metadata: - unit: Smig + unit: smig diff --git a/openfisca_tunisia_pension/regimes/cnrps.py b/openfisca_tunisia_pension/regimes/cnrps.py index 189400b..305262f 100644 --- a/openfisca_tunisia_pension/regimes/cnrps.py +++ b/openfisca_tunisia_pension/regimes/cnrps.py @@ -58,6 +58,49 @@ class RegimeCNRPS(AbstractRegimeEnAnnuites): variable_prefix = 'cnrps' parameters_prefix = 'cnrps' + class eligible(Variable): + value_type = bool + entity = Individu + label = "L'individu est éligible à une pension CNRPS" + definition_period = YEAR + + def formula(individu, period, parameters): + duree_assurance = individu('regime_name_duree_assurance', period = period) + salaire_de_reference = individu('regime_name_salaire_de_reference', period = period) + age = individu('age', period = period) + cnrps = parameters(period).retraite.regime_name + duree_de_service_minimale_accomplie = duree_assurance > 4 * cnrps.duree_de_service_minimale + critere_age_verifie = age >= cnrps.age_legal.civil.cadre_commun + return duree_de_service_minimale_accomplie * critere_age_verifie * (salaire_de_reference > 0) + + class pension_minimale(Variable): + value_type = float + default_value = 0 # Pas de pension minimale par défaut, elle est à zéro + entity = Individu + definition_period = YEAR + label = 'Pension minimale' + + def formula(individu, period, parameters): + cnrps = parameters(period).retraite.regime_name + pension_minimale = cnrps.pension_minimale + duree_de_service_minimale = cnrps.duree_de_service_minimale + # TODO Annualiser le Smig + smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel + duree_assurance = individu('regime_name_duree_assurance', period) + return apply_thresholds( + duree_assurance / 4, + [ + pension_minimale.duree_service_allocation_vieillesse, + duree_de_service_minimale, + ], + [ + 0, + pension_minimale.allocation_vieillesse * smig_annuel, + pension_minimale.minimum_garanti * smig_annuel, + ] + + ) + class salaire_de_reference_calcule_sur_demande(Variable): value_type = bool entity = Individu @@ -79,11 +122,11 @@ def formula(individu, period): moyenne_2_salaires_plus_eleves = apply_along_axis( mean_over_largest, axis = 0, - arr = vstack([individu('regime_name_salaire_de_base', period = year) for year in range(period.start.year, period.start.year - n, -1)]), + arr = vstack([individu('regime_name_salaire_de_base', period = year, options = [ADD]) for year in range(period.start.year, period.start.year - n, -1)]), ) p = 3 moyenne_3_derniers_salaires = sum( - individu('regime_name_salaire_de_base', period = year) + individu('regime_name_salaire_de_base', period = year, options = [ADD]) for year in range(period.start.year, period.start.year - p, -1) ) / p @@ -94,55 +137,15 @@ def formula(individu, period): ) return salaire_refererence - # class pension_maximale(Variable): - # value_type = float - # default_value = np.inf # Pas de pension maximale par défaut - # entity = Individu - # definition_period = YEAR - # label = 'Pension maximale' - - # def formula(individu, period, parameters): - # NotImplementedError - - class pension_minimale(Variable): + class bonifications(Variable): value_type = float - default_value = 0 # Pas de pension minimale par défaut, elle est à zéro entity = Individu + label = 'Bonifications' definition_period = YEAR - label = 'Pension minimale' - def formula(individu, period, parameters): - cnrps = parameters(period).retraite.regime_name - pension_minimale = cnrps.pension_minimale - duree_de_service_minimale = cnrps.duree_de_service_minimale - # TODO Annualiser le Smig - smig_annuel = 12 * parameters(period).marche_travail.smig_40h_mensuel - duree_assurance = individu('regime_name_duree_assurance', period) - return apply_thresholds( - duree_assurance / 4, - [ - pension_minimale.duree_service_allocation_vieillesse, - duree_de_service_minimale, - ], - [ - 0, - pension_minimale.allocation_vieillesse * smig_annuel, - pension_minimale.minimum_garanti * smig_annuel, - ] + def formula(individu, period): + return ( + individu('bonfication_retraite_pour_limite_d_age', period), + + individu('bonfication_retraite_avant_age_legal', period) ) - - class eligible(Variable): - value_type = bool - entity = Individu - label = "L'individu est éligible à une pension CNRPS" - definition_period = YEAR - - def formula(individu, period, parameters): - duree_assurance = individu('regime_name_duree_assurance', period = period) - salaire_de_reference = individu('regime_name_salaire_de_reference', period = period) - age = individu('age', period = period) - cnrps = parameters(period).retraite.regime_name - duree_de_service_minimale_accomplie = duree_assurance > 4 * cnrps.duree_de_service_minimale - critere_age_verifie = age >= cnrps.age_legal.civil.cadre_commun - return duree_de_service_minimale_accomplie * critere_age_verifie * (salaire_de_reference > 0) diff --git a/openfisca_tunisia_pension/regimes/regime.py b/openfisca_tunisia_pension/regimes/regime.py index ab7db87..6eae8f3 100644 --- a/openfisca_tunisia_pension/regimes/regime.py +++ b/openfisca_tunisia_pension/regimes/regime.py @@ -189,7 +189,7 @@ def formula(individu, period, parameters): class salaire_de_base(Variable): value_type = float entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Salaire de base (salaire brut)' set_input = set_input_divide_by_period diff --git a/openfisca_tunisia_pension/regimes/rsna.py b/openfisca_tunisia_pension/regimes/rsna.py index 357b6d3..d7c2b3f 100644 --- a/openfisca_tunisia_pension/regimes/rsna.py +++ b/openfisca_tunisia_pension/regimes/rsna.py @@ -92,7 +92,7 @@ def formula(individu, period): mean_over_largest, axis = 0, arr = vstack([ - individu('regime_name_salaire_de_base', period = year) + individu('regime_name_salaire_de_base', period = year, options = [ADD]) for year in range(period.start.year, period.start.year - n, -1) ]), ) diff --git a/openfisca_tunisia_pension/variables/cnrps.py b/openfisca_tunisia_pension/variables/cnrps.py index 2576439..207a7d6 100644 --- a/openfisca_tunisia_pension/variables/cnrps.py +++ b/openfisca_tunisia_pension/variables/cnrps.py @@ -10,6 +10,15 @@ from numpy import apply_along_axis, vstack from openfisca_tunisia_pension.tools import make_mean_over_consecutive_largest +class cnrps_bonifications(Variable): + value_type = float + entity = Individu + label = 'Bonifications' + definition_period = YEAR + + def formula(individu, period): + return (individu('bonfication_retraite_pour_limite_d_age', period), +individu('bonfication_retraite_avant_age_legal', period)) + class cnrps_cotisation(Variable): value_type = float entity = Individu @@ -136,7 +145,7 @@ def formula(individu, period, parameters): class cnrps_salaire_de_base(Variable): value_type = float entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Salaire de base (salaire brut)' set_input = set_input_divide_by_period @@ -151,9 +160,9 @@ def formula(individu, period): n = 40 k = 2 mean_over_largest = make_mean_over_consecutive_largest(k) - moyenne_2_salaires_plus_eleves = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) + moyenne_2_salaires_plus_eleves = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('cnrps_salaire_de_base', period=year, options=[ADD]) for year in range(period.start.year, period.start.year - n, -1)])) p = 3 - moyenne_3_derniers_salaires = sum((individu('cnrps_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - p, -1))) / p + moyenne_3_derniers_salaires = sum((individu('cnrps_salaire_de_base', period=year, options=[ADD]) for year in range(period.start.year, period.start.year - p, -1))) / p salaire_refererence = where(individu('cnrps_salaire_de_reference_calcule_sur_demande', period), moyenne_2_salaires_plus_eleves, moyenne_3_derniers_salaires) return salaire_refererence diff --git a/openfisca_tunisia_pension/variables/rsa.py b/openfisca_tunisia_pension/variables/rsa.py index 3ac1739..fd5051b 100644 --- a/openfisca_tunisia_pension/variables/rsa.py +++ b/openfisca_tunisia_pension/variables/rsa.py @@ -132,7 +132,7 @@ def formula(individu, period, parameters): class rsa_salaire_de_base(Variable): value_type = float entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Salaire de base (salaire brut)' set_input = set_input_divide_by_period diff --git a/openfisca_tunisia_pension/variables/rsna.py b/openfisca_tunisia_pension/variables/rsna.py index f6676a6..e67bf40 100644 --- a/openfisca_tunisia_pension/variables/rsna.py +++ b/openfisca_tunisia_pension/variables/rsna.py @@ -143,7 +143,7 @@ def formula(individu, period, parameters): class rsna_salaire_de_base(Variable): value_type = float entity = Individu - definition_period = YEAR + definition_period = MONTH label = 'Salaire de base (salaire brut)' set_input = set_input_divide_by_period @@ -157,7 +157,7 @@ def formula(individu, period): k = 10 mean_over_largest = make_mean_over_largest(k=k) n = 40 - salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('rsna_salaire_de_base', period=year) for year in range(period.start.year, period.start.year - n, -1)])) + salaire_refererence = apply_along_axis(mean_over_largest, axis=0, arr=vstack([individu('rsna_salaire_de_base', period=year, options=[ADD]) for year in range(period.start.year, period.start.year - n, -1)])) return salaire_refererence class rsna_taux_de_liquidation(Variable): diff --git a/pyproject.toml b/pyproject.toml index cb483b5..d05e1ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ requires-python = ">= 3.9" dependencies = [ "numba>=0.54,<1.0.0", 'numpy >=1.24.3, <2', - 'openfisca-core[web-api] >=41.5.0, <41.5.3', + 'openfisca-core[web-api] >=43.0.0, <44.0.0', 'scipy >= 0.12', ]