Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intégration du calcul de la rente d'accident du travail #1270

Merged
merged 18 commits into from
Mar 20, 2019
Merged

Conversation

mtifarine
Copy link
Contributor

@mtifarine mtifarine commented Feb 7, 2019

  • Évolution du système socio-fiscal.

  • Périodes concernées : toutes.

  • Zones impactées :

    • model/revenus/remplacement/rente_accident_travail.
    • parameters/accident_travail/rente/salaire_net/bareme.
    • parameters/accident_travail/rente/salaire_net/salaire_minimum.
    • parameters/accident_travail/rente/taux/bareme.
    • parameters/accident_travail/rente/taux/capital_representatif.
    • parameters/accident_travail/rente/taux/indemnite_accident_travail.
    • parameters/accident_travail/rente/taux/pcrtp.
    • parameters/accident_travail/rente/taux/taux_minimum.
  • Détails :

    • Intégration de la ressource rente_accident_travail.
    • Ajoute les variables:
      • rente_accident_travail_salarie
      • rente_accident_travail_exploitant_agricole
      • indemnite_accident_travail
      • rente_accident_travail_base
      • demande_rachat
      • rente_accident_travail_apres_rachat
      • rente_accident_travail_rachat
      • pcrtp_nombre_actes_assistance
      • pcrtp
      • rente_accident_travail_salaire_utile

rente_at = parameters(period).accident_travail.rente.taux
age = individu('age', period)
rente_accident_travail_rachat = individu('rente_accident_travail_rachat', period)
conversion_rente_capetal = rente_at.capital_representatif[age]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conversion_rente_capetal -> conversion_rente_capital

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morendil Je travaille sur le débogage :d .

@mtifarine mtifarine added the contrib:msa Identification des sujets MSA label Feb 7, 2019
class demande_rachat(Variable):
value_type = bool
entity = Individu
label = u"Le victime demande le rachat partiel de la rente"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le victime -> La victime

@Morendil
Copy link
Contributor

Morendil commented Feb 8, 2019

Merci @mtifarine! J'ai indiqué encore une coquille, mais pas encore commencé une relecture en détail. Est-ce que tu as terminé le travail sur cette PR et est-elle prête pour relecture ?

@mtifarine
Copy link
Contributor Author

Oui @Morendil, tu peux commencer la relecture.

Copy link
Contributor

@Morendil Morendil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci pour ce travail qui a certainement demandé pas mal d'analyse des textes.

J'ai un certain nombre de remarques et de changements qui me semblent s'imposer, toutefois il est possible que j'ai mal interprété le code ou les textes référencés, n'hésite pas à revenir vers moi si nécessaire.

@@ -6,6 +6,186 @@
class rente_accident_travail(Variable):
value_type = float
entity = Individu
label = u"Montant mensuel de la rente d’accident du travail"
label = u"Montant mensuel ou trimestriel de la rente d’accident du travail"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cette annotation prête à confusion. Le versement est mensuel ou trimestriel en fonction du taux d'incapacité, mais cette variation est sans conséquence pour le calcul effectué par OpenFisca qui devra bien être celui du montant mensuel, car la période de définition de la variable est le mois.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morendil
Exactement, le versement est mensuel ou trimestriel en fonction du taux d'incapacité. Donc, je ne sais pas si, dans ce cas, on calcule le montant mensuel au lieu de calculer le montant du versement ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oui on calcule le montant mensuel.

rente_accident_travail_salarie = individu('rente_accident_travail_salarie', period)
rente_accident_travail_exploitant_agricole = individu('rente_accident_travail_exploitant_agricole', period)

return max_(rente_accident_travail_salarie, rente_accident_travail_exploitant_agricole)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je ne comprends pas bien pourquoi on utilise ici le max de ces deux calculs, alors qu'on s'attendrait à voir un aiguillage en fonction du statut.

Je suppose que c'est parce qu'on n'a pas modélisé le statut d'exploitant agricole, qui n'est représenté par aucune variable existante; mais cela ne me semble pas très satisfaisant de prendre le maximum ici et d'utiliser tns_benefice_exploitant_agricole comme un indicateur du statut dans la formule du cas agricole.

Si on utilise tns_benefice_exploitant_agricole comme un indicateur de statut, il vaut mieux l'exploiter ici comme condition d'aiguillage au lieu de prendre le max.

Une solution plus pérenne consisterait à introduire une variable renseignant sur le statut d'activité de la personne, mais c'est un débat en cours. Pour l'instant je recommande donc la solution ci-dessus.

