Ajoute la déclaration dans la situation

pull/2092/head
Johan Girod 2022-04-20 15:16:10 +02:00
parent 389ecbcd07
commit 1723256ccf
8 changed files with 222 additions and 182 deletions

View File

@ -518,6 +518,7 @@ DRI . liasse . déclaration contrôlée . CN:
DRI . informations complémentaires: oui
DRI . informations complémentaires . OGA:
titre: Adhérent OGA
applicable si: entreprise . imposition . IR
question: Êtes-vous adhérant à un Organisme de Gestion Agrée (OGA) ?
par défaut: oui

View File

@ -615,6 +615,7 @@ dirigeant . indépendant . cotisations et contributions . exonérations . ACRE .
plafond: 100%
dirigeant . indépendant . conjoint collaborateur . assiette:
titre: Choix assiette (conjoint collaborateur)
question: Sur quelle base le conjoint cotise-t'il ?
description: |
Le conjoint collaborateur dispose de trois choix dassiette pour le calcul de ces cotisations :
@ -656,6 +657,7 @@ dirigeant . indépendant . conjoint collaborateur . assiette . revenu sans parta
formule: assiette = 'revenu sans partage'
dirigeant . indépendant . conjoint collaborateur . assiette . pourcentage:
titre: Proportion revenu (conjoint collaborateur)
question: À quelle proportion du revenu le conjoint cotise-t'il ?
par défaut: "'tiers'"
formule:

View File

