Skip to content

Commit bcf53c6

Browse files
committed
Gjør utregn av skatteperiode smartere
1 parent e5c602f commit bcf53c6

File tree

12 files changed

+222
-44
lines changed

12 files changed

+222
-44
lines changed

client/src/main/kotlin/no/nav/su/se/bakover/client/StubClientsBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class StubClientsBuilder(
102102
klageClient = KlageClientStub.also { log.warn("********** Using stub for ${KlageClientStub::class.java} **********") },
103103
queryJournalpostClient = QueryJournalpostClientStub.also { log.warn("********** Using stub for ${QueryJournalpostClientStub::class.java} **********") },
104104
tilbakekrevingClient = TilbakekrevingClientStub(clock).also { log.warn("********** Using stub for ${TilbakekrevingClient::class.java} **********") },
105-
skatteOppslag = SkatteClientStub().also { log.warn("********** Using stub for ${SkatteClient::class.java} **********") },
105+
skatteOppslag = SkatteClientStub(clock).also { log.warn("********** Using stub for ${SkatteClient::class.java} **********") },
106106
)
107107
}
108108
}

client/src/main/kotlin/no/nav/su/se/bakover/client/skatteetaten/SkatteClientStub.kt

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package no.nav.su.se.bakover.client.skatteetaten
22

33
import arrow.core.NonEmptyList
4+
import arrow.core.left
45
import arrow.core.right
6+
import no.nav.su.se.bakover.common.extensions.mars
57
import no.nav.su.se.bakover.common.extensions.toNonEmptyList
68
import no.nav.su.se.bakover.common.person.Fnr
79
import no.nav.su.se.bakover.common.tid.YearRange
10+
import no.nav.su.se.bakover.domain.skatt.KunneIkkeHenteSkattemelding
811
import no.nav.su.se.bakover.domain.skatt.SamletSkattegrunnlagForÅr
912
import no.nav.su.se.bakover.domain.skatt.SamletSkattegrunnlagForÅrOgStadie
1013
import no.nav.su.se.bakover.domain.skatt.Skattegrunnlag
1114
import no.nav.su.se.bakover.domain.skatt.Skatteoppslag
15+
import java.time.Clock
16+
import java.time.LocalDate
1217
import java.time.Year
1318