montant_rente_accident_travail = where(rente_accident_travail_rachat != 0, rente_accident_travail_apres_rachat,
rente_accident_travail_base)
rente_accident_travail_verse = select([taux_incapacite < 0.1, taux_incapacite < 0.5, taux_incapacite >= 0.5],
[0, montant_rente_accident_travail / 4, montant_rente_accident_travail / 12])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cet aiguillage ne me semble pas correct, pour les raisons évoquées dans la remarque sur le label de rente_accident_travail. La périodicité du versement n'a pas d'incidence sur le montant qui doit rester mensuel pour correspondre à la définition de la variable.

montant_rente_accident_travail = where(rente_accident_travail_rachat != 0, rente_accident_travail_apres_rachat,
rente_accident_travail_base)
rente_accident_travail_verse = select([taux_incapacite < 0.3, taux_incapacite >= 0.3],
[0, montant_rente_accident_travail / 12]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Même remarque que ci-dessus quant à la périodicité et au montant.

def formula(individu, period, parameters):
indem_at = parameters(period).accident_travail.rente.taux
taux_incapacite = individu('taux_accident_travail', period)
return select(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plutôt qu'un select il vaudrait mieux implémenter cela sous la forme d'un barème de type SingleAmountTaxScale (cf. #1258 pour un exemple d'utilisation).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morendil pour un barème de type SingleAmountTaxScale, les thresholds doivent être des entiers naturels pour donner les valeurs correctes?
J'ai testé les thresholds du barème avec des valeurs décimales [0.01, 0.02 , ..., 0.1] mais cela ne ne donne pas le bon résultat, par contre, lorsque je les ai remplacés par des valeurs entières [1, 2, ...,10], ça donne le bon résultat.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mtifarine Cela semble être dû à un bug dans Numpy… C'est très étonnant, 99% des cas dans ma carrière ou j'ai invoqué "un bug dans le compilateur" j'avais tort, mais le cas de test semble indiscutable :

>>> import numpy as np
>>> np.digitize([7], np.array([-np.inf,0.,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,np.inf])*100)
array([8])
>>> np.digitize([6], np.array([-np.inf,0.,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,np.inf])*100)
array([8])

Malheureusement, ce bug ne semble pas être corrigé dans les versions plus récentes que celle que nous utilisons.

Je pense que ta solution contourne élégamment le problème!

rente_accident_travail: 1216.67
pcrtp: 559.26

- name: "Cas 6: Victime non salarié agricol, taux d'IPP < 30%, pas de rente ou d'indemnité"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agricol -> agricole

@@ -0,0 +1,204 @@
- name: "Cas 1: Victime salarié, taux d'IPP < 10%, versement d'une indemnité en capital"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

salarié -> salariée

description: Salaire minimum des rentes
reference: "https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000006073189&idArticle=LEGIARTI000006743072&dateTexte=&categorieLien=cid"
unit: currency
values:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On trouve un historique plus complet de ces valeurs ici: http://www.securite-sociale.fr/7-Montants-des-prestations-accidents-du-travail-a-compter-du-1er-avril-2016-indemnisation-de-l

Si tu veux bien les intégrer ça serait top, à défaut ça serait bien de conserver ce lien en commentaire

reference: "https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000006073189&idArticle=LEGIARTI000006743072&dateTexte=&categorieLien=cid"
unit: currency
values:
1954-09-01:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ici ça me paraît compliqué de laisser une valeurs en francs sans préciser l'unité monétaire ! Je serais plutôt favorable à ce qu'on intègre les valeurs depuis 2002 et qu'on abandonne celles en francs.

salaire = max_(salaire_net, tns_benefice_exploitant_agricole)
salaire_net_base = max_(rente_at.salaire_net.salaire_minimum, salaire)

return rente_at.salaire_net.salaire_minimum * rente_at.salaire_net.bareme.calc(
Copy link
Contributor

@Morendil Morendil Feb 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Très bonne idée l'utilisation du barème ici!

@mtifarine Pas de changement demandé pour rente_accident_travail_salaire_utile, les remarques ci-dessous sont pour @sandcha pour amorcer une réflexion.

Je me demande si on peut encore améliorer la lisibilité de ce calcul, c'est dommage d'avoir ce max effectué ligne 188. Mais je crois qu'il faudrait une modification dans Core pour cela.

Idéalement on ferait porter tout le calcul sur le barème, en multipliant par salaire au lieu de multiplier par le paramètre "salaire minimum".

Si on avait un test pour cette variable, je m'attendrais à voir les valeurs suivantes; soit "U" la valeur de rente_accident_travail_salaire_utile pour janvier 2019 et "S" mon salaire pour l'année 2018:

  • si S est inférieur à 18520, alors U est 18520
  • si S est entre 18520 et 18520 * 2, alors U est égal à S
  • si S est entre 18520 * 2 et 18520 * 8, alors U est égal à 18520 * 2 + (S-18520 * 2)/3
  • si S est supérieur à 18520 * 8, alors U est égal à (18520 * 2)+(18520 * 8-18520 * 2)/3 soit 18520 * 4

Le problème est qu'on ne sait pas spécifier une tranche avec un minimum il me semble.

@Morendil
Copy link
Contributor

Morendil commented Mar 18, 2019

@mtifarine On fait la revue de cette PR avec @sandcha aujourd'hui, on reprend la main pour pousser éventuellement des commits d'amélioration à la marge (typos etc) et on te fait signe s'il y a quelque chose de plus substantiel à faire.

@Morendil Morendil force-pushed the msa_rente_at branch 3 times, most recently from 41e04fd to f7825ed Compare March 18, 2019 15:14
Copy link
Contributor

@sandcha sandcha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci @mtifarine !
Retour principal : besoin de mise à jour de parameters/accident_travail/rente/taux/capital_representatif

@@ -0,0 +1,22 @@
description: Barème utilisé pour la détermination de rente_accident_travail_salaire_utile (cf. formule)
reference: https://www.legifrance.gouv.fr/affichCodeArticle.do;jsessionid=7392B9902E4B974EAE8783FAF2D69849.tplgfr30s_1?idArticle=LEGIARTI000006750376&cidTexte=LEGITEXT000006073189&dateTexte=20180823
unit: currency
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unit: currency
metadata:
threshold_unit: /1
rate_unit: /1

@@ -0,0 +1,307 @@
description: Barème servant à la détermination du capital représentatif des rentes d'accidents du travail
reference: "https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000030308553&categorieLien=id"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il semble que ce texte ait été abrogé en faveur de cet arrêté du 19 décembre 2016 (en € 😍).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est l'expert qui nous a donné cette référence.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, que fait-on ? @mtifarine tu demandes l'avis de l'expert sur la base des nouvelles informations fournies par @sandcha ?

Copy link
Contributor Author

@mtifarine mtifarine Mar 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour info: @JenniferTelep

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sandcha, @Morendil
L'expert nous a dit que l'arrêté du 19 décembre 2016 concerne la faute inexcusable de l'employeur, et que le barème utilisé pour le versement d'une rente est bien celui de l'arrêté du 17 décembre 1954.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci @mtifarine pour l'info complémentaire ! Des informations erronées circulent à ce sujet, au point que certaines personnes ont porté l'affaire devant les tribunaux.

@JenniferTelep @MehdiBenHnin Lors de notre rencontre avec @ThibaultCCMSA fin 2018 j'avais évoqué une demande de notre part, qui nous permettrait je pense d'être plus efficace lors des revues de PR: est-ce que vous voudriez bien partager avec nous les fiches d'analyse produites par les experts métiers lorsque vous ouvrez un sujet ? Je fais l'hypothèse que ce type d'information fournie par les experts est présente dans la fiche d'analyse, et en avoir connaissance nous éviterait peut-être de remettre en question des éléments qui peuvent sembler surprenants mais sont en fait validés par l'expertise métier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morendil je m'avance peut-être, @JenniferTelep @MehdiBenHnin arrêtez moi si je dis une bêtise, mais il me semble que c'est bien ce qui est prévu à partir de maintenant pour toutes les prochaines demandes.
Nous créérons une issue au moment de commencer à travailler sur une tache et les fiches y seront associées.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frtomas Top, merci!


def formula(individu, period, parameters):
rente_at = parameters(period).accident_travail.rente.taux
age = max_(individu('age', period), 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As-tu rencontré un cas où l'âge était négatif/indéterminé (ce serait un bug dans l'appelant 🤔) ?
Supprimer le max ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avant, j'avais un problème mais maintenant non, donc je vais supprimer le max.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certaines checks ont échoué, où l'âge = -1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En effet, dans cmuc_fiab.yaml, "CMU-C: N°1 refus CMUC, accord ACS - 2018-05".

Dans cette situation il y a un enfant né le 2018-01-01 et pour qui on évalue des variables en 2017. A mon sens c'est une erreur dans le test, et on peut le faire passer en corrigeant cette date de naissance en 2017-01-01.

Si on souhaite corriger cette erreur de façon plus globale, il me semble qu'il vaudrait mieux s'assurer directement dans la variable age qu'elle renvoie un résultat supérieur ou égal à 0, et on peut embarquer ça dans une autre PR.

Donc @mtifarine je t'invite plutôt à corriger le test en question pour l'instant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour l'age , si je me rappelle bien il y a des allocations pour des enfants à naître et qui ont donc un âge négatif ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Morendil
Toujours le même problème, même après la correction du test en question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effectivement cette date de naissance n'est pas fausse en soi, comme le dit @benjello cela concerne des allocations pour enfants à naître.
Le problème étant que plus loin dans le code, on utilise cet age comme un index :
conversion_rente_capital = rente_at.capital_representatif[age]
et aucune valeur n'existe pour un age négatif.
Ce max permet d’éviter ce problème sans fausser les résultats.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mtifarine Oui c'est maintenant un autre test qui échoue: test_mes_aides_5530fbb7d421717116602458.yaml comme indiqué dans l'intégration continue. Malheureusement l'outil de test de Core n'est pas assez robuste face à ce type d'erreurs, il sort au premier échec. J'ai créé une issue pour ce sujet.

Effectivement à la lecture de ce test ça me paraît logique qu'on rétablisse ce max_ ici dans la mesure où d'autres tests sont concernés par cette difficulté. Cette notion "d'âge négatif" me semble quand même problématique.

Par ailleurs je m'aperçois que la valeur 0 n'est pas une valeur par défaut raisonnable pour ce paramètre pour age < 16. Ainsi nous avons une division par zéro dans rente_accident_travail_apres_rachat ligne 122, que le where ne peut pas éviter en raison de la nature vectorielle du calcul. Il vaudrait mieux ne garder que les valeurs > 0 dans le paramètre et utiliser dans ce cas max_(age, 16).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le problème existe (en production) pour les personnes âgées de plus de 100 ans. Mais j'ai l'intuiton que l'âge utilisé n'est pas le bon, en effet je pensais que l'âge utilisé dans le barème serait l'âge au moment de l'accident de travail ? (ou peut-être que c'est l'âge de la demande de passage en capital et là ça serait bon). À voir. #1327

@@ -0,0 +1,307 @@
description: Barème servant à la détermination du capital représentatif des rentes d'accidents du travail
reference: "https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000030308553&categorieLien=id"
unit: currency
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour les valeurs en euros, on peut indiquer : currency-EUR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Les valeurs du capital representatif sont des coefficients et ne sont pas des valeurs en euros.

@frtomas
Copy link
Contributor

frtomas commented Mar 20, 2019

@Morendil reste-t-il d'autres points bloquants sur cette PR ?

@Morendil
Copy link
Contributor

@frtomas Non, on devrait pouvoir merger dans l'après-midi.

@Morendil
Copy link
Contributor

@mtifarine J'ai rebasé et simplifié un peu l'historique de la branche, et corrigé aussi la présence d'un commit de merge résultant de ce qu'on s'est apparemment un peu marché sur les pieds vers la fin.

@sandcha m'a signalé tout à l'heure que j'ai effectué des rebase et push-force sur cette PR, et que ce n'était pas une habitude courante jusqu'ici. Pour moi l'avantage de rebaser en cours de route c'est que je suis certain que la PR contient bien les évolutions les plus récentes et que le résultat des tests est donc pertinent, mais je vais essayer d'être plus explicite quand je le fais et de le faire moins souvent.

L'inconvénient c'est que quand tu reprends une branche après qu'une autre personne ait fait un rebase et push-force, il ne faut surtout pas faire un git pull et faire attention à te mettre à jour de la branche telle qu'elle est dans Github avant d'ajouter des commits.

Généralement je fais ça comme suit:

git checkout master
git branch -f nom_de_branche origin/nom_de_branche
git checkout nom_de_branche

Cela revient à supprimer la branche locale, et la checkout à nouveau depuis Github.

@mtifarine
Copy link
Contributor Author

Ok @Morendil, merci!

@Morendil Morendil merged commit 53dfc8b into master Mar 20, 2019
@Morendil Morendil deleted the msa_rente_at branch March 20, 2019 15:25
frtomas pushed a commit that referenced this pull request Mar 21, 2019
Intégration du calcul de la rente d'accident du travail
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contrib:msa Identification des sujets MSA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants