Skip to content

Commit

Permalink
PLS 60 dager regel (#394)
Browse files Browse the repository at this point in the history
  • Loading branch information
frodeli authored Jan 17, 2022
1 parent 2de71ef commit 3f981f5
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum class Årsak(val oppfylt: Boolean) {
BARNETS_DØDSFALL(false),
INNGANGSVILKÅR_IKKE_OPPFYLT(false),
FOR_LAV_INNTEKT(false),
FOR_MANGE_DAGER_UTENLANDSOPPHOLD(false)
FOR_MANGE_DAGER_UTENLANDSOPPHOLD(false),
MAKS_DAGER_OVERSTEGET(false)

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ internal object UttaksplanRegler {

private val UttaksplanRegler = linkedSetOf(
InngangsvilkårIkkeOppfyltRegel(),
UtenlandsoppholdRegel()
UtenlandsoppholdRegel(),
MaxAntallDagerRegel()
// NB: erstartet inntil videre med BarnsDødPeriodeRegel
// BarnsDødRegel()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package no.nav.pleiepengerbarn.uttak.regler.delregler

import no.nav.pleiepengerbarn.uttak.kontrakter.*
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.tilVirkedager
import no.nav.pleiepengerbarn.uttak.regler.kontrakter_ext.virkedager
import java.math.BigDecimal
import java.math.RoundingMode
import java.time.LocalDate

internal class MaxAntallDagerRegel : UttaksplanRegel {

companion object {
val KVOTER = mapOf(
YtelseType.PLS to 60
)
}

override fun kjør(uttaksplan: Uttaksplan, grunnlag: RegelGrunnlag): Uttaksplan {

if (grunnlag.ytelseType != YtelseType.PLS) {
return uttaksplan
}
val maxDager = KVOTER[grunnlag.ytelseType] ?: throw IllegalArgumentException("Ulovlig ytelsestype ${grunnlag.ytelseType}")
val forBrukteDagerAndreParter = grunnlag.finnForbrukteDagerAndreParter()
var rest = BigDecimal(maxDager) - forBrukteDagerAndreParter

val nyePerioder = mutableMapOf<LukketPeriode, UttaksperiodeInfo>()

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

if (rest <= BigDecimal.ZERO) {
// Hvis ingenting igjen på kvoten så settes hele perioder til ikke oppfylt
nyePerioder[periode] = info.settIkkeoppfylt()
} else if (forbrukteDagerDennePerioen <= rest) {
// Hvis det er nok dager igjen, så settes hele periode til oppfylt
nyePerioder[periode] = info
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).toLong()
nyePerioder[LukketPeriode(periode.fom, periode.fom.plusDays(restHeleDager - 1L))] = info
nyePerioder[LukketPeriode(periode.fom.plusDays(restHeleDager), periode.tom)] = info.settIkkeoppfylt()
rest = BigDecimal.ZERO
}
} else {
// Gjør ingenting med perioder som ikke er oppfylt
nyePerioder[periode] = info
}
}

return uttaksplan.copy(perioder = nyePerioder)
}

}


private fun UttaksperiodeInfo.settIkkeoppfylt(): UttaksperiodeInfo {
return this.copy(
årsaker = setOf(Årsak.MAKS_DAGER_OVERSTEGET),
utfall = Utfall.IKKE_OPPFYLT,
inngangsvilkår = inngangsvilkår,
uttaksgrad = Prosent(0).setScale(2, RoundingMode.HALF_UP),
utbetalingsgrader = this.utbetalingsgrader.map {it.copy(utbetalingsgrad = Prosent(0).setScale(2, RoundingMode.HALF_UP))}
)
}

private fun RegelGrunnlag.finnForbrukteDagerAndreParter(): BigDecimal {
var antallDager = BigDecimal.ZERO
this.kravprioritetForBehandlinger.forEach { (kravprioritetsperiode, behandlingsUUIDer) ->
for (behandlingUUID in behandlingsUUIDer) {
if (behandlingUUID == this.behandlingUUID) {
//Avslutt loop dersom nåværende behandling
break
}
val annenPartsUttaksplan = this.andrePartersUttaksplanPerBehandling[behandlingUUID] ?: throw IllegalStateException("Skal ikke kunne skje at behandling ikke finnes")
annenPartsUttaksplan.perioder.forEach { (annenPartsPeriode, info) ->
if (annenPartsPeriode.overlapperDelvis(kravprioritetsperiode)) {
if (info.utfall == Utfall.OPPFYLT) {
antallDager += (info.uttaksgrad / HUNDRE_PROSENT.setScale(2, RoundingMode.HALF_UP))
}
}
}
}
}
return antallDager
}


private fun RegelGrunnlag.finnForbrukteDagerFraForrigeUttaksplan(): Map<LocalDate, BigDecimal> {
if (this.forrigeUttaksplan == null) {
return mapOf()
}
val forbrukteDagerPerDato = mutableMapOf<LocalDate, BigDecimal>()
this.forrigeUttaksplan.perioder
.filter {it.value.utfall == Utfall.OPPFYLT}
.forEach {
it.key.tilVirkedager().forEach { virkedag ->
forbrukteDagerPerDato[virkedag] = it.value.uttaksgrad.divide(HUNDRE_PROSENT).setScale(2, RoundingMode.HALF_UP)
}
}
return forbrukteDagerPerDato
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import no.nav.pleiepengerbarn.uttak.kontrakter.*
import no.nav.pleiepengerbarn.uttak.regler.NULL_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.stream
import no.nav.pleiepengerbarn.uttak.regler.kontrakter_ext.tilVirkedager
import no.nav.pleiepengerbarn.uttak.regler.kontrakter_ext.virkedager
import java.time.DayOfWeek
import java.time.LocalDate
Expand Down Expand Up @@ -88,18 +90,6 @@ private fun RegelGrunnlag.finnUtenlandsdager(): Set<LocalDate> {
}
return this.forrigeUttaksplan.perioder
.filter {it.value.utenlandsoppholdUtenÅrsak}
.flatMap {it.key.tilDatoer()}
.flatMap {it.key.tilVirkedager()}
.toSet()
}

private fun LukketPeriode.tilDatoer(): Set<LocalDate> {
val datoer = mutableSetOf<LocalDate>()
this.stream().forEach {
if (it.dayOfWeek !in listOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)) {
datoer.add(it)
}
}
return datoer
}

