def _salbrut_from_salnet(salnet, hsup, type_sal, _defaultP): ''' Calcule le salaire brut à partir du salaire net Renvoie 0 sauf pour les salariés non cadres, cadres (TODO: et les contractuels de la fonction publique ?) ''' plaf_ss = 12 * _defaultP.cotsoc.gen.plaf_ss salarie = scale_tax_scales(TaxScalesTree('sal', _defaultP.cotsoc.sal), plaf_ss) csg_deduc = scale_tax_scales(_defaultP.csg.act.deduc, plaf_ss) csg_impos = scale_tax_scales(_defaultP.csg.act.impos, plaf_ss) crds = scale_tax_scales(_defaultP.crds.act, plaf_ss) salarie['noncadre'].update(salarie['commun']) salarie['cadre'].update(salarie['commun']) # Salariés du privé prive_non_cadre = combine_tax_scales(salarie['noncadre']) prive_cadre = combine_tax_scales(salarie['cadre']) # On ajoute la CSG deductible et imposable for bareme in [prive_non_cadre, prive_cadre]: bareme.add_tax_scale(csg_deduc) bareme.add_tax_scale(csg_impos) bareme.add_tax_scale(crds) inversed_bareme = { 'prive_cadre': prive_cadre.inverse(), 'prive_non_cadre': prive_non_cadre.inverse(), } salbrut = zeros(len(salnet)) for category in ['prive_non_cadre', 'prive_cadre']: salbrut += inversed_bareme[category].calc(salnet) * (type_sal == CAT[category]) return salbrut + hsup
def test_combine_tax_scales(): from openfisca_core.parameters import ParameterNode node = ParameterNode('baremes', data = { 'health': { 'brackets': [ { 'rate': {'2015-01-01': 0.05}, 'threshold': {'2015-01-01': 0} }, { 'rate': {'2015-01-01': 0.10}, 'threshold': {'2015-01-01': 2000} }, ]}, 'retirement': { 'brackets': [ { 'rate': {'2015-01-01': 0.02}, 'threshold': {'2015-01-01': 0} }, { 'rate': {'2015-01-01': 0.04}, 'threshold': {'2015-01-01': 3000} }, ] }, })(2015) bareme = combine_tax_scales(node) assert_near(bareme.thresholds, [0, 2000, 3000]) assert_near(bareme.rates, [0.07, 0.12, 0.14], 1e-13)
def _chobrut_from_chonet(chonet, csg_rempl, _defaultP): ''' Calcule les allocations chômage brute à partir des allocations imposables ''' P = _defaultP.csg.chom plaf_ss = 12 * _defaultP.cotsoc.gen.plaf_ss csg = scale_tax_scales(TaxScaleDict('csg', P), plaf_ss) crds = scale_tax_scales(_defaultP.crds.rst, plaf_ss) # crds.rst est la CRDS sur les revenus de remplacement donc valable aussi pour le chômage taux_plein = combine_tax_scales(csg['plein']) taux_reduit = combine_tax_scales(csg['reduit']) taux_plein.add_tax_scale(crds) taux_reduit.add_tax_scale(crds) chom_plein = taux_plein.inverse() chom_reduit = taux_reduit.inverse() chobrut = (csg_rempl == 1) * chonet + (csg_rempl == 2) * chom_reduit.calc(chonet) + (csg_rempl == 3) * chom_plein.calc(chonet) isexo = exo_csg_chom(chobrut, csg_rempl, _defaultP) chobrut = not_(isexo) * chobrut + (isexo) * chonet return chobrut
def _rstbrut_from_rstnet(rstnet, csg_rempl, _defaultP): ''' Calcule les pensions de retraites brutes à partir des pensions nettes ''' P = _defaultP.csg.retraite plaf_ss = 12 * _defaultP.cotsoc.gen.plaf_ss csg = scale_tax_scales(TaxScalesTree('csg', P), plaf_ss) crds = scale_tax_scales(_defaultP.crds.rst, plaf_ss) taux_plein = combine_tax_scales(csg['plein']) taux_reduit = combine_tax_scales(csg['reduit']) taux_plein.add_tax_scale(crds) taux_reduit.add_tax_scale(crds) if hasattr(_defaultP.prelsoc, 'add_ret'): casa = MarginalRateTaxScale(name = "casa") casa.add_bracket(0, _defaultP.prelsoc.add_ret) taux_plein.add_tax_scale(casa) taux_reduit.add_tax_scale(casa) rst_plein = taux_plein.inverse() rst_reduit = taux_reduit.inverse() rstbrut = (csg_rempl == 2) * rst_reduit.calc(rstnet) + (csg_rempl == 3) * rst_plein.calc(rstnet) return rstbrut
def formula(self, simulation, period): """Calcule le salaire brut à partir du salaire imposable par inversion du barème de cotisations sociales correspondant à la catégorie à laquelle appartient le salarié. """ # Get value for year and divide below. this_year = period.this_year salaire_imposable_pour_inversion = simulation.calculate('salaire_imposable_pour_inversion', period = this_year) # Calcule le salaire brut (salaire de base) à partir du salaire imposable. categorie_salarie = simulation.calculate('categorie_salarie', period = this_year) contrat_de_travail = simulation.calculate('contrat_de_travail', period = this_year) heures_remunerees_volume = simulation.calculate('heures_remunerees_volume', period = this_year) hsup = simulation.calculate('hsup', period = this_year) P = simulation.parameters_at(period.start) salarie = P.cotsoc.cotisations_salarie plafond_securite_sociale_annuel = P.cotsoc.gen.plafond_securite_sociale * 12 csg_deductible = simulation.parameters_at(period.start).prelevements_sociaux.contributions.csg.activite.deductible taux_csg = csg_deductible.taux taux_abattement = csg_deductible.abattement.rates[0] try: seuil_abattement = csg_deductible.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg = MarginalRateTaxScale(name = 'csg') csg.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg.add_bracket(seuil_abattement, taux_csg) target = dict() target['prive_non_cadre'] = set(['maladie', 'arrco', 'vieillesse_deplafonnee', 'vieillesse', 'agff', 'assedic']) target['prive_cadre'] = set( ['maladie', 'arrco', 'vieillesse_deplafonnee', 'agirc', 'cet', 'apec', 'vieillesse', 'agff', 'assedic'] ) for categorie in ['prive_non_cadre', 'prive_cadre']: baremes_collection = salarie[categorie] baremes_to_remove = list() for name, bareme in baremes_collection.iteritems(): if name.endswith('alsace_moselle'): baremes_to_remove.append(name) for name in baremes_to_remove: del baremes_collection[name] for categorie in ['prive_non_cadre', 'prive_cadre']: test = set( name for name, bareme in salarie[categorie].iteritems() if isinstance(bareme, MarginalRateTaxScale) ) assert target[categorie] == test, 'target: {} \n test {}'.format(target[categorie], test) del bareme # On ajoute la CSG deductible et on proratise par le plafond de la sécurité sociale # Pour éviter les divisions 0 /0 dans le switch heures_remunerees_volume_avoid_warning = heures_remunerees_volume + (heures_remunerees_volume == 0) * 1e9 salaire_imposable_proratise = switch( contrat_de_travail, { # temps plein 0: salaire_imposable_pour_inversion / plafond_securite_sociale_annuel, # temps partiel 1: salaire_imposable_pour_inversion / ( (heures_remunerees_volume_avoid_warning / (52 * 35)) * plafond_securite_sociale_annuel ), } ) salaire_de_base = 0.0 for categorie in ['prive_non_cadre', 'prive_cadre']: bareme = combine_tax_scales(salarie[categorie]) bareme.add_tax_scale(csg) brut_proratise = bareme.inverse().calc(salaire_imposable_proratise) assert np.isfinite(brut_proratise).all() brut = plafond_securite_sociale_annuel * switch( contrat_de_travail, { # temps plein 0: brut_proratise, # temps partiel 1: brut_proratise * (heures_remunerees_volume / (52 * 35)), } ) salaire_de_base += ( (categorie_salarie == CATEGORIE_SALARIE[categorie]) * brut ) assert (salaire_de_base > -1e9).all() assert (salaire_de_base < 1e9).all() # agirc_gmp # gmp = P.prelevements_sociaux.gmp # salaire_charniere = gmp.salaire_charniere_annuel # cotisation_forfaitaire = gmp.cotisation_forfaitaire_mensuelle_en_euros.part_salariale * 12 # salaire_de_base += ( # (categorie_salarie == CATEGORIE_SALARIE['prive_cadre']) * # (salaire_de_base <= salaire_charniere) * # cotisation_forfaitaire # ) return salaire_de_base + hsup
def _salbrut_from_sali(sali, hsup, type_sal, _defaultP): ''' Calcule le salaire brut à partir du salaire imposable sauf pour les fonctionnaires où il renvoie le tratement indiciaire brut Note : le supplément familial de traitement est imposable ''' plaf_ss = 12 * _defaultP.cotsoc.gen.plaf_ss salarie = scale_tax_scales(TaxScalesTree('sal', _defaultP.cotsoc.sal), plaf_ss) csg = scale_tax_scales(TaxScalesTree('csg', _defaultP.csg), plaf_ss) salarie['noncadre'].update(salarie['commun']) salarie['cadre'].update(salarie['commun']) # log.info("Le dictionnaire des barèmes des cotisations salariés des titulaires de l'Etat contient : \n %s", # salarie['fonc']["etat"]) # Salariés du privé noncadre = combine_tax_scales(salarie['noncadre']) cadre = combine_tax_scales(salarie['cadre']) # On ajoute la CSG deductible noncadre.add_tax_scale(csg['act']['deduc']) cadre.add_tax_scale(csg['act']['deduc']) nca = noncadre.inverse() cad = cadre.inverse() brut_nca = nca.calc(sali) brut_cad = cad.calc(sali) salbrut = brut_nca * (type_sal == CAT['prive_non_cadre']) salbrut += brut_cad * (type_sal == CAT['prive_cadre']) # public etat # TODO: modifier la contribution exceptionelle de solidarité # en fixant son seuil de non imposition dans le barème (à corriger dans param.xml # et en tenant compte des éléments de l'assiette salarie['fonc']['etat']['excep_solidarite'] = salarie['fonc']['commun']['solidarite'] public_etat = salarie['fonc']['etat']['pension'] # public_colloc = combine_tax_scales(salarie['fonc']["colloc"]) TODO: # Pour a fonction publique la csg est calculée sur l'ensemble salbrut(=TIB) + primes # Imposable = TIB - csg( (1+taux_prime)*TIB ) - pension(TIB) + taux_prime*TIB bareme_csg_titulaire_etat = (csg['act']['deduc']).multiply_rates(1 + TAUX_DE_PRIME, inplace = False, new_name = "csg deduc titutaire etat") public_etat.add_tax_scale(bareme_csg_titulaire_etat) bareme_prime = MarginalRateTaxScale(name = "taux de prime") bareme_prime.add_bracket(0, -TAUX_DE_PRIME) # barème équivalent à taux_prime*TIB public_etat.add_tax_scale(bareme_prime) etat = public_etat.inverse() # TODO: complete this to deal with the fonctionnaire # supp_familial_traitement = 0 # TODO: dépend de salbrut # indemnite_residence = 0 # TODO: fix bug # print 'sali', sali / 12 brut_etat = etat.calc(sali) # print 'brut_etat', brut_etat/12 # print 'impot', public_etat.calc(brut_etat) / 12 # print 'brut_etat', brut_etat / 12 salbrut_etat = (brut_etat) # TODO: fonctionnaire # print 'salbrut_etat', salbrut_etat / 12 salbrut += salbrut_etat * (type_sal == CAT['public_titulaire_etat']) # <NODE desc= "Supplément familial de traitement " shortname="Supp. fam." code= "supp_familial_traitement"/> # <NODE desc= "Indemnité de résidence" shortname="Ind. rés." code= "indemenite_residence"/> return salbrut + hsup
def formula(individu, period, parameters): """Calcule le salaire brut à partir du salaire imposable par inversion du barème de cotisations sociales correspondant à la catégorie à laquelle appartient le salarié. """ # Get value for year and divide below. this_year = period.this_year salaire_imposable_pour_inversion = individu('salaire_imposable_pour_inversion', period = this_year) # Calcule le salaire brut (salaire de base) à partir du salaire imposable. categorie_salarie = individu('categorie_salarie', period = this_year) contrat_de_travail = individu('contrat_de_travail', period = this_year) heures_remunerees_volume = individu('heures_remunerees_volume', period = this_year) hsup = individu('hsup', period = this_year) P = parameters(period) salarie = P.cotsoc.cotisations_salarie plafond_securite_sociale_annuel = P.cotsoc.gen.plafond_securite_sociale * 12 csg_deductible = parameters(period).prelevements_sociaux.contributions.csg.activite.deductible taux_csg = csg_deductible.taux taux_abattement = csg_deductible.abattement.rates[0] try: seuil_abattement = csg_deductible.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg = MarginalRateTaxScale(name = 'csg') csg.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg.add_bracket(seuil_abattement, taux_csg) target = dict() target['prive_non_cadre'] = set(['maladie', 'arrco', 'vieillesse_deplafonnee', 'vieillesse', 'agff', 'assedic']) target['prive_cadre'] = set( ['maladie', 'arrco', 'vieillesse_deplafonnee', 'agirc', 'cet', 'apec', 'vieillesse', 'agff', 'assedic'] ) for categorie in ['prive_non_cadre', 'prive_cadre']: baremes_collection = salarie[categorie] baremes_to_remove = list() for name, bareme in baremes_collection.iteritems(): if name.endswith('alsace_moselle'): baremes_to_remove.append(name) for name in baremes_to_remove: del baremes_collection[name] for categorie in ['prive_non_cadre', 'prive_cadre']: test = set( name for name, bareme in salarie[categorie].iteritems() if isinstance(bareme, MarginalRateTaxScale) ) assert target[categorie] == test, 'target: {} \n test {}'.format(target[categorie], test) del bareme # On ajoute la CSG deductible et on proratise par le plafond de la sécurité sociale # Pour éviter les divisions 0 /0 dans le switch heures_remunerees_volume_avoid_warning = heures_remunerees_volume + (heures_remunerees_volume == 0) * 1e9 salaire_imposable_proratise = switch( contrat_de_travail, { # temps plein 0: salaire_imposable_pour_inversion / plafond_securite_sociale_annuel, # temps partiel 1: salaire_imposable_pour_inversion / ( (heures_remunerees_volume_avoid_warning / (52 * 35)) * plafond_securite_sociale_annuel ), } ) salaire_de_base = 0.0 for categorie in ['prive_non_cadre', 'prive_cadre']: bareme = combine_tax_scales(salarie[categorie]) bareme.add_tax_scale(csg) brut_proratise = bareme.inverse().calc(salaire_imposable_proratise) assert np.isfinite(brut_proratise).all() brut = plafond_securite_sociale_annuel * switch( contrat_de_travail, { # temps plein 0: brut_proratise, # temps partiel 1: brut_proratise * (heures_remunerees_volume / (52 * 35)), } ) salaire_de_base += ( (categorie_salarie == CATEGORIE_SALARIE[categorie]) * brut ) assert (salaire_de_base > -1e9).all() assert (salaire_de_base < 1e9).all() # agirc_gmp # gmp = P.prelevements_sociaux.gmp # salaire_charniere = gmp.salaire_charniere_annuel # cotisation_forfaitaire = gmp.cotisation_forfaitaire_mensuelle_en_euros.part_salariale * 12 # salaire_de_base += ( # (categorie_salarie == CATEGORIE_SALARIE['prive_cadre']) * # (salaire_de_base <= salaire_charniere) * # cotisation_forfaitaire # ) return salaire_de_base + hsup
def test_combine_tax_scales(node): result = taxscales.combine_tax_scales(node) tools.assert_near(result.thresholds, [0, 2000, 3000]) tools.assert_near(result.rates, [0.07, 0.12, 0.14], 1e-13)
def create_salaire_de_base(individus, period=None, revenu_type='imposable', tax_and_benefit_system=None): """Calcule le salaire brut à partir du salaire imposable par inversion du barème de cotisations sociales correspondant à la catégorie à laquelle appartient le salarié. """ assert period is not None assert revenu_type in ['net', 'imposable'] for variable in [ 'categorie_salarie', 'contrat_de_travail', 'heures_remunerees_volume' ]: assert variable in individus.columns assert tax_and_benefit_system is not None if revenu_type == 'imposable': salaire_pour_inversion = individus.salaire_imposable else: salaire_pour_inversion = individus.salaire_net categorie_salarie = individus.categorie_salarie contrat_de_travail = individus.contrat_de_travail heures_remunerees_volume = individus.heures_remunerees_volume # hsup = simulation.calculate('hsup', period = this_year) simulation = tax_and_benefit_system.new_scenario().init_single_entity( period=period, parent1=dict()).new_simulation() parameters = simulation.parameters_at(period.start) salarie = parameters.cotsoc.cotisations_salarie plafond_securite_sociale_mensuel = parameters.cotsoc.gen.plafond_securite_sociale parameters_csg_deductible = parameters.prelevements_sociaux.contributions.csg.activite.deductible taux_csg = parameters_csg_deductible.taux taux_abattement = parameters_csg_deductible.abattement.rates[0] try: seuil_abattement = parameters_csg_deductible.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg_deductible = MarginalRateTaxScale(name='csg_deductible') csg_deductible.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_deductible.add_bracket(seuil_abattement, taux_csg) if revenu_type == 'net': # On ajoute CSG imposable et crds # csg imposable parameters_csg_imposable = parameters.prelevements_sociaux.contributions.csg.activite.imposable taux_csg = parameters_csg_imposable.taux taux_abattement = parameters_csg_imposable.abattement.rates[0] try: seuil_abattement = parameters_csg_imposable.abattement.thresholds[ 1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg_imposable = MarginalRateTaxScale(name='csg_imposable') csg_imposable.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_imposable.add_bracket(seuil_abattement, taux_csg) # crds # csg imposable parameters_crds = parameters.prelevements_sociaux.contributions.crds.activite taux_csg = parameters_crds.taux taux_abattement = parameters_crds.abattement.rates[0] try: seuil_abattement = parameters_crds.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None crds = MarginalRateTaxScale(name='crds') crds.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: crds.add_bracket(seuil_abattement, taux_csg) # Check baremes target = dict() target['prive_non_cadre'] = set([ 'maladie', 'arrco', 'vieillesse_deplafonnee', 'vieillesse', 'agff', 'assedic' ]) target['prive_cadre'] = set([ 'maladie', 'arrco', 'vieillesse_deplafonnee', 'agirc', 'cet', 'apec', 'vieillesse', 'agff', 'assedic' ]) for categorie in ['prive_non_cadre', 'prive_cadre']: baremes_collection = salarie[categorie] baremes_to_remove = list() for name, bareme in baremes_collection._children.iteritems(): if name.endswith('alsace_moselle'): baremes_to_remove.append(name) for name in baremes_to_remove: del baremes_collection._children[name] for categorie in ['prive_non_cadre', 'prive_cadre']: test = set( name for name, bareme in salarie[categorie]._children.iteritems() if isinstance(bareme, MarginalRateTaxScale)) assert target[categorie] == test, 'target: {} \n test {}'.format( target[categorie], test) del bareme # On ajoute la CSG deductible et on proratise par le plafond de la sécurité sociale # Pour éviter les divisions 0 /0 dans le switch if period.unit == 'year': plafond_securite_sociale = plafond_securite_sociale_mensuel * 12 heures_temps_plein = 52 * 35 elif period.unit == 'month': plafond_securite_sociale = plafond_securite_sociale_mensuel * period.size heures_temps_plein = (52 * 35 / 12) * period.size else: raise heures_remunerees_volume_avoid_warning = heures_remunerees_volume + ( heures_remunerees_volume == 0) * 1e9 salaire_pour_inversion_proratise = switch( contrat_de_travail, { # temps plein 0: salaire_pour_inversion / plafond_securite_sociale, # temps partiel 1: salaire_pour_inversion / ((heures_remunerees_volume_avoid_warning / heures_temps_plein) * plafond_securite_sociale), }) salaire_de_base = 0.0 for categorie in ['prive_non_cadre', 'prive_cadre']: bareme = combine_tax_scales(salarie[categorie]) bareme.add_tax_scale(csg_deductible) if revenu_type == 'net': bareme.add_tax_scale(csg_imposable) bareme.add_tax_scale(crds) brut_proratise = bareme.inverse().calc( salaire_pour_inversion_proratise) assert np.isfinite(brut_proratise).all() brut = plafond_securite_sociale * switch( contrat_de_travail, { # temps plein 0: brut_proratise, # temps partiel 1: brut_proratise * (heures_remunerees_volume / (heures_temps_plein)), }) salaire_de_base += ( (categorie_salarie == CATEGORIE_SALARIE[categorie]) * brut) assert (salaire_de_base >= 0).all() assert (salaire_de_base < 1e9).all() # agirc_gmp # gmp = P.prelevements_sociaux.gmp # salaire_charniere = gmp.salaire_charniere_annuel # cotisation_forfaitaire = gmp.cotisation_forfaitaire_mensuelle_en_euros.part_salariale * 12 # salaire_de_base += ( # (categorie_salarie == CATEGORIE_SALARIE['prive_cadre']) * # (salaire_de_base <= salaire_charniere) * # cotisation_forfaitaire # ) individus['salaire_de_base'] = salaire_de_base
def create_salaire_de_base(individus, period=None, revenu_type='imposable', tax_benefit_system=None): """ Calcule la variable salaire_de_base à partir du salaire imposable par inversion du barème de cotisations sociales correspondant à la catégorie à laquelle appartient le salarié. """ assert period is not None assert revenu_type in ['net', 'imposable'] for variable in [ 'categorie_salarie', 'contrat_de_travail', 'heures_remunerees_volume' ]: assert variable in individus.columns, "{} is missing".format(variable) assert tax_benefit_system is not None if revenu_type == 'imposable': salaire_pour_inversion = individus.salaire_imposable else: salaire_pour_inversion = individus.salaire_net categorie_salarie = individus.categorie_salarie contrat_de_travail = individus.contrat_de_travail heures_remunerees_volume = individus.heures_remunerees_volume parameters = tax_benefit_system.get_parameters_at_instant(period.start) salarie = parameters.cotsoc.cotisations_salarie plafond_securite_sociale_mensuel = parameters.cotsoc.gen.plafond_securite_sociale parameters_csg_deductible = parameters.prelevements_sociaux.contributions.csg.activite.deductible taux_csg = parameters_csg_deductible.taux taux_abattement = parameters_csg_deductible.abattement.rates[0] try: seuil_abattement = parameters_csg_deductible.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg_deductible = MarginalRateTaxScale(name='csg_deductible') csg_deductible.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_deductible.add_bracket(seuil_abattement, taux_csg) if revenu_type == 'net': # On ajoute CSG imposable et crds parameters_csg_imposable = parameters.prelevements_sociaux.contributions.csg.activite.imposable taux_csg = parameters_csg_imposable.taux taux_abattement = parameters_csg_imposable.abattement.rates[0] try: seuil_abattement = parameters_csg_imposable.abattement.thresholds[ 1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None csg_imposable = MarginalRateTaxScale(name='csg_imposable') csg_imposable.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_imposable.add_bracket(seuil_abattement, taux_csg) parameters_crds = parameters.prelevements_sociaux.contributions.crds.activite taux_csg = parameters_crds.taux taux_abattement = parameters_crds.abattement.rates[0] try: seuil_abattement = parameters_crds.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours était limité à 4 PSS seuil_abattement = None crds = MarginalRateTaxScale(name='crds') crds.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: crds.add_bracket(seuil_abattement, taux_csg) # Check baremes target = dict() target['prive_non_cadre'] = set([ 'maladie', 'arrco', 'vieillesse_deplafonnee', 'vieillesse', 'agff', 'assedic' ]) target['prive_cadre'] = set([ 'maladie', 'arrco', 'vieillesse_deplafonnee', 'agirc', 'cet', 'apec', 'vieillesse', 'agff', 'assedic' ]) target['public_non_titulaire'] = set([ 'excep_solidarite', 'maladie', 'ircantec', 'vieillesse_deplafonnee', 'vieillesse' ]) for categorie in [ 'prive_non_cadre', 'prive_cadre', 'public_non_titulaire' ]: baremes_collection = salarie[categorie] baremes_to_remove = list() for name, bareme in baremes_collection._children.items(): if name.endswith('alsace_moselle'): baremes_to_remove.append(name) for name in baremes_to_remove: del baremes_collection._children[name] for categorie in [ 'prive_non_cadre', 'prive_cadre', 'public_non_titulaire' ]: test = set(name for name, bareme in salarie[categorie]._children.items() if isinstance(bareme, MarginalRateTaxScale)) assert target[categorie] == test, 'target: {} \n test {}'.format( target[categorie], test) del bareme # On ajoute la CSG deductible et on proratise par le plafond de la sécurité sociale # Pour éviter les divisions 0 /0 dans le switch qui sert à calculer le salaire_pour_inversion_proratise if period.unit == 'year': plafond_securite_sociale = plafond_securite_sociale_mensuel * 12 heures_temps_plein = 52 * 35 elif period.unit == 'month': plafond_securite_sociale = plafond_securite_sociale_mensuel * period.size heures_temps_plein = (52 * 35 / 12) * period.size else: raise heures_remunerees_volume_avoid_warning = heures_remunerees_volume + ( heures_remunerees_volume == 0) * 1e9 salaire_pour_inversion_proratise = switch( contrat_de_travail, { # temps plein 0: salaire_pour_inversion / plafond_securite_sociale, # temps partiel 1: salaire_pour_inversion / ((heures_remunerees_volume_avoid_warning / heures_temps_plein) * plafond_securite_sociale), }) def add_agirc_gmp_to_agirc(agirc, parameters): plafond_securite_sociale_annuel = parameters.cotsoc.gen.plafond_securite_sociale * 12 salaire_charniere = parameters.prelevements_sociaux.gmp.salaire_charniere_annuel / plafond_securite_sociale_annuel cotisation = parameters.prelevements_sociaux.gmp.cotisation_forfaitaire_mensuelle_en_euros.part_salariale * 12 n = (cotisation + 1) * 12 agirc.add_bracket(n / plafond_securite_sociale_annuel, 0) agirc.rates[0] = cotisation / n agirc.thresholds[2] = salaire_charniere salaire_de_base = 0.0 for categorie in [ 'prive_non_cadre', 'prive_cadre', 'public_non_titulaire' ]: if categorie == 'prive_cadre': add_agirc_gmp_to_agirc(salarie[categorie].agirc, parameters) bareme = combine_tax_scales(salarie[categorie]) bareme.add_tax_scale(csg_deductible) if revenu_type == 'net': bareme.add_tax_scale(csg_imposable) bareme.add_tax_scale(crds) assert bareme.inverse( ).thresholds[0] == 0, "Invalid inverse bareme for {}:\n {}".format( categorie, bareme.inverse()) for rate in bareme.inverse( ).rates: # Vérification que l'on peut inverser correctement assert rate > 0 brut_proratise = bareme.inverse().calc( salaire_pour_inversion_proratise) assert np.isfinite(brut_proratise).all() brut = plafond_securite_sociale * switch( contrat_de_travail, { # temps plein 0: brut_proratise, # temps partiel 1: brut_proratise * (heures_remunerees_volume / (heures_temps_plein)), }) salaire_de_base += ( (categorie_salarie == TypesCategorieSalarie[categorie].index) * brut) individus['salaire_de_base'] = salaire_de_base if period.unit == 'year': year = period.start.year individus.loc[(individus.contrat_de_travail == 0) & (individus.salaire_de_base > 0), 'salaire_de_base'] = np.maximum( salaire_de_base, smic_horaire_brut[year] * 35 * 52 / 12) individus.loc[(individus.contrat_de_travail == 1) & (individus.salaire_de_base > 0), 'salaire_de_base'] = np.maximum( salaire_de_base, smic_horaire_brut[year] * heures_remunerees_volume)
def create_traitement_indiciaire_brut(individus, period=None, revenu_type='imposable', tax_benefit_system=None): """ Calcule le tratement indiciaire brut à partir du salaire imposable ou du salaire net. Note : le supplément familial de traitement est imposable. Pas géré """ assert period is not None assert revenu_type in ['net', 'imposable'] assert tax_benefit_system is not None for variable in [ 'categorie_salarie', 'contrat_de_travail', 'heures_remunerees_volume' ]: assert variable in individus.columns if revenu_type == 'imposable': assert 'salaire_imposable' in individus.columns salaire_pour_inversion = individus.salaire_imposable else: assert 'salaire_net' in individus.columns salaire_pour_inversion = individus.salaire_net categorie_salarie = individus.categorie_salarie contrat_de_travail = individus.contrat_de_travail heures_remunerees_volume = individus.heures_remunerees_volume legislation = tax_benefit_system.get_parameters_at_instant(period.start) salarie = legislation.cotsoc.cotisations_salarie plafond_securite_sociale_mensuel = legislation.cotsoc.gen.plafond_securite_sociale legislation_csg_deductible = legislation.prelevements_sociaux.contributions.csg.activite.deductible taux_csg = legislation_csg_deductible.taux taux_abattement = legislation_csg_deductible.abattement.rates[0] try: seuil_abattement = legislation_csg_deductible.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours été limité à 4 PSS seuil_abattement = None csg_deductible = MarginalRateTaxScale(name='csg_deductible') csg_deductible.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_deductible.add_bracket(seuil_abattement, taux_csg) if revenu_type == 'net': # Cas des revenus nets: # comme les salariés du privé, on ajoute CSG imposable et crds qui s'appliquent à tous les revenus # 1. csg imposable legislation_csg_imposable = legislation.prelevements_sociaux.contributions.csg.activite.imposable taux_csg = legislation_csg_imposable.taux taux_abattement = legislation_csg_imposable.abattement.rates[0] try: seuil_abattement = legislation_csg_imposable.abattement.thresholds[ 1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours été limité à 4 PSS seuil_abattement = None csg_imposable = MarginalRateTaxScale(name='csg_imposable') csg_imposable.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: csg_imposable.add_bracket(seuil_abattement, taux_csg) # 2. crds legislation_crds = legislation.prelevements_sociaux.contributions.crds.activite taux_csg = legislation_crds.taux taux_abattement = legislation_crds.abattement.rates[0] try: seuil_abattement = legislation_crds.abattement.thresholds[1] except IndexError: # Pour gérer le fait que l'abattement n'a pas toujours été limité à 4 PSS seuil_abattement = None crds = MarginalRateTaxScale(name='crds') crds.add_bracket(0, taux_csg * (1 - taux_abattement)) if seuil_abattement is not None: crds.add_bracket(seuil_abattement, taux_csg) # Check baremes target = dict() target['public_titulaire_etat'] = set( ['excep_solidarite', 'pension', 'rafp']) target['public_titulaire_hospitaliere'] = set( ['excep_solidarite', 'cnracl1', 'rafp']) target['public_titulaire_territoriale'] = set( ['excep_solidarite', 'cnracl1', 'rafp']) categories_salarie_du_public = [ 'public_titulaire_etat', 'public_titulaire_hospitaliere', 'public_titulaire_territoriale', ] for categorie in categories_salarie_du_public: baremes_collection = salarie[categorie] test = set( name for name, bareme in salarie[categorie]._children.items() if isinstance(bareme, MarginalRateTaxScale) and name != 'cnracl2') assert target[ categorie] == test, 'target for {}: \n target = {} \n test = {}'.format( categorie, target[categorie], test) # Barèmes à éliminer : # cnracl1 = taux hors NBI -> OK # cnracl2 = taux NBI -> On ne le prend pas en compte pour l'instant for categorie in [ 'public_titulaire_hospitaliere', 'public_titulaire_territoriale', ]: baremes_collection = salarie[categorie] baremes_to_remove = list() baremes_to_remove.append('cnracl2') for name in baremes_to_remove: if 'cnracl2' in baremes_collection: del baremes_collection._children[name] salarie = salarie._children.copy() # RAFP des agents titulaires for categorie in categories_salarie_du_public: baremes_collection = salarie[categorie] baremes_collection['rafp'].multiply_rates(TAUX_DE_PRIME, inplace=True) # On ajoute la CSG déductible et on proratise par le plafond de la sécurité sociale if period.unit == 'year': plafond_securite_sociale = plafond_securite_sociale_mensuel * 12 heures_temps_plein = 52 * 35 elif period.unit == 'month': plafond_securite_sociale = plafond_securite_sociale_mensuel * period.size heures_temps_plein = (52 * 35 / 12) * period.size else: raise # Pour a fonction publique la csg est calculée sur l'ensemble salbrut(=TIB) + primes # Imposable = (1 + taux_prime) * TIB - csg[(1 + taux_prime) * TIB] - pension[TIB] for categorie in categories_salarie_du_public: bareme_csg_deduc_public = csg_deductible.multiply_rates( 1 + TAUX_DE_PRIME, inplace=False, new_name="csg deduc public") if revenu_type == 'net': bareme_csg_imp_public = csg_imposable.multiply_rates( 1 + TAUX_DE_PRIME, inplace=False, new_name="csg imposable public") bareme_crds_public = crds.multiply_rates(1 + TAUX_DE_PRIME, inplace=False, new_name="crds public") for categorie in categories_salarie_du_public: bareme_prime = MarginalRateTaxScale(name="taux de prime") bareme_prime.add_bracket( 0, -TAUX_DE_PRIME) # barème équivalent à taux_prime*TIB heures_remunerees_volume_avoid_warning = heures_remunerees_volume + ( heures_remunerees_volume == 0) * 1e9 salaire_pour_inversion_proratise = switch( contrat_de_travail, { # temps plein 0: salaire_pour_inversion / plafond_securite_sociale, # temps partiel 1: salaire_pour_inversion / ((heures_remunerees_volume_avoid_warning / heures_temps_plein) * plafond_securite_sociale), }) traitement_indiciaire_brut = 0.0 for categorie in categories_salarie_du_public: for key, value in salarie[categorie]._children.items(): log.debug(key, value) bareme = combine_tax_scales(salarie[categorie]) log.debug('bareme cotsoc : {}'.format(bareme)) bareme.add_tax_scale(bareme_csg_deduc_public) log.debug('bareme cotsoc + csg_deduc: {}'.format(bareme)) if revenu_type == 'net': bareme.add_tax_scale(bareme_csg_imp_public) log.debug('bareme cotsoc + csg_deduc + csg_imp: {}'.format(bareme)) bareme.add_tax_scale(bareme_crds_public) log.debug('bareme cotsoc + csg_deduc + csg_imp + crds: {}'.format( bareme)) bareme.add_tax_scale(bareme_prime) log.debug( 'bareme cotsoc + csg_deduc + csg_imp + crds + prime: {}'.format( bareme)) brut_proratise = bareme.inverse().calc( salaire_pour_inversion_proratise) assert np.isfinite(brut_proratise).all() brut = plafond_securite_sociale * switch( contrat_de_travail, { # temps plein 0: brut_proratise, # temps partiel 1: brut_proratise * (heures_remunerees_volume / (heures_temps_plein)), }) traitement_indiciaire_brut += ( (categorie_salarie == TypesCategorieSalarie[categorie].index) * brut) if (categorie_salarie == TypesCategorieSalarie[categorie].index).any(): log.debug("Pour {} : brut = {}".format( TypesCategorieSalarie[categorie].index, brut)) log.debug('bareme direct: {}'.format(bareme)) individus['traitement_indiciaire_brut'] = traitement_indiciaire_brut individus[ 'primes_fonction_publique'] = TAUX_DE_PRIME * traitement_indiciaire_brut