Skip to content

Commit

Permalink
refactor: BRS modélisé en vectoriel
Browse files Browse the repository at this point in the history
  • Loading branch information
Shamzic committed Jan 7, 2025
1 parent b1960e5 commit 69e1861
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 24 deletions.
70 changes: 46 additions & 24 deletions openfisca_france/model/prestations/bail_reel_solidaire.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,75 @@
from openfisca_france.model.base import *
import os
import csv

import numpy as np

ZONAGE_ABC = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'../../assets/zonage-communes/zonage-abc-juillet-2024.csv'
)

)
ZONES_ABC = ['A', 'Abis', 'B1', 'B2', 'C']
NB_PERSONNES_MAX = 6

def preload_zone_abc():
if not os.path.exists(ZONAGE_ABC):
return None

with open(ZONAGE_ABC, 'r', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile, delimiter=';')
return {
row['CODGEO']: row['Zone en vigueur depuis le 5 juillet 2024']
for row in reader
}

return {row['CODGEO']: row['Zone en vigueur depuis le 5 juillet 2024'] for row in reader}

class bail_reel_solidaire(Variable):
entity = Menage
value_type = float
value_type = bool
reference = 'https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000032918488'
label = 'Bail réel solidaire'
definition_period = MONTH

def formula(menage, period, parameters):
nb_personnes = menage.nb_persons()[0]
_zone_abc_by_depcom = preload_zone_abc()
def plafond_par_zone_et_composition(nb_personnes, plafonds_par_zones, zone):
plafond_zone = plafonds_par_zones[f'zone_{zone}']
conditions = [
nb_personnes == 1,
nb_personnes == 2,
nb_personnes == 3,
nb_personnes == 4,
nb_personnes == 5,
nb_personnes >= 6
]
plafonds = [
plafond_zone['nb_personnes_1'],
plafond_zone['nb_personnes_2'],
plafond_zone['nb_personnes_3'],
plafond_zone['nb_personnes_4'],
plafond_zone['nb_personnes_5'],
plafond_zone['nb_personnes_6']
]
return select(conditions, plafonds)

def plafond_supplementaire_par_zone(nb_personnes, plafonds_par_zones, zone):
return where(nb_personnes > NB_PERSONNES_MAX,
(nb_personnes - NB_PERSONNES_MAX) * plafonds_par_zones[f'zone_{zone}']['nb_personnes_supplementaires'], 0)

if _zone_abc_by_depcom is None:
zones_par_depcom = preload_zone_abc()
if not zones_par_depcom:
return False

nb_personnes = menage.nb_persons()
depcom = menage('depcom', period.first_month)
zone = _zone_abc_by_depcom.get(depcom[0].decode('utf-8'))
zones = np.array([zones_par_depcom.get(d.decode('utf-8'), None) for d in depcom])

if zone is None:
return False
plafonds_par_zones = parameters(period).prestations_sociales.bail_reel_solidaire.plafonds_par_zones

params = parameters(period).prestations_sociales.bail_reel_solidaire.plafonds_par_zones[f'zone_{zone}']
rfr = menage.sum(menage.members.foyer_fiscal('rfr', period.n_2), role = FoyerFiscal.DECLARANT_PRINCIPAL)[0]
plafond_base = select(
[zones == zone for zone in ZONES_ABC],
[plafond_par_zone_et_composition(nb_personnes, plafonds_par_zones, zone) for zone in ZONES_ABC]
)

if nb_personnes > 6:
plafond_base = params.nb_personnes_6
personnes_supp = nb_personnes - 6
plafond = plafond_base + (personnes_supp * params.nb_personnes_supplementaires)
else:
plafond = getattr(params, f'nb_personnes_{nb_personnes}')
plafond_supp = select(
[zones == zone for zone in ZONES_ABC],
[plafond_supplementaire_par_zone(nb_personnes, plafonds_par_zones, zone) for zone in ZONES_ABC]
)

return rfr <= plafond
rfr = menage.sum(menage.members.foyer_fiscal('rfr', period.n_2), role=FoyerFiscal.DECLARANT_PRINCIPAL)

return where(zones != None, rfr <= (plafond_base + plafond_supp), False)
45 changes: 45 additions & 0 deletions tests/formulas/bail_reel_solidaire.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
- name: Bail réel solidaire - Tests vectoriels
period: 2024-12
input:
foyers_fiscaux:
foyer_fiscal_0:
declarants: [personne1]
foyer_fiscal_1:
declarants: [personne2, personne3]
foyer_fiscal_2:
declarants: [personne4, personne5]
personnes_a_charge: [enfant1, enfant2]
individus:
personne1:
salaire_imposable:
2022: 35000
personne2:
salaire_imposable:
2022: 34000
personne3:
salaire_imposable:
2022: 32000
personne4:
salaire_imposable:
2022: 40000
personne5:
salaire_imposable:
2022: 48000
enfant1: {}
enfant2: {}
menages:
menage_0:
depcom: '01401' # Zone A - Sergy
personne_de_reference: [personne1]
menage_1:
depcom: '01103' # Zone A - Chevry
personne_de_reference: [personne2]
conjoint: [personne3]
menage_2:
depcom: '75056' # Zone Abis - Paris
personne_de_reference: [personne4]
conjoint: [personne5]
enfants: [enfant1, enfant2]
output:
bail_reel_solidaire: [true, false, true]

- name: Bail réel solidaire - Zone A - Personne seule
period: 2024-12
input:
Expand Down

0 comments on commit 69e1861

Please sign in to comment.