14-
class SkatteClientStub() : Skatteoppslag {
19+
class SkatteClientStub(private val clock: Clock) : Skatteoppslag {
20+
1521
override fun hentSamletSkattegrunnlag(
1622
fnr: Fnr,
1723
år: Year,
@@ -50,17 +56,27 @@ class SkatteClientStub() : Skatteoppslag {
5056
// }
5157
}
5258

53-
private fun samletYearr: Year) = SamletSkattegrunnlagForÅr(
54-
år = år,
55-
utkast = SamletSkattegrunnlagForÅrOgStadie.Utkast(
56-
oppslag = årsgrunnlag().right(),
57-
inntektsår = år,
58-
),
59-
oppgjør = SamletSkattegrunnlagForÅrOgStadie.Oppgjør(
60-
oppslag = årsgrunnlag().right(),
61-
inntektsår = år,
62-
),
63-
)
59+
private fun samletYearr: Year): SamletSkattegrunnlagForÅr {
60+
val currentYear = Year.now(clock)
61+
val grenseverdi = 7.mars(currentYear.value)
62+
val= LocalDate.now(clock)
63+
val oppslag = when {
64+
år < currentYear.minusYears(1) -> årsgrunnlag().right()
65+
år < currentYear &&>= grenseverdi -> årsgrunnlag().right()
66+
else -> KunneIkkeHenteSkattemelding.FinnesIkke.left()
67+
}
68+
return SamletSkattegrunnlagForÅr(
69+
år = år,
70+
utkast = SamletSkattegrunnlagForÅrOgStadie.Utkast(
71+
oppslag = oppslag,
72+
inntektsår = år,
73+
),
74+
oppgjør = SamletSkattegrunnlagForÅrOgStadie.Oppgjør(
75+
oppslag = oppslag,
76+
inntektsår = år,
77+
),
78+
)
79+
}
6480

6581
private fun årsgrunnlag() = Skattegrunnlag.SkattegrunnlagForÅr(
6682
oppgjørsdato = null,

common/domain/src/main/kotlin/no/nav/su/se/bakover/common/domain/tid/YearRange.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,27 @@ fun YearRange.krympTilØvreGrense(øvreGrense: Year): YearRange {
7070
}
7171
}
7272

73+
/**
74+
* Utivder nedre grense hvis nedre grense er før start.
75+
*/
76+
fun YearRange.utvidNedreGrense(nedreGrense: Year): YearRange {
77+
return if (nedreGrense >= start) {
78+
this
79+
} else {
80+
YearRange(nedreGrense, endInclusive)
81+
}
82+
}
83+
84+
fun YearRange.krymptTilNedreGrense(nedreGrense: Year): YearRange {
85+
return if (nedreGrense > endInclusive) {
86+
YearRange(nedreGrense, nedreGrense)
87+
} else {
88+
YearRange(max(start, nedreGrense), endInclusive)
89+
}
90+
}
91+
7392
fun min(y1: Year, y2: Year): Year = if (y1.value <= y2.value) y1 else y2
93+
fun max(y1: Year, y2: Year): Year = if (y1.value > y2.value) y1 else y2
7494

7595
fun min(a: YearRange, b: YearRange): YearRange = when {
7696
a.start < b.start -> a
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package no.nav.su.se.bakover.domain.skatt
2+
3+
import no.nav.su.se.bakover.common.tid.YearRange
4+
import no.nav.su.se.bakover.common.tid.krympTilØvreGrense
5+
import no.nav.su.se.bakover.common.tid.utvidNedreGrense
6+
import no.nav.su.se.bakover.domain.søknadsbehandling.stønadsperiode.Stønadsperiode
7+
import java.time.Clock
8+
import java.time.Year
9+
10+
/**
11+
* @return Skatteperiode for stønadsperiode. Hvis stønadsperiode er null, returneres skatteperiode for de tre siste årene.
12+
*/
13+
fun Stønadsperiode?.regnUtSkatteperiodeForStønadsperiode(clock: Clock): YearRange {
14+
val iÅr = Year.now(clock)
15+
val iForFjor = iÅr.minusYears(2)
16+
if (this == null) {
17+
return YearRange(iForFjor, iÅr)
18+
}
19+
20+
return this
21+
.toYearRange()
22+
.krympTilØvreGrense(iÅr)
23+
.utvidNedreGrense(iForFjor)
24+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package no.nav.su.se.bakover.domain.skatt
2+
3+
import io.kotest.matchers.shouldBe
4+
import no.nav.su.se.bakover.common.extensions.januar
5+
import no.nav.su.se.bakover.common.tid.YearRange
6+
import no.nav.su.se.bakover.common.tid.periode.desember
7+
import no.nav.su.se.bakover.common.tid.periode.januar
8+
import no.nav.su.se.bakover.common.tid.periode.juli
9+
import no.nav.su.se.bakover.common.tid.periode.juni
10+
import no.nav.su.se.bakover.domain.søknadsbehandling.stønadsperiode.Stønadsperiode
11+
import no.nav.su.se.bakover.test.fixedClockAt
12+
import org.junit.jupiter.api.Test
13+
import java.time.Year
14+
15+
internal class RegnUtSkatteperiodeForStønadsperiodeKtTest {
16+
private val jan24 = fixedClockAt(1.januar(2024))
17+
18+
@Test
19+
fun `stønadsperiode null`() {
20+
null.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
21+
YearRange(Year.of(2022), Year.of(2024)),
22+
)
23+
}
24+
25+
@Test
26+
fun `stønadsperiode 21`() {
27+
val stønadsperiode = Stønadsperiode.create(januar(2021)..desember(2021))
28+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
29+
YearRange(Year.of(2021), Year.of(2021)),
30+
)
31+
}
32+
33+
@Test
34+
fun `stønadsperiode 21 og 22`() {
35+
val stønadsperiode = Stønadsperiode.create(juli(2021)..juni(2022))
36+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
37+
YearRange(Year.of(2021), Year.of(2022)),
38+
)
39+
}
40+
41+
@Test
42+
fun `stønadsperiode 22`() {
43+
val stønadsperiode = Stønadsperiode.create(januar(2022)..desember(2022))
44+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
45+
YearRange(Year.of(2022), Year.of(2022)),
46+
)
47+
}
48+
49+
@Test
50+
fun `stønadsperiode 22 og 23`() {
51+
val stønadsperiode = Stønadsperiode.create(juli(2022)..juni(2023))
52+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
53+
YearRange(Year.of(2022), Year.of(2023)),
54+
)
55+
}
56+
57+
@Test
58+
fun `stønadsperiode 23`() {
59+
val stønadsperiode = Stønadsperiode.create(januar(2023)..desember(2023))
60+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
61+
YearRange(Year.of(2022), Year.of(2023)),
62+
)
63+
}
64+
65+
@Test
66+
fun `stønadsperiode 23 og 24`() {
67+
val stønadsperiode = Stønadsperiode.create(juli(2023)..juni(2024))
68+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
69+
YearRange(Year.of(2022), Year.of(2024)),
70+
)
71+
}
72+
73+
@Test
74+
fun `stønadsperiode 24`() {
75+
val stønadsperiode = Stønadsperiode.create(januar(2024)..desember(2024))
76+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
77+
YearRange(Year.of(2022), Year.of(2024)),
78+
)
79+
}
80+
81+
@Test
82+
fun `stønadsperiode 25`() {
83+
// Kun tenkt eksempel fram i tid (merk at dette skjer i jan 24). Dette skal ikke skje i praksis.
84+
val stønadsperiode = Stønadsperiode.create(januar(2025)..desember(2025))
85+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(jan24).shouldBe(
86+
YearRange(Year.of(2022), Year.of(2024)),
87+
)
88+
}
89+
}

