💚 corrige l'indentation
parent
0d56eff981
commit
96e8edf1d1
|
@ -36,17 +36,17 @@ contrat salarié . CDI:
|
|||
contrat salarié . frais professionnels:
|
||||
description: >-
|
||||
Les frais professionnels correspondent à des dépenses engagées par le salarié pour les besoins de son activité professionnelle. Ces frais sont ensuite remboursés par l’employeur.
|
||||
|
||||
|
||||
Le dédommagement de ces frais peut prendre la forme :
|
||||
- d’un remboursement des dépenses réelles sur justificatifs ;
|
||||
- d’un versement d’allocations forfaitaires ;
|
||||
- de l’application d’une déduction forfaitaire spécifique sur le salaire soumis à cotisations ; cette possibilité n’étant ouverte qu’à certaines professions.
|
||||
|
||||
|
||||
Les frais professionnels sont exclus de la base de calcul des cotisations de Sécurité sociale. Ils sont aussi exclus de la base CSG-CRDS.
|
||||
formule:
|
||||
somme:
|
||||
- indemnité kilométrique vélo
|
||||
- titres-restaurant . montant
|
||||
- titres-restaurant . participation employeur
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant:
|
||||
icônes: 🍽️
|
||||
|
@ -62,14 +62,29 @@ contrat salarié . frais professionnels . titres-restaurant:
|
|||
question: Le salarié reçoit-il des titres-restaurant ?
|
||||
par défaut: non
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . montant:
|
||||
contrat salarié . frais professionnels . titres-restaurant . part non exonérée de cotisation:
|
||||
formule:
|
||||
multiplication:
|
||||
facteur:
|
||||
encadrement:
|
||||
valeur: taux participation employeur * valeur - participation employeur . plafond
|
||||
plancher: 0€
|
||||
assiette: titres-restaurant par mois
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . participation employeur . plafond:
|
||||
formule: 5.36€
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . participation employeur:
|
||||
formule:
|
||||
multiplication:
|
||||
facteur: titres-restaurant par mois
|
||||
assiette:
|
||||
encadrement:
|
||||
valeur: 50% * valeur
|
||||
plafond: 5.55 €
|
||||
valeur: taux participation employeur * valeur
|
||||
plafond: plafond
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . participation salarié:
|
||||
formule: valeur * titres-restaurant par mois - participation employeur
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . titres-restaurant par mois:
|
||||
question: Combien de titres-restaurant recevez-vous par mois ?
|
||||
|
@ -81,6 +96,21 @@ contrat salarié . frais professionnels . titres-restaurant . valeur:
|
|||
par défaut: 8
|
||||
unité: €/titre-restaurant
|
||||
|
||||
contrat salarié . frais professionnels . titres-restaurant . taux participation employeur:
|
||||
description: Part du titre-restaurant payée par l'employeur. Doit être de 50% minimum et de 60% maximum
|
||||
question: Quelle est la participation de l'employeur ?
|
||||
par défaut: 50
|
||||
unité: '%'
|
||||
suggestions:
|
||||
50%: 50
|
||||
60%: 60
|
||||
contrôles:
|
||||
- si: taux participation employeur < 50%
|
||||
niveau: avertissement
|
||||
message: La part employeur du titre-restaurant doit être de 50% au minimum
|
||||
- si: taux participation employeur > 60%
|
||||
niveau: avertissement
|
||||
message: La part employeur du titre-restaurant doit être de 60% au maximum
|
||||
|
||||
contrat salarié . frais professionnels . indemnité kilométrique vélo:
|
||||
icônes: 🚴
|
||||
|
@ -755,6 +785,7 @@ contrat salarié . cotisations . assiette:
|
|||
abattement:
|
||||
somme:
|
||||
- frais professionnels
|
||||
- (- frais professionnels . titres-restaurant . part non exonérée de cotisation)
|
||||
- stage . gratification minimale
|
||||
|
||||
contrat salarié . cotisations . assiette . salariale:
|
||||
|
@ -1249,6 +1280,8 @@ contrat salarié . rémunération . net imposable:
|
|||
abattement:
|
||||
somme:
|
||||
- frais professionnels . indemnité kilométrique vélo
|
||||
- (- frais professionnels . titres-restaurant . participation employeur)
|
||||
- frais professionnels . titres-restaurant . participation salarié
|
||||
- prime d'impatriation
|
||||
- exonération d'impôt des stagiaires et apprentis
|
||||
- heures supplémentaires et complémentaires défiscalisées
|
||||
|
|
|
@ -4,29 +4,26 @@ import { findRuleByDottedName, getRuleFromAnalysis } from 'Engine/rules'
|
|||
import React, { Fragment, useContext } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import {
|
||||
analysisWithDefaultsSelector,
|
||||
parsedRulesSelector
|
||||
} from 'Selectors/analyseSelectors'
|
||||
import { analysisWithDefaultsSelector, parsedRulesSelector } from 'Selectors/analyseSelectors'
|
||||
import { analysisToCotisationsSelector } from 'Selectors/ficheDePaieSelectors'
|
||||
import './PaySlip.css'
|
||||
import { Line, SalaireBrutSection, SalaireNetSection } from './PaySlipSections'
|
||||
import RuleLink from './RuleLink'
|
||||
|
||||
export default function PaySlip() {
|
||||
const { lightestColor } = useContext(ThemeColorsContext)
|
||||
const cotisations = useSelector(analysisToCotisationsSelector)
|
||||
const analysis = useSelector(analysisWithDefaultsSelector)
|
||||
const parsedRules = useSelector(parsedRulesSelector)
|
||||
let getRule = getRuleFromAnalysis(analysis)
|
||||
const { lightestColor } = useContext(ThemeColorsContext)
|
||||
const cotisations = useSelector(analysisToCotisationsSelector)
|
||||
const analysis = useSelector(analysisWithDefaultsSelector)
|
||||
const parsedRules = useSelector(parsedRulesSelector)
|
||||
let getRule = getRuleFromAnalysis(analysis)
|
||||
|
||||
const heuresSupplémentaires = getRule(
|
||||
'contrat salarié . temps de travail . heures supplémentaires'
|
||||
)
|
||||
return (
|
||||
<div
|
||||
className="payslip__container"
|
||||
css={`
|
||||
const heuresSupplémentaires = getRule(
|
||||
'contrat salarié . temps de travail . heures supplémentaires'
|
||||
)
|
||||
return (
|
||||
<div
|
||||
className="payslip__container"
|
||||
css={`
|
||||
.value {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
@ -34,89 +31,91 @@ export default function PaySlip() {
|
|||
padding-right: 0.2em;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<div className="payslip__salarySection">
|
||||
<Line
|
||||
rule={getRule('contrat salarié . temps de travail')}
|
||||
unit="heures/mois"
|
||||
maximumFractionDigits={1}
|
||||
/>
|
||||
{heuresSupplémentaires?.nodeValue > 0 && (
|
||||
<Line
|
||||
rule={heuresSupplémentaires}
|
||||
unit="heures/mois"
|
||||
maximumFractionDigits={1}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
>
|
||||
<div className="payslip__salarySection">
|
||||
<Line
|
||||
rule={getRule('contrat salarié . temps de travail')}
|
||||
unit="heures/mois"
|
||||
maximumFractionDigits={1}
|
||||
/>
|
||||
{heuresSupplémentaires?.nodeValue > 0 && (
|
||||
<Line
|
||||
rule={heuresSupplémentaires}
|
||||
unit="heures/mois"
|
||||
maximumFractionDigits={1}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<SalaireBrutSection getRule={getRule} />
|
||||
{/* Section cotisations */}
|
||||
<div className="payslip__cotisationsSection">
|
||||
<h4>
|
||||
<Trans>Cotisations sociales</Trans>
|
||||
</h4>
|
||||
<h4>
|
||||
<Trans>Part employeur</Trans>
|
||||
</h4>
|
||||
<h4>
|
||||
<Trans>Part salarié</Trans>
|
||||
</h4>
|
||||
{cotisations.map(([brancheDottedName, cotisationList]) => {
|
||||
let branche = findRuleByDottedName(parsedRules, brancheDottedName)
|
||||
return (
|
||||
<Fragment key={branche.dottedName}>
|
||||
<h5 className="payslip__cotisationTitle">
|
||||
<RuleLink {...branche} />
|
||||
</h5>
|
||||
{cotisationList.map(cotisation => (
|
||||
<Fragment key={cotisation.dottedName}>
|
||||
<RuleLink
|
||||
style={{ backgroundColor: lightestColor }}
|
||||
{...cotisation}
|
||||
/>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
unit="€"
|
||||
customCSS="background-color: var(--lightestColor)"
|
||||
>
|
||||
{cotisation.montant.partPatronale}
|
||||
</Value>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
unit="€"
|
||||
customCSS="background-color: var(--lightestColor)"
|
||||
>
|
||||
{cotisation.montant.partSalariale}
|
||||
</Value>
|
||||
</Fragment>
|
||||
))}
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
<SalaireBrutSection getRule={getRule} />
|
||||
{/* Section cotisations */}
|
||||
<div className="payslip__cotisationsSection">
|
||||
<h4>
|
||||
<Trans>Cotisations sociales</Trans>
|
||||
</h4>
|
||||
<h4>
|
||||
<Trans>Part employeur</Trans>
|
||||
</h4>
|
||||
<h4>
|
||||
<Trans>Part salarié</Trans>
|
||||
</h4>
|
||||
{cotisations.map(([brancheDottedName, cotisationList]) => {
|
||||
let branche = findRuleByDottedName(parsedRules, brancheDottedName)
|
||||
return (
|
||||
<Fragment key={branche.dottedName}>
|
||||
<h5 className="payslip__cotisationTitle">
|
||||
<RuleLink {...branche} />
|
||||
</h5>
|
||||
{cotisationList.map(cotisation => (
|
||||
<Fragment key={cotisation.dottedName}>
|
||||
<RuleLink
|
||||
style={{ backgroundColor: lightestColor }}
|
||||
{...cotisation}
|
||||
/>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
unit="€"
|
||||
customCSS="background-color: var(--lightestColor)"
|
||||
>
|
||||
{cotisation.montant.partPatronale}
|
||||
</Value>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
unit="€"
|
||||
customCSS="background-color: var(--lightestColor)"
|
||||
>
|
||||
{cotisation.montant.partSalariale}
|
||||
</Value>
|
||||
</Fragment>
|
||||
))}
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
|
||||
{/* Total cotisation */}
|
||||
<div className="payslip__total">
|
||||
<Trans>Total des retenues</Trans>
|
||||
</div>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
{...getRule('contrat salarié . cotisations . patronales')}
|
||||
unit="€"
|
||||
className="payslip__total"
|
||||
/>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
{...getRule('contrat salarié . cotisations . salariales')}
|
||||
unit="€"
|
||||
className="payslip__total"
|
||||
/>
|
||||
{/* Salaire chargé */}
|
||||
<Line rule={getRule('contrat salarié . rémunération . total')} />
|
||||
<span />
|
||||
</div>
|
||||
{/* Section salaire net */}
|
||||
<SalaireNetSection getRule={getRule} />
|
||||
</div>
|
||||
)
|
||||
{/* Total cotisation */}
|
||||
<div className="payslip__total">
|
||||
<Trans>Total des retenues</Trans>
|
||||
</div>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
{...getRule('contrat salarié . cotisations . patronales')}
|
||||
unit="€"
|
||||
className="payslip__total"
|
||||
/>
|
||||
<Value
|
||||
nilValueSymbol="—"
|
||||
{...getRule('contrat salarié . cotisations . salariales')}
|
||||
unit="€"
|
||||
className="payslip__total"
|
||||
/>
|
||||
{/* Salaire chargé */}
|
||||
<Line rule={getRule('contrat salarié . rémunération . total')} />
|
||||
<span />
|
||||
{/* Titres-restaurant */}
|
||||
<Line rule={getRule('contrat salarié . frais professionnels . titres-restaurant . participation salarié')} />
|
||||
</div>
|
||||
{/* Section salaire net */}
|
||||
<SalaireNetSection getRule={getRule} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import { rules as realRules } from '../source/engine/rules'
|
|||
import { analyse, analyseMany, parseAll } from '../source/engine/traverse'
|
||||
|
||||
describe('bug-analyse-many', function () {
|
||||
it('complex inversion with composantes', () => {
|
||||
let rawRules = dedent`
|
||||
it('complex inversion with composantes', () => {
|
||||
let rawRules = dedent`
|
||||
- nom: net
|
||||
formule: brut - cotisations
|
||||
- nom: cotisations
|
||||
|
@ -48,48 +48,48 @@ describe('bug-analyse-many', function () {
|
|||
avec:
|
||||
- net
|
||||
`,
|
||||
rules = parseAll(safeLoad(rawRules).map(enrichRule)),
|
||||
stateSelector = name => ({ net: 700 }[name])
|
||||
const targets = ['brut', 'cotisations']
|
||||
const many = analyseMany(rules, targets)(stateSelector).targets
|
||||
rules = parseAll(safeLoad(rawRules).map(enrichRule)),
|
||||
stateSelector = name => ({ net: 700 }[name])
|
||||
const targets = ['brut', 'cotisations']
|
||||
const many = analyseMany(rules, targets)(stateSelector).targets
|
||||
|
||||
const one = analyse(rules, 'cotisations')(stateSelector).targets[0]
|
||||
const one = analyse(rules, 'cotisations')(stateSelector).targets[0]
|
||||
|
||||
//console.log(many[0].nodeValue, many[1].nodeValue, one.nodeValue)
|
||||
expect(many[1].nodeValue).to.be.closeTo(one.nodeValue, 0.1)
|
||||
})
|
||||
it('should compute the same contributions if asked with analyseMany or analyse', function () {
|
||||
const situationSelector = dottedName =>
|
||||
({
|
||||
'contrat salarié . rémunération . net de cotisations': 3500,
|
||||
'auto-entrepreneur': 'non',
|
||||
'contrat salarié': 'oui',
|
||||
dirigeant: 'assimilé salarié',
|
||||
'contrat salarié . ATMP . taux réduit': 'oui',
|
||||
'contrat salarié . CDD': 'non',
|
||||
'contrat salarié . frais professionnels . indemnité kilométrique vélo . indemnité vélo active':
|
||||
'non',
|
||||
'contrat salarié . rémunération . avantages en nature . montant': 0,
|
||||
'contrat salarié . temps partiel': 'non',
|
||||
'établissement . localisation': {},
|
||||
'contrat salarié . complémentaire santé . part employeur': 50,
|
||||
'contrat salarié . complémentaire santé . forfait . en france': 50,
|
||||
'entreprise . effectif': 1,
|
||||
'entreprise . association non lucrative': 'non'
|
||||
}[dottedName])
|
||||
const rules = parseAll(realRules.map(enrichRule))
|
||||
const targets = [
|
||||
'contrat salarié . rémunération . brut de base',
|
||||
'contrat salarié . cotisations . salariales'
|
||||
]
|
||||
const analyseManyValue = analyseMany(rules, targets)(situationSelector)
|
||||
.targets[1]
|
||||
const analyseValue = analyse(
|
||||
rules,
|
||||
'contrat salarié . cotisations . salariales'
|
||||
)(situationSelector).targets[0]
|
||||
//console.log(many[0].nodeValue, many[1].nodeValue, one.nodeValue)
|
||||
expect(many[1].nodeValue).to.be.closeTo(one.nodeValue, 0.1)
|
||||
})
|
||||
it('should compute the same contributions if asked with analyseMany or analyse', function () {
|
||||
const situationSelector = dottedName =>
|
||||
({
|
||||
'contrat salarié . rémunération . net de cotisations': 3500,
|
||||
'auto-entrepreneur': 'non',
|
||||
'contrat salarié': 'oui',
|
||||
dirigeant: 'assimilé salarié',
|
||||
'contrat salarié . ATMP . taux réduit': 'oui',
|
||||
'contrat salarié . CDD': 'non',
|
||||
'contrat salarié . frais professionnels . indemnité kilométrique vélo . indemnité vélo active':
|
||||
'non',
|
||||
'contrat salarié . rémunération . avantages en nature . montant': 0,
|
||||
'contrat salarié . temps partiel': 'non',
|
||||
'établissement . localisation': {},
|
||||
'contrat salarié . complémentaire santé . part employeur': 50,
|
||||
'contrat salarié . complémentaire santé . forfait . en france': 50,
|
||||
'entreprise . effectif': 1,
|
||||
'entreprise . association non lucrative': 'non'
|
||||
}[dottedName])
|
||||
const rules = parseAll(realRules.map(enrichRule))
|
||||
const targets = [
|
||||
'contrat salarié . rémunération . brut de base',
|
||||
'contrat salarié . cotisations . salariales'
|
||||
]
|
||||
const analyseManyValue = analyseMany(rules, targets)(situationSelector)
|
||||
.targets[1]
|
||||
const analyseValue = analyse(
|
||||
rules,
|
||||
'contrat salarié . cotisations . salariales'
|
||||
)(situationSelector).targets[0]
|
||||
|
||||
console.log(analyseManyValue.nodeValue, analyseValue.nodeValue)
|
||||
expect(analyseManyValue.nodeValue).to.equal(analyseValue.nodeValue)
|
||||
})
|
||||
console.log(analyseManyValue.nodeValue, analyseValue.nodeValue)
|
||||
expect(analyseManyValue.nodeValue).to.equal(analyseValue.nodeValue)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue