feat(lodeom): ajout de la sélection de zone

Alice Dahan 2024-12-23 17:42:00 +01:00
parent 78e166e245
commit 70538cc6dc
9 changed files with 223 additions and 81 deletions

View File

@ -1,51 +0,0 @@
import { useDispatch } from 'react-redux'
import { useEngine } from '@/components/utils/EngineContext'
import { toOuiNon } from '@/domaine/engine/toOuiNon'
import { batchUpdateSituation } from '@/store/actions/actions'
const barèmesPossibles = [
'barème compétitivité',
'barème compétitivité renforcée',
'barème innovation et croissance',
]
export type Barème = (typeof barèmesPossibles)[number]
type ReturnType = {
barèmesPossibles: Barème[]
currentBarème?: Barème
updateBarème: (barème: Barème) => void
}
export const useBaremeLodeom = (): ReturnType => {
const dottedName = 'salarié . cotisations . exonérations . lodeom . zone un'
const engine = useEngine()
const dispatch = useDispatch()
let currentBarème
for (let i = 0; i < barèmesPossibles.length; i++) {
const barème = barèmesPossibles[i]
const barèmeValue = engine.evaluate(`${dottedName} . ${barème}`).nodeValue
if (barèmeValue) {
currentBarème = barème
break
}
}
const updateBarème = (newBarème: Barème): void => {
const newSituation = barèmesPossibles.reduce((situation, barème) => {
return {
...situation,
[`${dottedName} . ${barème}`]: toOuiNon(barème === newBarème),
}
}, {})
dispatch(batchUpdateSituation(newSituation))
}
return {
barèmesPossibles,
currentBarème,
updateBarème,
}
}

View File

@ -0,0 +1,77 @@
import { DottedName } from 'modele-social'
import { useDispatch } from 'react-redux'
import { useEngine } from '@/components/utils/EngineContext'
import { toOuiNon } from '@/domaine/engine/toOuiNon'
import {
batchUpdateSituation,
deleteFromSituation,
} from '@/store/actions/actions'
import { useZoneLodeom, ZoneLodeom as Zone } from './useZoneLodeom'
const barèmes = {
['zone un' as Zone]: [
'barème compétitivité',
'barème compétitivité renforcée',
'barème innovation et croissance',
],
['zone deux' as Zone]: [
'barème moins de 11 salariés',
'barème sectoriel',
'barème compétitivité',
],
}
export type Barème = (typeof barèmes)[Zone][number]
type ReturnType = {
barèmes: Barème[]
currentBarème?: Barème
updateBarème: (barème?: Barème) => void
}
export const useBarèmeLodeom = (): ReturnType => {
const dottedName = 'salarié . cotisations . exonérations . lodeom'
const { currentZone } = useZoneLodeom()
const engine = useEngine()
const dispatch = useDispatch()
const barèmesPossibles = currentZone ? barèmes[currentZone] : []
const currentBarème = barèmesPossibles.find((barème) => {
const barèmeValue = engine.evaluate(
`${dottedName} . ${currentZone} . ${barème}`
).nodeValue
return !!barèmeValue
})
const updateBarème = (newBarème?: Barème): void => {
if (!newBarème) {
barèmesPossibles.forEach((barème) => {
dispatch(
deleteFromSituation(
`${dottedName} . ${currentZone} . ${barème}` as DottedName
)
)
})
} else {
const newSituation = barèmesPossibles.reduce((situation, barème) => {
return {
...situation,
[`${dottedName} . ${currentZone} . ${barème}`]: toOuiNon(
barème === newBarème
),
}
}, {})
dispatch(batchUpdateSituation(newSituation))
}
}
return {
barèmes: barèmesPossibles,
currentBarème,
updateBarème,
}
}

View File

@ -0,0 +1,38 @@
import { useDispatch } from 'react-redux'
import { useEngine } from '@/components/utils/EngineContext'
import { toOuiNon } from '@/domaine/engine/toOuiNon'
import { batchUpdateSituation } from '@/store/actions/actions'
const zones = ['zone un', 'zone deux']
export type ZoneLodeom = (typeof zones)[number]
type ReturnType = {
currentZone?: ZoneLodeom
updateZone: (zone: ZoneLodeom) => void
}
export const useZoneLodeom = (): ReturnType => {
const engine = useEngine()
const dispatch = useDispatch()
const dottedName = 'salarié . cotisations . exonérations . lodeom'
const currentZone = zones.find((zone) => {
const zoneValue = engine.evaluate(`${dottedName} . ${zone}`).nodeValue
return !!zoneValue
})
const updateZone = (newZone: ZoneLodeom): void => {
const newSituation = zones.reduce((situation, zone) => {
return {
...situation,
[`${dottedName} . ${zone}`]: toOuiNon(zone === newZone),
}
}, {})
dispatch(batchUpdateSituation(newSituation))
}
return { currentZone, updateZone }
}