@ -27,9 +27,10 @@ import RuleInput from './RuleInput'
type AnswerListProps = {
onClose: () => void
children?: React.ReactNode
}
export default function AnswerList({ onClose }: AnswerListProps) {
export default function AnswerList({ onClose, children }: AnswerListProps) {
const dispatch = useDispatch()
const engine = useEngine()
const situation = useSelector(situationSelector)
@ -75,7 +76,9 @@ export default function AnswerList({ onClose }: AnswerListProps) {
</H3>
<StepsTable {...{ rules: answeredAndPassedQuestions, onClose }} />
<Spacing sm />
{children}
<Spacing lg />
<div
css={`
text-align: center;
@ -92,14 +95,13 @@ export default function AnswerList({ onClose }: AnswerListProps) {
</div>
</>
)}
{companyQuestions.length > 0 && (
<>
<Trans>
<H3>Mon entreprise</H3>
</Trans>
<StepsTable {...{ rules: companyQuestions, onClose }} />
<Spacing sm />
<Spacing lg />
<div
css={`
text-align: center;
@ -152,6 +154,7 @@ function StepsTable({
>
<Grid item xs>
{rule.title}
<ExplicableRule light dottedName={rule.dottedName} />
</Grid>
<StyledAnswer item xs="auto">
<AnswerElement {...rule} />

View File

@ -1,4 +1,3 @@
import { Grid } from '@mui/material'
import { goToQuestion, stepAction, updateSituation } from '@/actions/actions'
import RuleInput from '@/components/conversation/RuleInput'
import Notifications from '@/components/Notifications'
@ -10,24 +9,29 @@ import { Button } from '@/design-system/buttons'
import { Spacing } from '@/design-system/layout'
import { H3 } from '@/design-system/typography/heading'
import { Body } from '@/design-system/typography/paragraphs'
import { PublicodesExpression } from 'publicodes'
import React, { useContext, useEffect } from 'react'
import { Trans } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import {
answeredQuestionsSelector,
situationSelector,
} from '@/selectors/simulationSelectors'
import { evaluateQuestion } from '@/utils'
import { Grid } from '@mui/material'
import { PublicodesExpression } from 'publicodes'
import React, { useContext, useEffect } from 'react'
import { Trans } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { TrackPage } from '../../ATInternetTracking'
import { ExplicableRule } from './Explicable'
import SeeAnswersButton from './SeeAnswersButton'
import { evaluateQuestion } from '@/utils'
export type ConversationProps = {
customEndMessages?: React.ReactNode
customSituationVisualisation?: React.ReactNode
}
export default function Conversation({ customEndMessages }: ConversationProps) {
export default function Conversation({
customEndMessages,
customSituationVisualisation,
}: ConversationProps) {
const dispatch = useDispatch()
const engine = useContext(EngineContext)
const currentQuestion = useNextQuestions()[0]
@ -104,7 +108,7 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
</Button>
</Grid>
<Grid container item xs={12} sm justifyContent="flex-end">
<SeeAnswersButton />
<SeeAnswersButton>{customSituationVisualisation}</SeeAnswersButton>
</Grid>
</Grid>
<Notifications />
@ -136,7 +140,7 @@ export default function Conversation({ customEndMessages }: ConversationProps) {
</Grid>
)}
<Grid container item xs={6} sm justifyContent="flex-end">
<SeeAnswersButton />
<SeeAnswersButton>{customSituationVisualisation}</SeeAnswersButton>
</Grid>
</Grid>
<Spacing lg />

View File

@ -1,9 +1,14 @@
import { Button } from '@/design-system/buttons'
import { PopoverWithTrigger } from '@/design-system'
import { Button } from '@/design-system/buttons'
import React from 'react'
import { Trans } from 'react-i18next'
import Answers from './AnswerList'
export default function SeeAnswersButton() {
export default function SeeAnswersButton({
children,
}: {
children?: React.ReactNode
}) {
return (
<PopoverWithTrigger
trigger={(buttonProps) => (
@ -12,7 +17,7 @@ export default function SeeAnswersButton() {
</Button>
)}
>
{(close) => <Answers onClose={close} />}
{(close) => <Answers onClose={close}>{children}</Answers>}
</PopoverWithTrigger>
)
}

View File

@ -91,35 +91,12 @@ function getAllCases(rule: RuleNode): string[] {
}
export function DéclarationRevenuSection({ progress }: { progress: number }) {
const fields = useDéclarationRevenuFields()
const sitePaths = useContext(SitePathsContext)
const engine = useEngine()
const caseName =
engine.evaluate('DRI . informations complémentaires . OGA').nodeValue ===
false
? 'sans OGA'
: 'défaut'
const getCases = useCallback(
(rule: Rule): string[] => {
const meta = getMeta<Meta>(rule, {})
return (
(Array.isArray(meta.cases) && meta.cases) ||
(typeof meta.cases === 'object' && meta.cases[caseName]) ||
[]
)
},
[caseName]
)
const déclarationRevenusManuel = engine.evaluate(
'DRI . déclaration revenus manuelle'
).nodeValue
const declarant =
engine.evaluate('DRI . déclarant').nodeValue === 'déclarant 2' ? 1 : 0
).nodeValue as boolean
if (!déclarationRevenusManuel && progress !== 1) {
return null
@ -167,57 +144,7 @@ export function DéclarationRevenuSection({ progress }: { progress: number }) {
justifyContent="space-between"
>
<SimpleField dottedName="DRI . déclarant" />
{fields.map(([dottedName, rule]) =>
getMeta<Meta>(rule.rawNode, {})?.section === 'oui' ? (
<Grid item xs={12} key={dottedName}>
{rule.dottedName.split(' . ').length === 2 ? (
<RuleInputWithTitle
title={rule.rawNode.question}
dottedName={dottedName}
/>
) : rule.dottedName.split(' . ').length === 3 ? (
<H3>{rule.title}</H3>
) : (
<H4
css={`
margin-top: 0rem;
`}
>
{rule.title}
</H4>
)}
</Grid>
) : (
<Fragment key={dottedName}>
<Grid item xs={12} md={8}>
<Body>
{rule.title} <em>{rule.rawNode.note}</em>
</Body>
</Grid>
{déclarationRevenusManuel ? (
<Grid item sm={12} md>
<SimpleField
label={getAllCases(rule).join(' / ')}
dottedName={dottedName}
/>
</Grid>
) : (
<Grid item xs="auto">
<Body>
<Strong>{getCases(rule.rawNode)[declarant]}</Strong>
<StyledCase>
<Value
expression={dottedName}
linkToRule={false}
/>
</StyledCase>
</Body>
</Grid>
)}
</Fragment>
)
)}
<DéclarationRevenu editable={déclarationRevenusManuel} />
</Grid>
{déclarationRevenusManuel && (
<SmallBody>
@ -225,9 +152,8 @@ export function DéclarationRevenuSection({ progress }: { progress: number }) {
continuer. Si un champs est vide, inscrivez la valeur 0.
</SmallBody>
)}
<ShareOrSaveSimulationBanner share print />
<Spacing xl />
<Spacing lg />
<Grid
xs={12}
@ -245,6 +171,8 @@ export function DéclarationRevenuSection({ progress }: { progress: number }) {
</Button>
</Grid>
<Spacing md />
<ShareOrSaveSimulationBanner share print />
<Spacing lg />
</Message>
</Grid>
{!déclarationRevenusManuel && (
@ -280,6 +208,88 @@ export function DéclarationRevenuSection({ progress }: { progress: number }) {
)
}
export function DéclarationRevenu({
editable = false,
}: {
editable?: boolean
}) {
const fields = useDéclarationRevenuFields()
const engine = useEngine()
const caseName =
engine.evaluate('DRI . informations complémentaires . OGA').nodeValue ===
false
? 'sans OGA'
: 'défaut'
const getCases = useCallback(
(rule: Rule): string[] => {
const meta = getMeta<Meta>(rule, {})
return (
(Array.isArray(meta.cases) && meta.cases) ||
(typeof meta.cases === 'object' && meta.cases[caseName]) ||
[]
)
},
[caseName]
)
const declarant =
engine.evaluate('DRI . déclarant').nodeValue === 'déclarant 2' ? 1 : 0
return (
<>
{fields.map(([dottedName, rule]) =>
getMeta<Meta>(rule.rawNode, {})?.section === 'oui' ? (
<Grid item xs={12} key={dottedName}>
{rule.dottedName.split(' . ').length === 2 ? (
<RuleInputWithTitle
title={rule.rawNode.question}
dottedName={dottedName}
/>
) : rule.dottedName.split(' . ').length === 3 ? (
<H3>{rule.title}</H3>
) : (
<H4
css={`
margin-top: 0rem;
`}
>
{rule.title}
</H4>
)}
</Grid>
) : (
<Fragment key={dottedName}>
<Grid item xs={12} md={8}>
<Body>
{rule.title} <em>{rule.rawNode.note}</em>
</Body>
</Grid>
{editable ? (
<Grid item sm={12} md>
<SimpleField
label={getAllCases(rule).join(' / ')}
dottedName={dottedName}
/>
</Grid>
) : (
<Grid item xs="auto">
<Body>
<Strong>{getCases(rule.rawNode)[declarant]}</Strong>
<StyledCase>
<Value expression={dottedName} linkToRule={false} />
</StyledCase>
</Body>
</Grid>
)}
</Fragment>
)
)}
</>
)
}
const StyledCase = styled.span`
border: 1px solid ${({ theme }) => theme.colors.bases.primary[800]};
border-top: none;

View File

@ -13,6 +13,7 @@ import { H2, H3 } from '@/design-system/typography/heading'
import { Body, Intro } from '@/design-system/typography/paragraphs'
import { Grid } from '@mui/material'
import { SimpleField } from '../_components/Fields'
import { DéclarationRevenu } from './_components/DéclarationRevenu'
export default function Cotisations() {
const progress = useSimulationProgress()
@ -36,86 +37,98 @@ export default function Cotisations() {
darkMode
backgroundColor={(theme) => theme.colors.bases.primary[600]}
>
<Grid container columnSpacing={4} rowSpacing={2}>
<Grid item lg={10} xl={8}>
<H2>Estimation des cotisations à payer</H2>
<Body>
Voici votre estimation personalisée, calculée sur la base des
éléments renseignées sur la déclaration de revenu de la page
précédente :
</Body>
<Message icon border={false}>
<Intro>
<Condition expression="DRI . cotisations >= 0">
En 2022, vous devrez payer à l'Urssaf{' '}
<Strong>
{' '}
<Value expression="DRI . cotisations" />
</Strong>{' '}
de cotisations sociales.
</Condition>
<Condition expression="DRI . cotisations < 0">
En 2022, l'Urssaf vous remboursera{' '}
<Strong>
{' '}
<Value expression="DRI . cotisations * -1" />
</Strong>{' '}
</Condition>
</Intro>
</Message>
<FromTop>
<Grid container columnSpacing={4} rowSpacing={2}>
<Grid item lg={10} xl={8}>
<FromTop>
<H2>Estimation des cotisations à payer</H2>
<Body>
Voici votre estimation personalisée, calculée sur la base
des éléments renseignées sur la déclaration de revenu de la
page précédente :
</Body>
<Message icon border={false}>
<Intro>
<Condition expression="DRI . cotisations >= 0">
En 2022, vous devrez payer à l'Urssaf{' '}
<Strong>
{' '}
<Value expression="DRI . cotisations" />
</Strong>{' '}
de cotisations sociales.
</Condition>
<Condition expression="DRI . cotisations < 0">
En 2022, l'Urssaf vous remboursera{' '}
<Strong>
{' '}
<Value expression="DRI . cotisations * -1" />
</Strong>{' '}
</Condition>
</Intro>
</Message>
<Intro>
Améliorez cette estimation en répondant aux questions suivantes
pour l'année 2021
</Intro>
<Message border={false}>
<div
css={`
margin: -0.75rem 0;
`}
>
<Conversation />
<div
css={`
position: relative;
top: -2px;
margin: 0 -1.5rem;
`}
>
<Progress progress={progress} />
</div>
</div>
</Message>
<Intro>
Améliorez cette estimation en répondant aux questions
suivantes pour l'année 2021
</Intro>
<Message border={false}>
<div
css={`
margin: -0.75rem 0;
`}
>
<Conversation
customSituationVisualisation={
<>
<Grid container>
<DéclarationRevenu editable />
</Grid>
</>
}
/>
<div
css={`
position: relative;
top: -2px;
margin: 0 -1.5rem;
`}
>
<Progress progress={progress} />
</div>
</div>
</Message>
</FromTop>
</Grid>
<Grid item md={6} sm={12}>
<H3>
{engine.getRule('DRI . cotisations . provisionnelles').title}
</H3>
<Intro>
<Value
expression="dirigeant . indépendant . cotisations et contributions"
displayedUnit="€"
/>
</Intro>
<Markdown>
{engine.getRule('DRI . cotisations . provisionnelles').rawNode
.description ?? ''}
</Markdown>{' '}
</Grid>
<Grid item md={6} sm={12}>
<H3>
{engine.getRule('DRI . cotisations . régularisation').title}
</H3>
<Intro>
<Value expression="DRI . cotisations . régularisation" />
</Intro>
<Markdown>
{engine.getRule('DRI . cotisations . régularisation').rawNode
.description ?? ''}
</Markdown>{' '}
</Grid>
</Grid>
<Grid item md={6} sm={12}>
<H3>
{engine.getRule('DRI . cotisations . provisionnelles').title}
</H3>
<Intro>
<Value
expression="dirigeant . indépendant . cotisations et contributions"
displayedUnit="€"
/>
</Intro>
<Markdown>
{engine.getRule('DRI . cotisations . provisionnelles').rawNode
.description ?? ''}
</Markdown>{' '}
</Grid>
<Grid item md={6} sm={12}>
<H3>
{engine.getRule('DRI . cotisations . régularisation').title}
</H3>
<Intro>
<Value expression="DRI . cotisations . régularisation" />
</Intro>
<Markdown>
{engine.getRule('DRI . cotisations . régularisation').rawNode
.description ?? ''}
</Markdown>{' '}
</Grid>
</Grid>
<Spacing md />
<Spacing md />
</FromTop>
</Container>
<Container

View File

@ -155,17 +155,19 @@ export default function Déclaration() {
déclaration de résultat de votre entreprise dans le formulaire
suivant.
</Body>
<Message type="info">
<H6 as="h3">Écriture entre parenthèse ( )</H6>
<Body>
Certains montants sont écris entre parenthèses dans la
déclaration de résultat. Par exemple, la case « plus value »
peut contenir <code>(1546)</code>. C'est une écriture
comptable pour dire que le montant est négatif. Vous pouvez le
reporter dans ce formulaire en utilisant le signe « - »
habituel.
</Body>
</Message>
<Condition expression="entreprise . imposition . IR . type de bénéfices . BIC">
<Message type="info">
<H6 as="h3">Écriture entre parenthèse ( )</H6>
<Body>
Certains montants sont écris entre parenthèses dans la
déclaration de résultat. Par exemple, la case « plus value »
peut contenir <code>(1546)</code>. C'est une écriture
comptable pour dire que le montant est négatif. Vous pouvez
le reporter dans ce formulaire en utilisant le signe « - »
habituel.
</Body>
</Message>
</Condition>
</FromTop>
</Grid>