Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
throndi committed Dec 15, 2023
2 parents 635ae58 + 3602dd7 commit bc694c1
Show file tree
Hide file tree
Showing 21 changed files with 435 additions and 150 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
Expand Down
21 changes: 13 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<version>3.1.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>no.nav.familie.ef</groupId>
Expand All @@ -29,20 +29,20 @@
<changelist>-SNAPSHOT</changelist>
<java.version>21</java.version>
<kotlin.version>1.9.21</kotlin.version>
<kafka-avro-serializer.version>7.5.1</kafka-avro-serializer.version>
<kafka-avro-serializer.version>7.5.2</kafka-avro-serializer.version>
<avro.version>1.11.3</avro.version>
<graphql-kotlin-spring-client.version>7.0.1</graphql-kotlin-spring-client.version>
<graphql-kotlin-maven-plugin.version>7.0.1</graphql-kotlin-maven-plugin.version>
<graphql-kotlin-spring-client.version>7.0.2</graphql-kotlin-spring-client.version>
<graphql-kotlin-maven-plugin.version>7.0.2</graphql-kotlin-maven-plugin.version>
<graphql-kotlin.version>3.5.0</graphql-kotlin.version>
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
<kontrakter.version>3.0_20231026154353_1ccdbb1</kontrakter.version>
<exec-maven-plugin.version>3.1.1</exec-maven-plugin.version>
<kontrakter.version>3.0_20231206111937_3c866af</kontrakter.version>
<eksterne-kontrakter.version>2.0_20230825103733_1ac52c2</eksterne-kontrakter.version>
<felles.version>2.20231023162434_fa320ce</felles.version>
<felles.version>2.20231201131108_ea25dd3</felles.version>
<token-validation-spring-test.version>3.0.4</token-validation-spring-test.version> <!-- Denne burde være samme versjon som i felles -->
<okhttp3.version>4.9.1</okhttp3.version> <!-- overskrever spring sin versjon, blir brukt av mock-oauth2-server -->
<wiremock.version>2.35.1</wiremock.version>
<mockk-jvm.version>1.13.8</mockk-jvm.version>
<postgres.version>1.19.1</postgres.version>
<postgres.version>1.19.3</postgres.version>
<start-class>no.nav.familie.ef.personhendelse.Application</start-class>
</properties>
<dependencies>
Expand Down Expand Up @@ -104,6 +104,11 @@
<artifactId>kafka</artifactId>
<version>${felles.version}</version>
</dependency>
<dependency>
<groupId>no.nav.familie.felles</groupId>
<artifactId>leader</artifactId>
<version>${felles.version}</version>
</dependency>
<dependency>
<groupId>no.nav.familie.kontrakter</groupId>
<artifactId>felles</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ class OppgaveClient(
return response.getDataOrThrow()
}