service/src/main/kotlin/no/nav/su/se/bakover/service/skatt/SkatteService.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import no.nav.su.se.bakover.common.tid.YearRange
88
import no.nav.su.se.bakover.domain.skatt.Skattegrunnlag
99

1010
interface SkatteService {
11+
/**
12+
* Ikke i bruk. TODO jah: Slett?
13+
*/
1114
fun hentSamletSkattegrunnlag(
1215
fnr: Fnr,
1316
saksbehandler: NavIdentBruker.Saksbehandler,
@@ -19,6 +22,9 @@ interface SkatteService {
1922
yearRange: YearRange,
2023
): Skattegrunnlag
2124

25+
/**
26+
* Brukes for frioppslag på skattemelding.
27+
*/
2228
fun hentOgLagSkattePdf(request: FrioppslagSkattRequest): Either<KunneIkkeHenteOgLagePdfAvSkattegrunnlag, PdfA>
2329
fun hentLagOgJournalførSkattePdf(request: FrioppslagSkattRequest): Either<KunneIkkeGenerereSkattePdfOgJournalføre, PdfA>
2430
}

service/src/main/kotlin/no/nav/su/se/bakover/service/søknadsbehandling/SøknadsbehandlingServiceImpl.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ import no.nav.su.se.bakover.common.persistence.SessionFactory
1313
import no.nav.su.se.bakover.common.persistence.TransactionContext
1414
import no.nav.su.se.bakover.common.person.Fnr
1515
import no.nav.su.se.bakover.common.tid.YearRange
16-
import no.nav.su.se.bakover.common.tid.krympTilØvreGrense
17-
import no.nav.su.se.bakover.common.tid.toRange
1816
import no.nav.su.se.bakover.domain.Sak
1917
import no.nav.su.se.bakover.domain.behandling.BehandlingMetrics
2018
import no.nav.su.se.bakover.domain.grunnlag.Bosituasjon.Companion.harEPS
@@ -29,6 +27,7 @@ import no.nav.su.se.bakover.domain.revurdering.vilkår.bosituasjon.LeggTilBositu
2927
import no.nav.su.se.bakover.domain.sak.SakService
3028
import no.nav.su.se.bakover.domain.sak.lagNyUtbetaling
3129
import no.nav.su.se.bakover.domain.skatt.Skattegrunnlag
30+
import no.nav.su.se.bakover.domain.skatt.regnUtSkatteperiodeForStønadsperiode
3231
import no.nav.su.se.bakover.domain.statistikk.StatistikkEvent
3332
import no.nav.su.se.bakover.domain.statistikk.StatistikkEventObserver
3433
import no.nav.su.se.bakover.domain.statistikk.notify
@@ -98,7 +97,6 @@ import satser.domain.SatsFactory
9897
import vilkår.formue.domain.FormuegrenserFactory
9998
import økonomi.domain.utbetaling.UtbetalingsinstruksjonForEtterbetalinger
10099
import java.time.Clock
101-
import java.time.Year
102100
import java.util.UUID
103101
import kotlin.reflect.KClass
104102

@@ -787,7 +785,8 @@ class SøknadsbehandlingServiceImpl(
787785
saksbehandler: NavIdentBruker.Saksbehandler,
788786
samletSkattegrunnlag: (Fnr, NavIdentBruker.Saksbehandler, YearRange) -> Skattegrunnlag,
789787
clock: Clock,
790-
): Skattegrunnlag = samletSkattegrunnlag(fnr, saksbehandler, getYearRangeForSkatt(clock))
788+
): Skattegrunnlag =
789+
samletSkattegrunnlag(fnr, saksbehandler, stønadsperiode.regnUtSkatteperiodeForStønadsperiode(clock))
791790