private fun LukketPeriode.stream() = fom.datesUntil(tom.plusDays(1))
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import no.nav.pleiepengerbarn.uttak.kontrakter.LukketPeriode
import no.nav.pleiepengerbarn.uttak.kontrakter.SøktUttak
import java.lang.IllegalArgumentException
import java.time.DayOfWeek
import java.time.LocalDate

internal fun LukketPeriode.overlapperHelt(annen: LukketPeriode) =
(fom == annen.fom || fom.isBefore(annen.fom)) &&
Expand Down Expand Up @@ -40,3 +41,15 @@ internal fun LukketPeriode.virkedager(): Int {
}
return antall
}

internal fun LukketPeriode.tilVirkedager(): Set<LocalDate> {
val datoer = mutableSetOf<LocalDate>()
this.stream().forEach {
if (it.dayOfWeek !in listOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)) {
datoer.add(it)
}
}
return datoer
}

internal fun LukketPeriode.stream() = fom.datesUntil(tom.plusDays(1))
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class UttakplanApi {
fun opprettUttaksplan(
@RequestBody uttaksgrunnlag: Uttaksgrunnlag,
uriComponentsBuilder: UriComponentsBuilder): ResponseEntity<Uttaksplan> {
logger.info("Opprett uttaksplan for behanding=${uttaksgrunnlag.behandlingUUID}")
logger.info("Opprett uttaksplan for behandling=${uttaksgrunnlag.behandlingUUID}")
uttaksgrunnlag.valider()
val forrigeUttaksplan = uttakRepository.hentForrige(uttaksgrunnlag.saksnummer, UUID.fromString(uttaksgrunnlag.behandlingUUID))
val nyUttaksplan = lagUttaksplan(uttaksgrunnlag, forrigeUttaksplan, true)
Expand All @@ -53,7 +53,7 @@ class UttakplanApi {
@PostMapping(EndringUttaksplanPath, consumes = [MediaType.APPLICATION_JSON_VALUE], produces = [MediaType.APPLICATION_JSON_VALUE])
@Operation(description = "Endrer en uttaksplan. Kun enkelte endringer er lovlig, hvis endringen er ulovlig så vil endepunktet returnere en 'bad request'.")
fun endrePerioder(@RequestBody endrePerioderGrunnlag: EndrePerioderGrunnlag): ResponseEntity<Uttaksplan?> {
logger.info("Endrer uttaksplan for behanding=${endrePerioderGrunnlag.behandlingUUID}")
logger.info("Endrer uttaksplan for behandling=${endrePerioderGrunnlag.behandlingUUID}")
endrePerioderGrunnlag.valider()
val eksisterendeUttaksplan = uttakRepository.hent(UUID.fromString(endrePerioderGrunnlag.behandlingUUID))
?: return ResponseEntity.badRequest().body(null)
Expand All @@ -68,7 +68,7 @@ class UttakplanApi {
fun simulerUttaksplan(
@RequestBody uttaksgrunnlag: Uttaksgrunnlag,
uriComponentsBuilder: UriComponentsBuilder): ResponseEntity<Simulering> {
logger.info("Simulerer uttaksplan(PSB) for behanding=${uttaksgrunnlag.behandlingUUID}")
logger.info("Simulerer uttaksplan(PSB) for behandling=${uttaksgrunnlag.behandlingUUID}")
val simulering = simuler(uttaksgrunnlag)
return ResponseEntity.ok(simulering)
}
Expand All @@ -78,7 +78,7 @@ class UttakplanApi {
fun simulerUttaksplanForLivetsSluttfase(
@RequestBody uttaksgrunnlag: Uttaksgrunnlag,
uriComponentsBuilder: UriComponentsBuilder): ResponseEntity<SimuleringLivetsSluttfase> {
logger.info("Simulerer uttaksplan(PLS) for behanding=${uttaksgrunnlag.behandlingUUID}")
logger.info("Simulerer uttaksplan(PLS) for behandling=${uttaksgrunnlag.behandlingUUID}")
val simulering = simuler(uttaksgrunnlag)
val erKvotenBruktOpp = BeregnBruktKvote.erKvotenOversteget(simulering.simulertUttaksplan, hentAndrePartersUttaksplanerPerBehandling(uttaksgrunnlag))
return ResponseEntity.ok(SimuleringLivetsSluttfase(simulering.forrigeUttaksplan, simulering.simulertUttaksplan,
Expand Down Expand Up @@ -131,7 +131,7 @@ class UttakplanApi {
]
)
fun hentUttaksplanForBehandling(@RequestParam behandlingUUID: BehandlingUUID, @RequestParam slåSammenLikePerioder: Boolean = false): ResponseEntity<Uttaksplan> {
logger.info("Henter uttaksplan for behanding=$behandlingUUID slåSammenLikePerioder=$slåSammenLikePerioder")
logger.info("Henter uttaksplan for behandling=$behandlingUUID slåSammenLikePerioder=$slåSammenLikePerioder")
val behandlingUUIDParsed = try {
UUID.fromString(behandlingUUID)
} catch (e: IllegalArgumentException) {
Expand All @@ -153,7 +153,7 @@ class UttakplanApi {
]
)
fun slettUttaksplab(@RequestParam behandlingUUID: BehandlingUUID): ResponseEntity<Unit> {
logger.info("Sletter uttaksplan for behanding=$behandlingUUID")
logger.info("Sletter uttaksplan for behandling=$behandlingUUID")
val behandlingUUIDParsed = try {
UUID.fromString(behandlingUUID)
} catch (e: IllegalArgumentException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ class UttakplanApiTest(@Autowired val restTemplate: TestRestTemplate) {
søknadsperiode = søknadsperiode,
arbeid = listOf(arbeidSøker2),
pleiebehov = mapOf(søknadsperiode to Pleiebehov.PROSENT_6000),
behandlingUUID = nesteBehandlingId(),
behandlingUUID = søker2BehandlingId,
saksnummer = nesteSaksnummer()).copy(kravprioritetForBehandlinger = mapOf(søknadsperiode to listOf(søker2BehandlingId, grunnlag1Søker1.behandlingUUID)))

grunnlagSøker2.opprettUttaksplan()
Expand All @@ -978,7 +978,7 @@ class UttakplanApiTest(@Autowired val restTemplate: TestRestTemplate) {
søknadsperiode = søknadsperiode,
arbeid = listOf(arbeidSøker3),
pleiebehov = mapOf(søknadsperiode to Pleiebehov.PROSENT_6000),
behandlingUUID = nesteBehandlingId(),
behandlingUUID = søker3BehandlingId,
saksnummer = nesteSaksnummer()).copy(kravprioritetForBehandlinger = mapOf(søknadsperiode to listOf(søker3BehandlingId, grunnlagSøker2.behandlingUUID, grunnlag1Søker1.behandlingUUID)))


Expand Down

0 comments on commit 3f981f5

Please sign in to comment.