fun leggOppgaveIMappe(oppgaveId: Long) {
fun leggOppgaveIMappe(oppgaveId: Long, mappenavnInneholder: String = "Hendelser") {
val oppgave = finnOppgaveMedId(oppgaveId)
if (oppgave.tildeltEnhetsnr == EF_ENHETNUMMER) { // Skjermede personer skal ikke puttes i mappe
val mapperResponse = finnMapper(oppgave.tildeltEnhetsnr!!)
try {
oppdaterOppgaveMedMappe(mapperResponse, oppgave)
oppdaterOppgaveMedMappe(mapperResponse, oppgave, mappenavnInneholder)
} catch (e: Exception) {
log.error("Feil under knytning av mappe til oppgave - se securelogs for stacktrace")
secureLogger.error("Feil under knytning av mappe til oppgave", e)
Expand All @@ -67,12 +67,12 @@ class OppgaveClient(
private fun oppdaterOppgaveMedMappe(
mapperResponse: FinnMappeResponseDto,
oppgave: Oppgave,
mappenavnInneholder: String = "Hendelser",
) {
val mappe = mapperResponse.mapper.find {
it.navn.contains("62") &&
it.navn.contains("Hendelser") &&
it.navn.contains(mappenavnInneholder, true) &&
!it.navn.contains("EF Sak", true)
} ?: error("Fant ikke mappe 62 Hendelser for uplassert oppgave")
} ?: error("Fant ikke mappe som inneholder mappenavn $mappenavnInneholder for uplassert oppgave")
oppdaterOppgave(oppgave.copy(mappeId = mappe.id.toLong()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class SakClient(
fun hentPersonerMedAktivStønadIkkeManueltRevurdertSisteMåneder(antallMåneder: Int = 3): List<String> {
val uriComponentsBuilder = UriComponentsBuilder.fromUri(uri)
.pathSegment("api/vedtak/personerMedAktivStonadIkkeManueltRevurdertSisteMaaneder")
.queryParam("antallMaaneder", 4)
.queryParam("antallMaaneder", antallMåneder)
val response = getForEntity<Ressurs<List<String>>>(uriComponentsBuilder.build().toUri())
return response.data
?: throw Exception("Feil ved kall mot ef-sak ved henting av forventet inntekt for personer med aktiv stønad")
Expand All @@ -86,4 +86,5 @@ data class ForventetInntektForPerson(
val forventetInntektForrigeMåned: Int?,
val forventetInntektToMånederTilbake: Int?,
val forventetInntektTreMånederTilbake: Int?,
val forventetInntektFireMånederTilbake: Int?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,54 @@ class ForelderBarnHandler(val sakClient: SakClient) : PersonhendelseHandler {
secureLogger.info("Nye barn for bruker er ${nyeBarnForBruker.nyeBarn}, hendelseId : ${personhendelse.hendelseId}")

val barnFødtFørTermin = nyeBarnForBruker.filtrerÅrsak(NyttBarnÅrsak.FØDT_FØR_TERMIN)
val barnFødtEtterTermin = nyeBarnForBruker.filtrerÅrsak(NyttBarnÅrsak.FØDT_ETTER_TERMIN)
val nyeBarnSomIkkeFinnesPåBehandlingen = nyeBarnForBruker.filtrerÅrsak(NyttBarnÅrsak.BARN_FINNES_IKKE_PÅ_BEHANDLING)

if (barnFødtFørTermin.isNotEmpty()) {
val nyeBarnTekst = if (nyeBarnSomIkkeFinnesPåBehandlingen.isNotEmpty()) {
"Bruker har også fått et nytt/nye barn ${nyeBarnSomIkkeFinnesPåBehandlingen.separerteIdenterMedStønadstype()}. "
} else {
""
}
return OpprettOppgave(
"Bruker er innvilget stønad for ufødt(e) barn ${barnFødtFørTermin.separerteIdenterMedStønadstype()}. " +
"Barnet er registrert født i måneden før oppgitt termindato. " +
nyeBarnTekst +
"Vurder saken.",
)
return opprettOppgaveBarnFødtFørTermin(nyeBarnSomIkkeFinnesPåBehandlingen, barnFødtFørTermin)
}
if (barnFødtEtterTermin.isNotEmpty()) {
return opprettOppgaveBarnFødtEtterTermin(nyeBarnSomIkkeFinnesPåBehandlingen, barnFødtEtterTermin)
}

return OpprettOppgave("Bruker har fått et nytt/nye barn ${nyeBarnSomIkkeFinnesPåBehandlingen.separerteIdenterMedStønadstype()} som ikke finnes på behandling.")
}

private fun opprettOppgaveBarnFødtFørTermin(
nyeBarnSomIkkeFinnesPåBehandlingen: List<NyttBarn>,
barnFødtFørTermin: List<NyttBarn>,
): OpprettOppgave {
val nyeBarnTekst = nyeBarnTekst(nyeBarnSomIkkeFinnesPåBehandlingen)
return OpprettOppgave(
"Bruker er innvilget stønad for ufødt(e) barn ${barnFødtFørTermin.separerteIdenterMedStønadstype()}. " +
"Barnet er registrert født i måneden før oppgitt termindato. " +
nyeBarnTekst +
"Vurder saken.",
)
}

private fun opprettOppgaveBarnFødtEtterTermin(
nyeBarnSomIkkeFinnesPåBehandlingen: List<NyttBarn>,
barnFødtEtterTermin: List<NyttBarn>,
): OpprettOppgave {
val nyeBarnTekst = nyeBarnTekst(nyeBarnSomIkkeFinnesPåBehandlingen)
return OpprettOppgave(
"Bruker er innvilget stønad for ufødt(e) barn ${barnFødtEtterTermin.separerteIdenterMedStønadstype()}. " +
"Barnet er registrert født i måneden etter oppgitt termindato. " +
nyeBarnTekst +
"Vurder saken.",
)
}

private fun nyeBarnTekst(nyeBarnSomIkkeFinnesPåBehandlingen: List<NyttBarn>): String {
val nyeBarnTekst = if (nyeBarnSomIkkeFinnesPåBehandlingen.isNotEmpty()) {
"Bruker har også fått et nytt/nye barn ${nyeBarnSomIkkeFinnesPåBehandlingen.separerteIdenterMedStønadstype()}. "
} else {
""
}
return nyeBarnTekst
}

private fun NyeBarnDto.filtrerÅrsakrsak: NyttBarnÅrsak) = this.nyeBarn.filter { it.årsak == årsak }

private fun List<NyttBarn>.separerteIdenterMedStønadstype() = this.joinToString(", ") { it.personIdent + " (${it.stønadstype.name.enumToReadable()})" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package no.nav.familie.ef.personhendelse.inntekt

import java.math.BigDecimal
import java.math.RoundingMode

private val grunnbeløp = 118_620
private val halvtGrunnbeløp = 59_310
private val reduksjonsfaktor = BigDecimal(0.45)

fun beregnFeilutbetalingForMåned(forventetInntekt: Int, samletInntekt: Int): Int {
return beregnUtbetaling(forventetInntekt) - beregnUtbetaling(samletInntekt)
}

private fun beregnUtbetaling(inntekt: Int): Int {
val avkortning = beregnAvkortning(inntekt).setScale(0, RoundingMode.HALF_DOWN)

val fullOvergangsstønad =
BigDecimal(grunnbeløp).multiply(BigDecimal(2.25)).setScale(0, RoundingMode.HALF_EVEN)

val utbetaling = fullOvergangsstønad.subtract(avkortning).setScale(0, RoundingMode.HALF_UP).toInt()

return if (utbetaling <= 0) 0 else utbetaling / 12
}

private fun beregnAvkortning(inntekt: Int): BigDecimal {
val inntektOverHalveGrunnbeløpÅrlig = BigDecimal(inntekt).multiply(BigDecimal(12)).subtract(BigDecimal(halvtGrunnbeløp))
return if (inntektOverHalveGrunnbeløpÅrlig > BigDecimal.ZERO) {
inntektOverHalveGrunnbeløpÅrlig.multiply(reduksjonsfaktor).setScale(5, RoundingMode.HALF_DOWN)
} else {
BigDecimal.ZERO
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,6 @@ data class Tilleggsinformasjon(
val tilleggsinformasjonDetaljer: TilleggsinformasjonDetaljer?,
)

data class Inntektsendring(
val treMånederTilbake: Int,
val toMånederTilbake: Int,
val forrigeMåned: Int,
val beløpTreMånederTilbake: Int,
val beløpToMånederTilbake: Int,
val beløpForrigeMåned: Int,
) {
fun harEndretInntekt() = treMånederTilbake >= 10 && toMånederTilbake >= 10 && forrigeMåned >= 10
}

enum class AktørType {
AKTOER_ID,
NATURLIG_IDENT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package no.nav.familie.ef.personhendelse.inntekt

import no.nav.familie.leader.LeaderClient
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service

@Service
class InntektsendringerScheduler(val vedtakendringerService: VedtakendringerService) {

@Scheduled(cron = "0 0 4 6 * *") // kl 04:00 den 6. hver måned
fun inntektskontroll() {
if (LeaderClient.isLeader() == true) {
vedtakendringerService.beregnInntektsendringerOgLagreIDb()
vedtakendringerService.opprettOppgaverForInntektsendringer(true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class InntektsendringerService(
val sakClient: SakClient,
) {

private val halvtGrunnbeløpMånedlig = (118620 / 2) / 12
private val grunnbeløp = 118_620
private val halvtGrunnbeløpMånedlig = (grunnbeløp / 2) / 12

fun beregnEndretInntekt(inntektshistorikkResponse: InntektshistorikkResponse, forventetInntektForPerson: ForventetInntektForPerson): Inntektsendring {
// hent alle registrerte vedtak som var på personen sist beregning
Expand All @@ -23,6 +24,14 @@ class InntektsendringerService(
inntektshistorikkResponse.inntektForMåned(YearMonth.now().minusMonths(2))
val inntektTreMånederTilbake =
inntektshistorikkResponse.inntektForMåned(YearMonth.now().minusMonths(3))
val inntektFireMånederTilbake =
inntektshistorikkResponse.inntektForMåned(YearMonth.now().minusMonths(4))

val inntektsendringFireMånederTilbake = beregnInntektsendring(
inntektFireMånederTilbake,
forventetInntektForPerson.personIdent,
forventetInntektForPerson.forventetInntektTreMånederTilbake,
)

val inntektsendringTreMånederTilbake = beregnInntektsendring(
inntektTreMånederTilbake,
Expand All @@ -41,21 +50,20 @@ class InntektsendringerService(
)

return Inntektsendring(
treMånederTilbake = inntektsendringTreMånederTilbake.prosent,
toMånederTilbake = inntektsendringToMånederTilbake.prosent,
forrigeMåned = inntektsendringForrigeMåned.prosent,
beløpTreMånederTilbake = inntektsendringTreMånederTilbake.beløp,
beløpToMånederTilbake = inntektsendringToMånederTilbake.beløp,
beløpForrigeMåned = inntektsendringForrigeMåned.beløp,
fireMånederTilbake = inntektsendringFireMånederTilbake,
treMånederTilbake = inntektsendringTreMånederTilbake,
toMånederTilbake = inntektsendringToMånederTilbake,
forrigeMåned = inntektsendringForrigeMåned,
)
}

private fun beregnInntektsendring(nyesteRegistrerteInntekt: List<InntektVersjon>?, ident: String, forventetInntekt: Int?): BeregningResultat {
if (forventetInntekt == null || nyesteRegistrerteInntekt?.maxOfOrNull { it.versjon } == null) {
secureLogger.warn("Ingen gjeldende inntekt funnet på person $ident har personen løpende stønad?")
return BeregningResultat(0, 0)
return BeregningResultat(0, 0, 0)
}
if (forventetInntekt > 585000) return BeregningResultat(0, 0) // Ignorer alle med over 585000 i årsinntekt, da de har 0 i utbetaling.

if (forventetInntekt > 652000) return BeregningResultat(0, 0, 0) // Ignorer alle med over 652000 i årsinntekt, da de har 0 i utbetaling.
val månedligForventetInntekt = (forventetInntekt / 12)

val orgNrToNyesteVersjonMap = nyesteRegistrerteInntekt.associate { it.opplysningspliktig to it.versjon }
Expand All @@ -67,13 +75,14 @@ class InntektsendringerService(
(it.inntektType == InntektType.YTELSE_FRA_OFFENTLIGE && it.tilleggsinformasjon?.tilleggsinformasjonDetaljer?.detaljerType == "ETTERBETALINGSPERIODE")
}.sumOf { it.beløp }

if (samletInntekt < halvtGrunnbeløpMånedlig) return BeregningResultat(0, 0)
if (samletInntekt < halvtGrunnbeløpMånedlig) return BeregningResultat(0, 0, 0)

secureLogger.info("Samlet inntekt: $samletInntekt - månedlig forventet inntekt: $månedligForventetInntekt (årlig: $forventetInntekt) for person $ident")
val inntektsendringProsent = (((samletInntekt - månedligForventetInntekt) / månedligForventetInntekt.toDouble()) * 100).toInt()
val beløp = samletInntekt - månedligForventetInntekt
if (månedligForventetInntekt == 0) return BeregningResultat(beløp, 100) // Prioriterer personer registrert med uredusert stønad, men har samlet inntekt over 1/2 G
return BeregningResultat(beløp, inntektsendringProsent)
val endretInntektBeløp = samletInntekt - månedligForventetInntekt
val feilutbetaling = beregnFeilutbetalingForMåned(månedligForventetInntekt, samletInntekt)
if (månedligForventetInntekt == 0) return BeregningResultat(endretInntektBeløp, 100, feilutbetaling) // Prioriterer personer registrert med uredusert stønad, men har samlet inntekt over 1/2 G
return BeregningResultat(endretInntektBeløp, inntektsendringProsent, feilutbetaling)
}

// Ignorterte ytelser: Alle uføre går under annet regelverk (samordning) og skal derfor ignoreres.
Expand All @@ -86,7 +95,17 @@ class InntektsendringerService(
)
}

data class Inntektsendring(
val fireMånederTilbake: BeregningResultat,
val treMånederTilbake: BeregningResultat,
val toMånederTilbake: BeregningResultat,
val forrigeMåned: BeregningResultat,
) {
fun harEndretInntekt() = fireMånederTilbake.prosent >= 10 && treMånederTilbake.prosent >= 10 && toMånederTilbake.prosent >= 10 && forrigeMåned.prosent >= 10
}

data class BeregningResultat(
val beløp: Int,
val prosent: Int,
val feilutbetaling: Int,
)
Loading

0 comments on commit bc694c1

Please sign in to comment.