792791
private fun Søknadsbehandling.hentSkattegrunnlagForEps(
793792
saksbehandler: NavIdentBruker.Saksbehandler,
@@ -797,15 +796,9 @@ class SøknadsbehandlingServiceImpl(
797796
samletSkattegrunnlag(
798797
grunnlagsdata.bosituasjon.singleFullstendigEpsOrNull()!!.fnr,
799798
saksbehandler,
800-
getYearRangeForSkatt(clock),
799+
stønadsperiode.regnUtSkatteperiodeForStønadsperiode(clock),
801800
)
802801
} else {
803802
null
804803
}
805-
806-
private fun Søknadsbehandling.getYearRangeForSkatt(clock: Clock): YearRange {
807-
return Year.now(clock).minusYears(1).let {
808-
stønadsperiode?.toYearRange()?.krympTilØvreGrense(it) ?: it.toRange()
809-
}
810-
}
811804
}

service/src/test/kotlin/no/nav/su/se/bakover/service/søknadsbehandling/SøknadsbehandlingSkattTest.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package no.nav.su.se.bakover.service.søknadsbehandling
33
import io.kotest.assertions.arrow.core.shouldBeLeft
44
import io.kotest.assertions.arrow.core.shouldBeRight
55
import io.kotest.matchers.shouldBe
6-
import no.nav.su.se.bakover.common.tid.toRange
6+
import no.nav.su.se.bakover.common.tid.YearRange
77
import no.nav.su.se.bakover.domain.grunnlag.EksterneGrunnlagSkatt
88
import no.nav.su.se.bakover.domain.grunnlag.StøtterHentingAvEksternGrunnlag
99
import no.nav.su.se.bakover.domain.søknadsbehandling.SøknadsbehandlingRepo
@@ -18,7 +18,6 @@ import org.mockito.kotlin.any
1818
import org.mockito.kotlin.anyOrNull
1919
import org.mockito.kotlin.doReturn
2020
import org.mockito.kotlin.mock
21-
import org.mockito.kotlin.times
2221
import org.mockito.kotlin.verify
2322
import org.mockito.kotlin.verifyNoMoreInteractions
2423
import java.time.Year
@@ -47,7 +46,7 @@ class SøknadsbehandlingSkattTest {
4746
verify(skatteServiceMock).hentSamletSkattegrunnlagForÅr(
4847
argThat { it shouldBe søknadsbehandling.fnr },
4948
argThat { it shouldBe saksbehandler },
50-
argThat { it shouldBe Year.of(2020).toRange() },
49+
argThat { it shouldBe YearRange(Year.of(2019), Year.of(2021)) },
5150
)
5251

5352
verify(søknadsbehandlingRepoMock).lagre(
Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package no.nav.su.se.bakover.test
22

3+
import org.json.JSONObject
34
import org.skyscreamer.jsonassert.Customization
45
import org.skyscreamer.jsonassert.JSONAssert
56
import org.skyscreamer.jsonassert.JSONCompareMode
@@ -13,16 +14,30 @@ fun jsonAssertEquals(
1314
actual: String,
1415
vararg ignorePaths: String,
1516
) {
16-
JSONAssert.assertEquals(
17-
expected,
18-
actual,
19-
CustomComparator(
20-
JSONCompareMode.STRICT,
21-
*ignorePaths.map {
22-
Customization(
23-
it,
24-
) { _, _ -> true }
25-
}.toTypedArray(),
26-
),
27-
)
17+
try {
18+
JSONAssert.assertEquals(
19+
expected,
20+
actual,
21+
CustomComparator(
22+
JSONCompareMode.STRICT,
23+
*ignorePaths.map {
24+
Customization(
25+
it,
26+
) { _, _ -> true }
27+
}.toTypedArray(),
28+
),
29+
)
30+
} catch (error: AssertionError) {
31+
throw AssertionError(
32+
"""
33+
|JSONAssert.assertEquals failed:
34+
|
35+
|Expected: ${JSONObject(expected).toString(2)}
36+
|
37+
|Actual: ${JSONObject(actual).toString(2)}
38+
|
39+
|Error: ${error.message}
40+
""".trimMargin(),
41+
)
42+
}
2843
}

web-regresjonstest/src/main/kotlin/no/nav/su/se/bakover/web/SharedRegressionTestData.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ data class TestClientsBuilder(
351351
klageClient = KlageClientStub,
352352
queryJournalpostClient = QueryJournalpostClientStub,
353353
tilbakekrevingClient = TilbakekrevingClientStub(clock),
354-
skatteOppslag = SkatteClientStub(),
354+
skatteOppslag = SkatteClientStub(clock),
355355
)
356356

357357
override fun build(applicationConfig: ApplicationConfig): Clients = testClients

0 commit comments

Comments
 (0)