@@ -4,6 +4,7 @@ import arrow.core.Either
4
4
import arrow.core.NonEmptyList
5
5
import arrow.core.left
6
6
import arrow.core.right
7
+ import no.nav.su.se.bakover.common.domain.Saksnummer
7
8
import no.nav.su.se.bakover.common.extensions.toNonEmptyList
8
9
import no.nav.su.se.bakover.common.person.Fnr
9
10
import no.nav.su.se.bakover.common.sikkerLogg
@@ -39,43 +40,95 @@ class PersonhendelseServiceImpl(
39
40
private fun prosesserNyHendelseForBruker (
40
41
personhendelse : Personhendelse .IkkeTilknyttetSak ,
41
42
isLiveRun : Boolean ,
42
- ): Either < Unit , Unit > {
43
+ ): PersonhendelseresultatBruker {
43
44
val fødselsnumre = personhendelse.metadata.personidenter.mapNotNull { Fnr .tryCreate(it) }
44
45
val fraOgMedEllerSenere = M åned.now(clock)
45
46
val vedtaksammendragForSak = vedtakService.hentForBrukerFødselsnumreOgFraOgMedMåned(
46
47
fødselsnumre = fødselsnumre,
47
48
fraOgMed = fraOgMedEllerSenere,
48
49
).singleOrNull()
50
+ if (vedtaksammendragForSak == null ) {
51
+ return PersonhendelseresultatBruker .IkkeRelevantHendelseForBruker .IngenSakEllerVedtak (
52
+ identer = personhendelse.metadata.personidenter,
53
+ )
54
+ }
49
55
50
56
return prosesserVedtaksammendragForSak(
51
57
vedtaksammendragForSak = vedtaksammendragForSak,
52
58
fraOgMedEllerSenere = fraOgMedEllerSenere,
53
59
personhendelse = personhendelse,
54
60
isLiveRun = isLiveRun,
55
61
gjelderEps = false ,
56
- )
62
+ ).let {
63
+ it.fold(
64
+ {
65
+ PersonhendelseresultatBruker .IkkeRelevantHendelseForBruker .IngenAktiveVedtak (
66
+ saksnummer = vedtaksammendragForSak.saksnummer,
67
+ fnr = vedtaksammendragForSak.fødselsnummer,
68
+ identer = personhendelse.metadata.personidenter,
69
+ )
70
+ },
71
+ {
72
+ PersonhendelseresultatBruker .TreffP åBruker (
73
+ saksnummer = vedtaksammendragForSak.saksnummer,
74
+ fnr = vedtaksammendragForSak.fødselsnummer,
75
+ identer = personhendelse.metadata.personidenter,
76
+ )
77
+ },
78
+ )
79
+ }
57
80
}
58
81
59
82
private fun prosesserNyHendelseForEps (
60
83
personhendelse : Personhendelse .IkkeTilknyttetSak ,
61
84
isLiveRun : Boolean ,
62
- ): List < Either < Unit , Unit >> {
85
+ ): PersonhendelseresultatEps {
63
86
val fødselsnumre = personhendelse.metadata.personidenter.mapNotNull { Fnr .tryCreate(it) }
64
87
val fraOgMedEllerSenere = M åned.now(clock)
65
- return vedtakService.hentForEpsFødselsnumreOgFraOgMedMåned(fødselsnumre, fraOgMedEllerSenere).map {
66
- prosesserVedtaksammendragForSak(it, fraOgMedEllerSenere, personhendelse, isLiveRun, gjelderEps = true )
88
+ val vedtaksammendragForSaker =
89
+ vedtakService.hentForEpsFødselsnumreOgFraOgMedMåned(fødselsnumre, fraOgMedEllerSenere)
90
+ if (vedtaksammendragForSaker.isEmpty()) {
91
+ return PersonhendelseresultatEps .IkkeTreffP åEps (identer = personhendelse.metadata.personidenter)
92
+ }
93
+ return vedtaksammendragForSaker.map { vedtaksammendragForSak ->
94
+ prosesserVedtaksammendragForSak(
95
+ vedtaksammendragForSak,
96
+ fraOgMedEllerSenere,
97
+ personhendelse,
98
+ isLiveRun,
99
+ gjelderEps = true ,
100
+ ) to vedtaksammendragForSak
101
+ }.map { (result, vedtaksammendragForSak) ->
102
+ result.fold(
103
+ {
104
+ PersonhendelseresultatEps .TreffP åEps .IkkeAktivtVedtak (
105
+ brukersSaksnummer = vedtaksammendragForSak.saksnummer,
106
+ brukersFnr = vedtaksammendragForSak.fødselsnummer,
107
+ identer = personhendelse.metadata.personidenter,
108
+ )
109
+ },
110
+ {
111
+ PersonhendelseresultatEps .TreffP åEps .AktivtVedtak (
112
+ brukersSaksnummer = vedtaksammendragForSak.saksnummer,
113
+ brukersFnr = vedtaksammendragForSak.fødselsnummer,
114
+ identer = personhendelse.metadata.personidenter,
115
+ )
116
+ },
117
+ )
118
+ }.let {
119
+ PersonhendelseresultatEps .TreffP åEnEllerFlereEps (it)
67
120
}
68
121
}
69
122
70
123
private fun prosesserVedtaksammendragForSak (
71
- vedtaksammendragForSak : VedtaksammendragForSak ? ,
124
+ vedtaksammendragForSak : VedtaksammendragForSak ,
72
125
fraOgMedEllerSenere : M åned,
73
126
personhendelse : Personhendelse .IkkeTilknyttetSak ,
74
127
isLiveRun : Boolean ,
75
128
gjelderEps : Boolean ,
76
129
): Either <Unit , Unit > {
77
130
return when {
78
- vedtaksammendragForSak == null || ! vedtaksammendragForSak.erInnvilgetForMånedEllerSenere(fraOgMedEllerSenere) -> Unit .left()
131
+ ! vedtaksammendragForSak.erInnvilgetForMånedEllerSenere(fraOgMedEllerSenere) -> Unit .left()
79
132
.also {
80
133
sikkerLogg.debug(
81
134
" Personhendelse - Forkaster hendelse som ikke er knyttet til aktiv/løpende sak. Hendelse: {}" ,
@@ -106,6 +159,64 @@ class PersonhendelseServiceImpl(
106
159
}
107
160
}
108
161
162
+ sealed interface PersonhendelseresultatBruker {
163
+ fun ikkeTreff (): Boolean = this is IkkeRelevantHendelseForBruker
164
+
165
+ fun unikeSaksnummer (): List <Saksnummer > = when (this ) {
166
+ is IkkeRelevantHendelseForBruker -> emptyList()
167
+ is TreffP åBruker -> listOf (this .saksnummer)
168
+ }
169
+
170
+ sealed interface IkkeRelevantHendelseForBruker : PersonhendelseresultatBruker {
171
+ val identer: List <String >
172
+
173
+ /* * Enten har vi ikke en sak, eller så har ikke den saken vedtak av typen søknad, endring, opphør. */
174
+ data class IngenSakEllerVedtak (override val identer : List <String >) : IkkeRelevantHendelseForBruker
175
+
176
+ /* * Vi har en sak med vedtak av typen søknad, endring, opphør; men ingen av disse var aktive etter fraOgMed dato */
177
+ data class IngenAktiveVedtak (override val identer : List <String >, val saksnummer : Saksnummer , val fnr : Fnr ) :
178
+ IkkeRelevantHendelseForBruker
179
+ }
180
+
181
+ data class TreffP åBruker (val saksnummer : Saksnummer , val fnr : Fnr , val identer : List <String >) :
182
+ PersonhendelseresultatBruker
183
+ }
184
+
185
+ sealed interface PersonhendelseresultatEps {
186
+ fun ikkeTreff (): Boolean
187
+
188
+ fun unikeSaksnummer (): List <Saksnummer > = when (this ) {
189
+ is IkkeTreffP åEps -> emptyList()
190
+ is TreffP åEnEllerFlereEps -> this .treff.map { it.brukersSaksnummer }
191
+ }.distinct().sortedBy { it.nummer }
192
+
193
+ data class IkkeTreffP åEps (val identer : List <String >) : PersonhendelseresultatEps {
194
+ override fun ikkeTreff (): Boolean = true
195
+ }
196
+
197
+ data class TreffP åEnEllerFlereEps (val treff : List <TreffP åEps >) : PersonhendelseresultatEps {
198
+ override fun ikkeTreff (): Boolean = treff.all { it is TreffP åEps .IkkeAktivtVedtak }
199
+ }
200
+
201
+ sealed interface TreffP åEps {
202
+ val brukersSaksnummer: Saksnummer
203
+ val brukersFnr: Fnr
204
+ val identer: List <String >
205
+
206
+ data class AktivtVedtak (
207
+ override val brukersSaksnummer : Saksnummer ,
208
+ override val brukersFnr : Fnr ,
209
+ override val identer : List <String >,
210
+ ) : TreffPåEps
211
+
212
+ data class IkkeAktivtVedtak (
213
+ override val brukersSaksnummer : Saksnummer ,
214
+ override val brukersFnr : Fnr ,
215
+ override val identer : List <String >,
216
+ ) : TreffPåEps
217
+ }
218
+ }
219
+
109
220
override fun opprettOppgaverForPersonhendelser () {
110
221
val personhendelser = personhendelseRepo.hentPersonhendelserUtenOppgave()
111
222
personhendelser.groupBy { it.sakId }
@@ -120,41 +231,52 @@ class PersonhendelseServiceImpl(
120
231
}
121
232
122
233
override fun dryRunPersonhendelser (personhendelser : List <Personhendelse .IkkeTilknyttetSak >): DryrunResult {
123
- val seenFnr = mutableSetOf<String >()
124
- // Vi prøver emulere produksjonskoden som slår sammen personhendelser på samme sak.
125
- // Et mulig unntak vil være 2 som får SU som bor sammen. Da kan det hende vi får en ekstra oppgave på de.
126
- // Men dette vil kun være et godt nok estimat
127
- val filteredHendelser = personhendelser.filter { hendelse ->
128
- val identer = hendelse.metadata.personidenter
129
- val seenAny = identer.any { seenFnr.contains(it) }
130
- seenFnr.addAll(identer)
131
- ! seenAny
132
- }
133
-
134
- return filteredHendelser.fold(DryrunResult .empty()) { acc, element ->
234
+ return personhendelser.fold(DryrunResult .empty()) { acc, element ->
135
235
val firstRes = prosesserNyHendelseForBruker(element, false )
136
236
val secondRes = prosesserNyHendelseForEps(element, false )
137
- when {
138
- firstRes.isLeft() && secondRes.all { it.isLeft() } -> acc.incForkastet()
139
- firstRes.isRight() -> acc.incBruker()
140
- else -> acc.plusEps(secondRes.mapNotNull { it.getOrNull() }.size)
141
- }
237
+ acc.leggTilHendelse(firstRes, secondRes)
142
238
}.also {
143
239
log.info(" Dry run for personhendelser: $it " )
240
+ sikkerLogg.info(" Dry run for personhendelser: ${it.toSikkerloggString()} " )
144
241
}
145
242
}
146
243
147
244
data class DryrunResult (
148
- val treffBruker : Int ,
149
- val treffEps : Int ,
150
- val forkastet : Int ,
245
+ val perHendelse : List <DryRunResultPerHendelse >,
151
246
) {
152
247
companion object {
153
- fun empty () = DryrunResult (0 , 0 , 0 )
248
+ fun empty () = DryrunResult (emptyList() )
154
249
}
155
- fun incBruker () = copy(treffBruker = treffBruker + 1 )
156
- fun incForkastet () = copy(forkastet = forkastet + 1 )
157
- fun plusEps (eps : Int ) = copy(treffEps = treffEps + eps)
250
+
251
+ fun leggTilHendelse (resultatBruker : PersonhendelseresultatBruker , resultatEps : PersonhendelseresultatEps ) =
252
+ DryrunResult (perHendelse + DryRunResultPerHendelse (resultatBruker, resultatEps))
253
+
254
+ val antallForkastet: Int by lazy { perHendelse.count { it.ikkeTreff() } }
255
+ val antallBruker: Int by lazy { perHendelse.count { it.resultatBruker is PersonhendelseresultatBruker .TreffP åBruker } }
256
+ val antallEps: Int by lazy { perHendelse.count { it.resultatEps is PersonhendelseresultatEps .TreffP åEnEllerFlereEps } }
257
+ val antallOppgaver: Int by lazy {
258
+ oppgaver.size
259
+ }
260
+
261
+ val forkastet: List <DryRunResultPerHendelse > by lazy { perHendelse.filter { it.ikkeTreff() } }
262
+ val bruker: List <PersonhendelseresultatBruker > by lazy { perHendelse.map { it.resultatBruker } }
263
+ val eps: List <PersonhendelseresultatEps > by lazy { perHendelse.map { it.resultatEps } }
264
+ val oppgaver: List <Saksnummer > by lazy {
265
+ (bruker.flatMap { it.unikeSaksnummer() } + eps.flatMap { it.unikeSaksnummer() }).distinct().sortedBy { it.nummer }
266
+ }
267
+
268
+ data class DryRunResultPerHendelse (
269
+ val resultatBruker : PersonhendelseresultatBruker ,
270
+ val resultatEps : PersonhendelseresultatEps ,
271
+ ) {
272
+ fun ikkeTreff (): Boolean = resultatBruker.ikkeTreff() && resultatEps.ikkeTreff()
273
+ }
274
+
275
+ override fun toString () =
276
+ " DryrunResult(antallForkastet=$antallForkastet , antallBruker=$antallBruker , antallEps=$antallEps , antallOppgaver=$antallOppgaver ). Se sikkerlogg for mer detaljer"
277
+
278
+ fun toSikkerloggString (): String =
279
+ " DryrunResult(antallForkastet=$antallForkastet , antallBruker=$antallBruker , antallEps=$antallEps , antallOppgaver=$antallOppgaver ). Forkastet: $forkastet , Bruker: $bruker , Eps: $eps , Oppgaver: $oppgaver "
158
280
}
159
281
160
282
private fun opprettOppgaveForSak (
0 commit comments