diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/PleiepengerSyktBarnGrunnlag.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/PleiepengerSyktBarnGrunnlag.java new file mode 100644 index 00000000..adcfc1c4 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/PleiepengerSyktBarnGrunnlag.java @@ -0,0 +1,22 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett; + +import java.math.BigDecimal; + +import no.nav.fpsak.tidsserie.LocalDateTimeline; + +public class PleiepengerSyktBarnGrunnlag extends YtelsesSpesifiktGrunnlag { + + private final LocalDateTimeline tilsynsgraderingsprosent; + + public PleiepengerSyktBarnGrunnlag(LocalDateTimeline tilsynsgraderingsprosent) { + super("PSB"); + this.tilsynsgraderingsprosent = tilsynsgraderingsprosent; + } + + public LocalDateTimeline getTilsynsgraderingsprosent() { + if (tilsynsgraderingsprosent == null) { + return LocalDateTimeline.empty(); + } + return tilsynsgraderingsprosent; + } +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdi.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdi.java index 31091573..bcdcb071 100644 --- a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdi.java +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdi.java @@ -10,11 +10,14 @@ import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.PleiepengerSyktBarnGrunnlag; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; import no.nav.fpsak.nare.doc.RuleDocumentation; import no.nav.fpsak.nare.evaluation.Evaluation; import no.nav.fpsak.nare.evaluation.node.SingleEvaluation; import no.nav.fpsak.nare.specification.LeafSpecification; +import no.nav.fpsak.tidsserie.LocalDateInterval; +import no.nav.fpsak.tidsserie.StandardCombinators; @RuleDocumentation(FinnGrenseverdi.ID) public class FinnGrenseverdi extends LeafSpecification { @@ -38,14 +41,19 @@ public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { grunnlag.setTotalUtbetalingsgradFraUttak(totalUtbetalingsgradFraUttak); resultater.put("totalUtbetalingsgradFraUttak", totalUtbetalingsgradFraUttak); - //hvis §8-47a, skaler med fast faktor - var erInaktivTypeA = MidlertidigInaktivType.A.equals(grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivType()); - if (erInaktivTypeA) { - BigDecimal reduksjonsfaktor = grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivTypeAReduksjonsfaktor(); - grenseverdi = grenseverdi.multiply(reduksjonsfaktor); - resultater.put("grad847a", reduksjonsfaktor); - } + grenseverdi = utførMidlertidigInaktivGradering(grunnlag, resultater, grenseverdi); + grenseverdi = utførYtelsesspesifikkGradering(grunnlag, grenseverdi); + grenseverdi = utførGraderingMotInntekt(grunnlag, resultater, grenseverdi, totalUtbetalingsgradFraUttak); + resultater.put("grenseverdi", grenseverdi); + grunnlag.setGrenseverdi(grenseverdi); + SingleEvaluation resultat = ja(); + resultat.setEvaluationProperties(resultater); + return resultat; + + } + + private BigDecimal utførGraderingMotInntekt(BeregningsgrunnlagPeriode grunnlag, Map resultater, BigDecimal grenseverdi, BigDecimal totalUtbetalingsgradFraUttak) { //juster ned med tilkommet inntekt hvis det gir lavere utbetaling enn overstående if (grunnlag.getBeregningsgrunnlag().getToggles().isEnabled("GRADERING_MOT_INNTEKT", false) && !grunnlag.getTilkommetInntektsforholdListe().isEmpty()) { BigDecimal graderingPåToppenAvUttakgraderingPgaTilkommetInntekt = andelBeholdtEtterGradertMotTilkommetInntekt(grunnlag); @@ -60,15 +68,37 @@ public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { resultater.put("inntektgraderingsprosent", grunnlag.getInntektsgraderingFraBruttoBeregningsgrunnlag()); } } - resultater.put("grenseverdi", grenseverdi); - grunnlag.setGrenseverdi(grenseverdi); - SingleEvaluation resultat = ja(); - resultat.setEvaluationProperties(resultater); - return resultat; + return grenseverdi; + } + private static BigDecimal utførMidlertidigInaktivGradering(BeregningsgrunnlagPeriode grunnlag, Map resultater, BigDecimal grenseverdi) { + //hvis §8-47a, skaler med fast faktor + var erInaktivTypeA = MidlertidigInaktivType.A.equals(grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivType()); + if (erInaktivTypeA) { + BigDecimal reduksjonsfaktor = grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivTypeAReduksjonsfaktor(); + grenseverdi = grenseverdi.multiply(reduksjonsfaktor); + resultater.put("grad847a", reduksjonsfaktor); + } + return grenseverdi; + } + + private static BigDecimal utførYtelsesspesifikkGradering(BeregningsgrunnlagPeriode grunnlag, BigDecimal grenseverdi) { + if (grunnlag.getBeregningsgrunnlag().getYtelsesSpesifiktGrunnlag() != null && grunnlag.getBeregningsgrunnlag().getYtelsesSpesifiktGrunnlag() instanceof PleiepengerSyktBarnGrunnlag psbGrunnlag) { + var tilsynsgraderingsprosent = psbGrunnlag.getTilsynsgraderingsprosent().compress((b1, b2) -> b1.compareTo(b2) == 0, StandardCombinators::leftOnly); + var intersection = tilsynsgraderingsprosent.intersection(new LocalDateInterval(grunnlag.getPeriodeFom(), grunnlag.getPeriodeTom())); + if (intersection.toSegments().size() > 1) { + throw new IllegalStateException("Fant flere tilsynsgrader for samme periode " + grunnlag.getPeriodeFom()); + } + if (!intersection.isEmpty()) { + var tilsynsgradering = intersection.toSegments().first().getValue(); + grenseverdi = grenseverdi.multiply(tilsynsgradering.divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP)); + } + } + return grenseverdi; } - static BigDecimal min(BigDecimal a, BigDecimal b){ + + static BigDecimal min(BigDecimal a, BigDecimal b) { return a.compareTo(b) > 0 ? b : a; } @@ -91,7 +121,7 @@ private static BigDecimal summerAvkortet(BeregningsgrunnlagPeriode grunnlag) { for (BeregningsgrunnlagPrStatus bps : grunnlag.getBeregningsgrunnlagPrStatusSomSkalBrukes()) { if (bps.erArbeidstakerEllerFrilanser()) { sum = sum.add(bps.getArbeidsforholdSomSkalBrukes().stream() - .map(arb -> arb.getAndelsmessigFørGraderingPrAar()) + .map(BeregningsgrunnlagPrArbeidsforhold::getAndelsmessigFørGraderingPrAar) .reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); } else { sum = sum.add(bps.getAndelsmessigFørGraderingPrAar()); diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java index 93cda4b7..cd616652 100644 --- a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java @@ -10,11 +10,14 @@ import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.PleiepengerSyktBarnGrunnlag; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; import no.nav.fpsak.nare.doc.RuleDocumentation; import no.nav.fpsak.nare.evaluation.Evaluation; import no.nav.fpsak.nare.evaluation.node.SingleEvaluation; import no.nav.fpsak.nare.specification.LeafSpecification; +import no.nav.fpsak.tidsserie.LocalDateInterval; +import no.nav.fpsak.tidsserie.StandardCombinators; @RuleDocumentation(FinnGrenseverdiUtenFordeling.ID) public class FinnGrenseverdiUtenFordeling extends LeafSpecification { @@ -38,14 +41,19 @@ public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { grunnlag.setTotalUtbetalingsgradFraUttak(totalUtbetalingsgradFraUttak); resultater.put("totalUtbetalingsgradFraUttak", totalUtbetalingsgradFraUttak); - //hvis §8-47a, skaler med fast faktor - var erInaktivTypeA = MidlertidigInaktivType.A.equals(grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivType()); - if (erInaktivTypeA) { - BigDecimal reduksjonsfaktor = grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivTypeAReduksjonsfaktor(); - grenseverdi = grenseverdi.multiply(reduksjonsfaktor); - resultater.put("grad847a", reduksjonsfaktor); - } + grenseverdi = utførMidlertidigInaktivGradering(grunnlag, resultater, grenseverdi); + grenseverdi = utførYtelsesspesifikkGradering(grunnlag, grenseverdi); + grenseverdi = utførGraderingMotInntekt(grunnlag, resultater, grenseverdi, totalUtbetalingsgradFraUttak); + resultater.put("grenseverdi", grenseverdi); + grunnlag.setGrenseverdi(grenseverdi); + SingleEvaluation resultat = ja(); + resultat.setEvaluationProperties(resultater); + return resultat; + + } + + private BigDecimal utførGraderingMotInntekt(BeregningsgrunnlagPeriode grunnlag, Map resultater, BigDecimal grenseverdi, BigDecimal totalUtbetalingsgradFraUttak) { //juster ned med tilkommet inntekt hvis det gir lavere utbetaling enn overstående if (grunnlag.getBeregningsgrunnlag().getToggles().isEnabled("GRADERING_MOT_INNTEKT", false) && !grunnlag.getTilkommetInntektsforholdListe().isEmpty()) { BigDecimal graderingPåToppenAvUttakgraderingPgaTilkommetInntekt = andelBeholdtEtterGradertMotTilkommetInntekt(grunnlag); @@ -60,15 +68,36 @@ public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { resultater.put("inntektgraderingsprosent", grunnlag.getInntektsgraderingFraBruttoBeregningsgrunnlag()); } } - resultater.put("grenseverdi", grenseverdi); - grunnlag.setGrenseverdi(grenseverdi); - SingleEvaluation resultat = ja(); - resultat.setEvaluationProperties(resultater); - return resultat; + return grenseverdi; + } + + private static BigDecimal utførMidlertidigInaktivGradering(BeregningsgrunnlagPeriode grunnlag, Map resultater, BigDecimal grenseverdi) { + //hvis §8-47a, skaler med fast faktor + var erInaktivTypeA = MidlertidigInaktivType.A.equals(grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivType()); + if (erInaktivTypeA) { + BigDecimal reduksjonsfaktor = grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivTypeAReduksjonsfaktor(); + grenseverdi = grenseverdi.multiply(reduksjonsfaktor); + resultater.put("grad847a", reduksjonsfaktor); + } + return grenseverdi; + } + private static BigDecimal utførYtelsesspesifikkGradering(BeregningsgrunnlagPeriode grunnlag, BigDecimal grenseverdi) { + if (grunnlag.getBeregningsgrunnlag().getYtelsesSpesifiktGrunnlag() != null && grunnlag.getBeregningsgrunnlag().getYtelsesSpesifiktGrunnlag() instanceof PleiepengerSyktBarnGrunnlag psbGrunnlag) { + var tilsynsgraderingsprosent = psbGrunnlag.getTilsynsgraderingsprosent().compress((b1, b2) -> b1.compareTo(b2) == 0, StandardCombinators::leftOnly); + var intersection = tilsynsgraderingsprosent.intersection(new LocalDateInterval(grunnlag.getPeriodeFom(), grunnlag.getPeriodeTom())); + if (intersection.toSegments().size() > 1) { + throw new IllegalStateException("Fant flere tilsynsgrader for samme periode " + grunnlag.getPeriodeFom()); + } + if (!intersection.isEmpty()) { + var tilsynsgradering = intersection.toSegments().first().getValue(); + grenseverdi = grenseverdi.multiply(tilsynsgradering.divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP)); + } + } + return grenseverdi; } - static BigDecimal min(BigDecimal a, BigDecimal b){ + static BigDecimal min(BigDecimal a, BigDecimal b) { return a.compareTo(b) > 0 ? b : a; } @@ -91,7 +120,7 @@ private static BigDecimal summerAvkortet(BeregningsgrunnlagPeriode grunnlag) { for (BeregningsgrunnlagPrStatus bps : grunnlag.getBeregningsgrunnlagPrStatusSomSkalBrukes()) { if (bps.erArbeidstakerEllerFrilanser()) { sum = sum.add(bps.getArbeidsforholdSomSkalBrukes().stream() - .map(arb -> arb.getAndelsmessigFørGraderingPrAar()) + .map(BeregningsgrunnlagPrArbeidsforhold::getAndelsmessigFørGraderingPrAar) .reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); } else { sum = sum.add(bps.getAndelsmessigFørGraderingPrAar()); diff --git a/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiTest.java b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiTest.java index 1bf15890..1b301043 100644 --- a/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiTest.java +++ b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiTest.java @@ -18,8 +18,10 @@ import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.PleiepengerSyktBarnGrunnlag; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.grunnlag.inntekt.Arbeidsforhold; +import no.nav.fpsak.tidsserie.LocalDateTimeline; class RegelFinnGrenseverdiTest { @@ -118,6 +120,31 @@ void ett_arbeidsforhold_over_6G() { assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); } + @Test + void ett_arbeidsforhold_over_6G_og_gradering_mot_tilsyn() { + //Arrange + double beregnetPrÅr = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)) + .medYtelsesSpesifiktGrunnlag(new PleiepengerSyktBarnGrunnlag(new LocalDateTimeline<>( + periode.getPeriodeFom(), periode.getPeriodeTom(), BigDecimal.valueOf(50) + ))); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test void to_arbeidsforhold_under_6G() { //Arrange diff --git a/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java index 58e937e8..181d1466 100644 --- a/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java +++ b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java @@ -11,6 +11,8 @@ import org.junit.jupiter.api.Test; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatusMedHjemmel; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.BeregningsgrunnlagHjemmel; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.MidlertidigInaktivType; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.Periode; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.RegelResultat; @@ -18,8 +20,10 @@ import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.PleiepengerSyktBarnGrunnlag; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.grunnlag.inntekt.Arbeidsforhold; +import no.nav.fpsak.tidsserie.LocalDateTimeline; class RegelFinnGrenseverdiUtenFordelingTest { @@ -118,6 +122,31 @@ void ett_arbeidsforhold_over_6G() { assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); } + @Test + void ett_arbeidsforhold_over_6G_og_gradering_mot_tilsyn() { + //Arrange + double beregnetPrÅr = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)) + .medYtelsesSpesifiktGrunnlag(new PleiepengerSyktBarnGrunnlag(new LocalDateTimeline<>( + periode.getPeriodeFom(), periode.getPeriodeTom(), BigDecimal.valueOf(50) + ))); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test void to_arbeidsforhold_under_6G() { //Arrange