Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: PPN kan bruke 100% av kvoten ved gradert uttak #923

Merged
merged 7 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package no.nav.pleiepengerbarn.uttak.regler.delregler

import no.nav.pleiepengerbarn.uttak.kontrakter.*
import no.nav.pleiepengerbarn.uttak.regler.FeatureToggle
import no.nav.pleiepengerbarn.uttak.regler.HUNDRE_PROSENT
import no.nav.pleiepengerbarn.uttak.regler.domene.RegelGrunnlag
import no.nav.pleiepengerbarn.uttak.regler.kontrakter_ext.overlapperDelvis
import no.nav.pleiepengerbarn.uttak.regler.kontrakter_ext.virkedager
import org.slf4j.LoggerFactory
import java.math.BigDecimal
import java.math.RoundingMode
import java.time.DayOfWeek
import java.time.LocalDate
import java.util.UUID
import kotlin.math.min

internal class MaxAntallDagerRegel : UttaksplanRegel {

Expand All @@ -36,7 +37,8 @@ internal class MaxAntallDagerRegel : UttaksplanRegel {

uttaksplan.perioder.forEach { (periode, info) ->
if (info.utfall == Utfall.OPPFYLT) {
val forbrukteDagerDennePerioen = BigDecimal(periode.virkedager()) * (info.uttaksgrad.divide(HUNDRE_PROSENT, 2, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP))
val uttaksgrad = info.uttaksgrad.divide(HUNDRE_PROSENT, 2, RoundingMode.HALF_UP)
val forbrukteDagerDennePerioen = BigDecimal(periode.virkedager()) * uttaksgrad

if (rest <= BigDecimal.ZERO) {
// Hvis ingenting igjen på kvoten så må undersøke om det fremdeles kan innvilges
Expand All @@ -47,11 +49,12 @@ internal class MaxAntallDagerRegel : UttaksplanRegel {
rest -= forbrukteDagerDennePerioen
} else {
// Bare delvis nok dager igjen, så deler derfor opp perioden i en oppfylt og en ikke oppfylt periode
val restHeleDager = rest.setScale(0, RoundingMode.UP)
val restHeleDagerMedEventuellHelg = if (restHeleDager > BigDecimal(5)) ((restHeleDager.divide(BigDecimal(5), 2, RoundingMode.HALF_UP)) * BigDecimal(2)) + restHeleDager - BigDecimal(2) else restHeleDager
nyePerioder[LukketPeriode(periode.fom, periode.fom.plusDays((restHeleDagerMedEventuellHelg - BigDecimal.ONE).toLong()))] = info
if (erDetFlereDagerIgjenÅVurdere(periode, restHeleDagerMedEventuellHelg)) {
nyePerioder[LukketPeriode(periode.fom.plusDays(restHeleDagerMedEventuellHelg.toLong()), periode.tom)] = info.settIkkeoppfylt()
val restVirkedagerGradert = rest.divide(uttaksgrad, 0, RoundingMode.UP).toInt() // ingen #div/0, treffer kode over om det er 0 uttaksgrad
val tomInnvilget = plussVirkedager(periode.fom, restVirkedagerGradert-1)
check(tomInnvilget <= periode.tom) { "Post-condition feilet: tomInnvilget $tomInnvilget er utenfor $periode. Uttaksgrad var $uttaksgrad og rest var $rest" }
nyePerioder[LukketPeriode(periode.fom, tomInnvilget)] = info
if (tomInnvilget < periode.tom) {
nyePerioder[LukketPeriode(tomInnvilget.plusDays(1), periode.tom)] = info.settIkkeoppfylt()
}
rest = BigDecimal.ZERO
}
Expand Down Expand Up @@ -86,7 +89,17 @@ internal class MaxAntallDagerRegel : UttaksplanRegel {
return uttaksplan.copy(perioder = nyePerioder, kvoteInfo = kvoteInfo)
}

private fun erDetFlereDagerIgjenÅVurdere(periode: LukketPeriode, restHeleDagerMedEventuellHelg: BigDecimal) = !periode.tom.isBefore(periode.fom.plusDays(restHeleDagerMedEventuellHelg.toLong()))
private fun plussVirkedager(inputDato: LocalDate, antallVirkedager: Int): LocalDate {
var restVirkedager = antallVirkedager
var dato = inputDato
while (restVirkedager > 0) {
dato = dato.plusDays(1);
if (dato.dayOfWeek !in listOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)) {
restVirkedager--;
}
}
return dato
}

private fun skalKunSetteMaxDatoHvisKvotenErbruktOpp(
forBrukteDagerHittil: BigDecimal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,41 @@ class MaxAntallDagerRegelTest {
assertThat(resultatInfo2.utfall).isEqualTo(Utfall.IKKE_OPPFYLT)
}

@Test
internal fun `Søker har 50% uttak, får innvilget i 120 ukedager, deretter avslag`() {
//120 ukedager er 24 uker
//1.jan 2024 er en mandag

//24 hele uker fra og med 1.jan 2024 slutter 16.juni 2024 (en søndag)

val periode1 = LukketPeriode("2024-01-01/2024-07-01")
val søkersUttaksplan = Uttaksplan(
perioder = mapOf(
periode1 to dummyUttaksperiodeInfo(uttaksgrad = Prosent(50))
), trukketUttak = listOf()
)

val helePerioden = LukketPeriode(LocalDate.of(2024, Month.JANUARY, 1), LocalDate.of(2024, Month.JULY, 1))
val grunnlag = dummyRegelGrunnlag(helePerioden)

val resultat = regel.kjør(søkersUttaksplan, grunnlag)
assertThat(resultat.perioder).hasSize(2)
assertThat(resultat.kvoteInfo).isNotNull
assertThat(resultat.kvoteInfo!!.maxDato).isNull()
assertThat(resultat.kvoteInfo!!.totaltForbruktKvote).isEqualTo(BigDecimal.valueOf(60).setScale(2))

val resultatPeriode = resultat.perioder.keys.first()
val resultatInfo = resultat.perioder.values.first()
assertThat(resultatPeriode).isEqualTo(LukketPeriode("2024-01-01/2024-06-14"))
assertThat(resultatInfo.utfall).isEqualTo(Utfall.OPPFYLT)

val resultatPeriode2 = resultat.perioder.keys.last()
val resultatInfo2 = resultat.perioder.values.last()
assertThat(resultatPeriode2).isEqualTo(LukketPeriode("2024-06-15/2024-07-01"))
assertThat(resultatInfo2.utfall).isEqualTo(Utfall.IKKE_OPPFYLT)
}


@Test
internal fun `Søker får avslått det fraværet som ikke er oppfylt av andre grunner, innvilget det som er innenfor kvoten, og avslått det som er over kvoten`() {
val periode1 = LukketPeriode("2020-01-06/2020-01-31") // 20 dager
Expand Down Expand Up @@ -476,10 +511,10 @@ private fun dummyRegelGrunnlagMedAndreParter(
)


private fun dummyUttaksperiodeInfo(oppgittTilsyn: Duration? = null, utfall: Utfall = Utfall.OPPFYLT) =
private fun dummyUttaksperiodeInfo(oppgittTilsyn: Duration? = null, utfall: Utfall = Utfall.OPPFYLT, uttaksgrad:Prosent = HUNDRE_PROSENT) =
UttaksperiodeInfo(
utfall = utfall,
utbetalingsgrader = mapOf(arbeidsforhold1 to Prosent(100)).somUtbetalingsgrader(),
utbetalingsgrader = mapOf(arbeidsforhold1 to uttaksgrad).somUtbetalingsgrader(),
annenPart = AnnenPart.ALENE,
beredskap = null,
nattevåk = null,
Expand All @@ -494,7 +529,7 @@ private fun dummyUttaksperiodeInfo(oppgittTilsyn: Duration? = null, utfall: Utfa
oppgittTilsyn = oppgittTilsyn,
pleiebehov = Pleiebehov.PROSENT_100.prosent,
søkersTapteArbeidstid = null,
uttaksgrad = HUNDRE_PROSENT,
uttaksgrad = uttaksgrad,
årsaker = setOf(),
uttaksgradUtenReduksjonGrunnetInntektsgradering = null,
uttaksgradMedReduksjonGrunnetInntektsgradering = null
Expand Down