View File

@ -7,7 +7,8 @@ import RéductionMoisParMois from '@/components/RéductionDeCotisations/Réducti
import { SimulationGoals } from '@/components/Simulation'
import { useEngine } from '@/components/utils/EngineContext'
import useYear from '@/components/utils/useYear'
import { Barème, useBaremeLodeom } from '@/hooks/useBaremeLodeom'
import { Barème, useBarèmeLodeom } from '@/hooks/useBarèmeLodeom'
import { useZoneLodeom, ZoneLodeom } from '@/hooks/useZoneLodeom'
import { situationSelector } from '@/store/selectors/simulationSelectors'
import {
getDataAfterOptionsChange,
@ -41,7 +42,8 @@ export default function LodeomSimulationGoals({
const year = useYear()
const situation = useSelector(situationSelector) as SituationType
const previousSituation = useRef(situation)
const { currentBarème } = useBaremeLodeom()
const { currentZone } = useZoneLodeom()
const { currentBarème } = useBarèmeLodeom()
const { t } = useTranslation()
const initializeLodeomMoisParMoisData = useCallback(() => {
@ -102,17 +104,51 @@ export default function LodeomSimulationGoals({
}
const codesByBareme = {
['barème compétitivité' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.462', 'code 462'),
régularisation: t('pages.simulateurs.lodeom.recap.code.684', 'code 684'),
['zone un' as ZoneLodeom]: {
['barème compétitivité' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.462', 'code 462'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.684',
'code 684'
),
},
['barème compétitivité renforcée' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.463', 'code 463'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.538',
'code 538'
),
},
['barème innovation et croissance' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.473', 'code 473'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.685',
'code 685'
),
},
},
['barème compétitivité renforcée' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.463', 'code 463'),
régularisation: t('pages.simulateurs.lodeom.recap.code.538', 'code 538'),
},
['barème innovation et croissance' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.473', 'code 473'),
régularisation: t('pages.simulateurs.lodeom.recap.code.685', 'code 685'),
['zone deux' as ZoneLodeom]: {
['barème moins de 11 salariés' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.463', 'code 463'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.538',
'code 538'
),
},
['barème sectoriel' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.473', 'code 473'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.685',
'code 685'
),
},
['barème compétitivité' as Barème]: {
réduction: t('pages.simulateurs.lodeom.recap.code.462', 'code 462'),
régularisation: t(
'pages.simulateurs.lodeom.recap.code.684',
'code 684'
),
},
},
}
@ -132,10 +168,14 @@ export default function LodeomSimulationGoals({
warningCondition={`${lodeomDottedName} = 0`}
warningTooltip={<WarningSalaireTrans />}
codeRéduction={
currentBarème && codesByBareme[currentBarème].réduction
currentZone &&
currentBarème &&
codesByBareme[currentZone][currentBarème].réduction
}
codeRégularisation={
currentBarème && codesByBareme[currentBarème].régularisation
currentZone &&
currentBarème &&
codesByBareme[currentZone][currentBarème].régularisation
}
/>
) : (

View File

@ -7,9 +7,11 @@ import RégularisationSwitch from '@/components/RéductionDeCotisations/Régular
import { SelectSimulationYear } from '@/components/SelectSimulationYear'
import SimulateurWarning from '@/components/SimulateurWarning'
import Simulation from '@/components/Simulation'
import { useZoneLodeom } from '@/hooks/useZoneLodeom'
import { RégularisationMethod } from '@/utils/réductionDeCotisations'
import BarèmeSwitch from './components/BarèmeSwitch'
import ZoneSwitch from './components/ZoneSwitch'
import LodeomSimulationGoals from './Goals'
export default function LodeomSimulation() {
@ -39,10 +41,14 @@ export default function LodeomSimulation() {
const [régularisationMethod, setRégularisationMethod] =
useState<RégularisationMethod>('progressive')
const { currentZone } = useZoneLodeom()
return (
<>
<Simulation afterQuestionsSlot={<SelectSimulationYear />}>
<SimulateurWarning simulateur="lodeom" />
<ZoneSwitch />
<BarèmeSwitch />
<LodeomSimulationGoals
monthByMonth={monthByMonth}
legend={t(
@ -51,12 +57,15 @@ export default function LodeomSimulation() {
)}
toggles={
<>
<BarèmeSwitch />
<RégularisationSwitch
régularisationMethod={régularisationMethod}
setRégularisationMethod={setRégularisationMethod}
/>
<EffectifSwitch />
{currentZone === 'zone un' && (
<>
<RégularisationSwitch
régularisationMethod={régularisationMethod}
setRégularisationMethod={setRégularisationMethod}
/>
<EffectifSwitch />
</>
)}
<PeriodSwitch periods={periods} onSwitch={onPeriodSwitch} />
</>
}

View File

@ -6,12 +6,14 @@ import { ExplicableRule } from '@/components/conversation/Explicable'
import { useEngine } from '@/components/utils/EngineContext'
import { Radio, ToggleGroup } from '@/design-system'
import { FlexCenter } from '@/design-system/global-style'
import { useBaremeLodeom } from '@/hooks/useBaremeLodeom'
import { useBarèmeLodeom } from '@/hooks/useBarèmeLodeom'
import { useZoneLodeom } from '@/hooks/useZoneLodeom'
export default function BarèmeSwitch() {
const { t } = useTranslation()
const engine = useEngine()
const { barèmesPossibles, currentBarème, updateBarème } = useBaremeLodeom()
const { currentZone } = useZoneLodeom()
const { barèmes, currentBarème, updateBarème } = useBarèmeLodeom()
return (
<Container>
@ -23,9 +25,9 @@ export default function BarèmeSwitch() {
'Barème à appliquer'
)}
>
{barèmesPossibles.map((barème, index) => {
{barèmes.map((barème, index) => {
const dottedName =
`salarié . cotisations . exonérations . lodeom . zone un . ${barème}` as DottedName
`salarié . cotisations . exonérations . lodeom . ${currentZone} . ${barème}` as DottedName
const rule = engine.getRule(dottedName)
return (
@ -33,9 +35,7 @@ export default function BarèmeSwitch() {
{rule.title}
<ExplicableRule
light
dottedName={
`salarié . cotisations . exonérations . lodeom . zone un . ${barème}` as DottedName
}
dottedName={dottedName}
aria-label={t("Plus d'informations sur {{ title }}", {
title: barème,
})}

View File

@ -1,9 +1,9 @@
import { Trans } from 'react-i18next'
import { useBaremeLodeom } from '@/hooks/useBaremeLodeom'
import { useBarèmeLodeom } from '@/hooks/useBarèmeLodeom'
export default function WarningSalaireTrans() {
const { currentBarème } = useBaremeLodeom()
const { currentBarème } = useBarèmeLodeom()
return (
<>

View File

@ -0,0 +1,27 @@
import { useTranslation } from 'react-i18next'
import { Radio, ToggleGroup } from '@/design-system'
import { useBarèmeLodeom } from '@/hooks/useBarèmeLodeom'
import { useZoneLodeom } from '@/hooks/useZoneLodeom'
export default function ZoneSwitch() {
const { currentZone, updateZone } = useZoneLodeom()
const { updateBarème } = useBarèmeLodeom()
const { t } = useTranslation()
return (
<ToggleGroup
value={currentZone}
onChange={(value) => {
updateBarème()
updateZone(value)
}}
aria-label={t("Zone de l'entreprise")}
>
<Radio value="zone un">
{t('Guadeloupe, Guyane, Martinique, La Réunion')}
</Radio>
<Radio value="zone deux">{t('Saint-Barthélémy, Saint-Martin')}</Radio>
</ToggleGroup>
)
}

View File

@ -29,6 +29,9 @@ export const configRéductionGénérale: SimulationConfig = {
},
],
'liste noire': [
'établissement . commune',
'salarié . cotisations . exonérations . lodeom . zone un . barème compétitivité renforcée',
'salarié . cotisations . exonérations . lodeom . zone un . barème innovation et croissance',
'entreprise . salariés . effectif . seuil',
'salarié . contrat . CDD . motif',
'salarié . rémunération . primes . activité . base',
@ -41,6 +44,5 @@ export const configRéductionGénérale: SimulationConfig = {
dirigeant: 'non',
'entreprise . catégorie juridique': "''",
'entreprise . imposition': 'non',
'salarié . cotisations . exonérations . lodeom . zone un': "'oui'",
},
}