Skip to content

Commit 8346562

Browse files
ramrock93tendestad
andauthored
Validere gyldigeperioder per aktivitetstype og pr. arbeidsgiver (#319)
* Tester for validering pr. fraværsaktivitet og arbeidsgiver. * Unngår exception ved intern overlapp ved sjekk mot gyldige perioder. Overlapp valideres uansett et annet sted * Mulighet for mer nøyaktig validering av endringer fra punsj * Tester for validering av overlappende hos samme arbeidsgiver. Like/overlappende perioder hos samme arbeidsgiver skal feile. Like/overlappende perioder hos ulike arbeidsgiver skal ikke feile. Co-authored-by: Tore Langedal Endestad <[email protected]>
1 parent 666cad9 commit 8346562

File tree

4 files changed

+304
-133
lines changed

4 files changed

+304
-133
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package no.nav.k9.søknad.ytelse.omsorgspenger.v1;
2+
3+
import static no.nav.k9.søknad.TidsserieUtils.tilPeriodeList;
4+
import static no.nav.k9.søknad.TidsserieUtils.toLocalDateTimeline;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Objects;
10+
import java.util.stream.Collectors;
11+
12+
import no.nav.fpsak.tidsserie.LocalDateSegment;
13+
import no.nav.fpsak.tidsserie.LocalDateTimeline;
14+
import no.nav.fpsak.tidsserie.StandardCombinators;
15+
import no.nav.k9.søknad.felles.Feil;
16+
import no.nav.k9.søknad.felles.fravær.AktivitetFravær;
17+
import no.nav.k9.søknad.felles.fravær.FraværPeriode;
18+
import no.nav.k9.søknad.felles.type.Organisasjonsnummer;
19+
import no.nav.k9.søknad.felles.type.Periode;
20+
import no.nav.k9.søknad.ytelse.Ytelse;
21+
22+
class OmsorgspengerUbetalingDelvalidatorEndringsperioder {
23+
24+
public List<Feil> validerMotGyldigEndringsperode(Ytelse ytelse, List<Periode> gyldigeEndringsperioder) {
25+
Objects.requireNonNull(gyldigeEndringsperioder, "gyldigeEndringsperioder");
26+
27+
var omsorgspengerUtbetaling = (OmsorgspengerUtbetaling) ytelse;
28+
var feil = new ArrayList<Feil>();
29+
30+
try {
31+
feil.addAll(validerMotGyldigePerioder(omsorgspengerUtbetaling, gyldigeEndringsperioder));
32+
} catch (ValideringsAvbrytendeFeilException valideringsAvbrytendeFeilException) {
33+
feil.addAll(valideringsAvbrytendeFeilException.getFeilList());
34+
}
35+
36+
return feil;
37+
}
38+
39+
/**
40+
* for å kunne validere endringer mer nøyaktig fra punsj
41+
*/
42+
public List<Feil> validerMotGyldigEndringsperode(Ytelse ytelse, Map<AktivitetFravær, List<Periode>> gyldigeEndringsperioderSøknad, Map<Organisasjonsnummer, List<Periode>> gyldigeKorrigeringsperioderIm) {
43+
var omsorgspengerUtbetaling = (OmsorgspengerUtbetaling) ytelse;
44+
var feil = new ArrayList<Feil>();
45+
46+
try {
47+
feil.addAll(validerSøknadMotGyldigePerioder(omsorgspengerUtbetaling, gyldigeEndringsperioderSøknad));
48+
feil.addAll(validerKorrigeringImMotGyldigePerioder(omsorgspengerUtbetaling, gyldigeKorrigeringsperioderIm));
49+
} catch (ValideringsAvbrytendeFeilException valideringsAvbrytendeFeilException) {
50+
feil.addAll(valideringsAvbrytendeFeilException.getFeilList());
51+
}
52+
return feil;
53+
}
54+
55+
private List<Feil> validerMotGyldigePerioder(OmsorgspengerUtbetaling omp, List<Periode> gyldigeEndringsperioder) {
56+
List<Feil> feilene = new ArrayList<>();
57+
if (omp.getFraværsperioder() != null) {
58+
feilene.addAll(validerSøknadMotGyldigePerioder(omp.getFraværsperioder(), gyldigeEndringsperioder));
59+
}
60+
if (omp.getFraværsperioderKorrigeringIm() != null) {
61+
feilene.addAll(validerKorrigeringImMotGyldigePerioder(omp.getFraværsperioderKorrigeringIm(), gyldigeEndringsperioder));
62+
}
63+
return feilene;
64+
}
65+
66+
private List<Feil> validerKorrigeringImMotGyldigePerioder(OmsorgspengerUtbetaling omp, Map<Organisasjonsnummer, List<Periode>> gyldigeKorrigeringsperioderIm) {
67+
if (omp.getFraværsperioderKorrigeringIm() == null) {
68+
return List.of();
69+
}
70+
List<Feil> feilene = new ArrayList<>();
71+
Map<Organisasjonsnummer, List<FraværPeriode>> korrigeringerPrArbeidsgiver = omp.getFraværsperioderKorrigeringIm().stream().collect(Collectors.groupingBy(FraværPeriode::getArbeidsgiverOrgNr));
72+
korrigeringerPrArbeidsgiver.forEach((aktuellArbeidsgiver, korrigeringer) -> feilene.addAll(validerKorrigeringImMotGyldigePerioder(korrigeringer, gyldigeKorrigeringsperioderIm.get(aktuellArbeidsgiver))));
73+
return feilene;
74+
}
75+
76+
List<Feil> validerSøknadMotGyldigePerioder(OmsorgspengerUtbetaling omp, Map<AktivitetFravær, List<Periode>> gyldigeEndringsperioder) {
77+
if (omp.getFraværsperioder() == null) {
78+
return List.of();
79+
}
80+
List<Feil> feilene = new ArrayList<>();
81+
for (AktivitetFravær aktivitestype : AktivitetFravær.values()) {
82+
List<FraværPeriode> aktuelleFraværPerioder = omp.getFraværsperioder().stream().filter(fp -> fp.getAktivitetFravær().contains(aktivitestype)).toList();
83+
List<Periode> aktuelleEndringsperioder = gyldigeEndringsperioder.getOrDefault(aktivitestype, List.of());
84+
feilene.addAll(validerSøknadMotGyldigePerioder(aktuelleFraværPerioder, aktuelleEndringsperioder));
85+
}
86+
return feilene;
87+
}
88+
89+
private List<Feil> validerSøknadMotGyldigePerioder(List<FraværPeriode> fraværPerioder, List<Periode> gyldigeEndringsperioder) {
90+
final LocalDateTimeline<Boolean> fraværsperioderTidslinje = lagTidslinjeGodtaOverlapp(tilPerioder(fraværPerioder), "fraværsperioder.perioder");
91+
final LocalDateTimeline<Boolean> gyldigEndringsperiodeTidslinje = lagTidslinjeOgValider(gyldigeEndringsperioder, "gyldigeEndringsperioder.perioder");
92+
return validerAtYtelsePerioderErInnenforIntervalForEndring(fraværsperioderTidslinje, gyldigEndringsperiodeTidslinje, "fraværsperioder.perioder");
93+
}
94+
95+
private List<Feil> validerKorrigeringImMotGyldigePerioder(List<FraværPeriode> fraværPerioder, List<Periode> gyldigeEndringsperioder) {
96+
final LocalDateTimeline<Boolean> fraværsperioderKorrigeringImTidslinje = lagTidslinjeGodtaOverlapp(tilPerioder(fraværPerioder), "fraværsperioderKorrigeringIm.perioder");
97+
final LocalDateTimeline<Boolean> gyldigEndringsperiodeTidslinje = lagTidslinjeOgValider(gyldigeEndringsperioder, "gyldigeEndringsperioder.perioder");
98+
return validerAtYtelsePerioderErInnenforIntervalForEndring(fraværsperioderKorrigeringImTidslinje, gyldigEndringsperiodeTidslinje, "fraværsperioderKorrigeringIm.perioder");
99+
}
100+
101+
private static List<Periode> tilPerioder(List<FraværPeriode> fraværPerioder) {
102+
return fraværPerioder.stream().map(FraværPeriode::getPeriode).toList();
103+
}
104+
105+
private LocalDateTimeline<Boolean> lagTidslinjeOgValider(List<Periode> periodeList, String felt) throws ValideringsAvbrytendeFeilException {
106+
var nyFeil = validerPerioderErLukketOgGyldig(periodeList, felt);
107+
if (!nyFeil.isEmpty()) {
108+
throw new ValideringsAvbrytendeFeilException(nyFeil);
109+
}
110+
try {
111+
return toLocalDateTimeline(periodeList);
112+
} catch (RuntimeException e) {
113+
throw new ValideringsAvbrytendeFeilException(List.of(lagFeil(felt, e.getClass().getSimpleName(), e.getMessage())));
114+
}
115+
}
116+
117+
private LocalDateTimeline<Boolean> lagTidslinjeGodtaOverlapp(List<Periode> perioder, String felt) throws ValideringsAvbrytendeFeilException {
118+
var nyFeil = validerPerioderErLukketOgGyldig(perioder, felt);
119+
if (!nyFeil.isEmpty()) {
120+
throw new ValideringsAvbrytendeFeilException(nyFeil);
121+
}
122+
List<LocalDateSegment<Boolean>> segmenter = perioder.stream().map(p -> new LocalDateSegment<>(p.getFraOgMed(), p.getTilOgMed(), true)).toList();
123+
return new LocalDateTimeline<>(segmenter, StandardCombinators::alwaysTrueForMatch);
124+
}
125+
126+
private List<Feil> validerAtYtelsePerioderErInnenforIntervalForEndring(
127+
LocalDateTimeline<Boolean> søknadsperiodeTidslinje,
128+
LocalDateTimeline<Boolean> gyldigePerioderTidslinje,
129+
String felt) {
130+
131+
LocalDateTimeline<Boolean> fellesPerioder = søknadsperiodeTidslinje.disjoint(gyldigePerioderTidslinje);
132+
133+
return tilPeriodeList(fellesPerioder)
134+
.stream()
135+
.map((Periode ugyldigPeriode) -> toFeil(ugyldigPeriode, felt, "ugyldigPeriode",
136+
"Perioden er utenfor gyldig interval. Gyldig interval: (" + gyldigePerioderTidslinje.getLocalDateIntervals() + "), Ugyldig periode: "))
137+
.toList();
138+
}
139+
140+
private List<Feil> validerPerioderErLukketOgGyldig(List<Periode> periodeList, String felt) {
141+
var feil = new ArrayList<Feil>();
142+
for (int i = 0; i < periodeList.size(); i++) {
143+
var periode = periodeList.get(i);
144+
if (periode != null) {
145+
validerPerioderErLukket(periode, felt + "[" + i + "]", feil);
146+
validerPerioderIkkeErInvertert(periode, felt + "[" + i + "]", feil);
147+
}
148+
}
149+
return feil;
150+
}
151+
152+
private void validerPerioderErLukket(Periode periode, String felt, List<Feil> feil) {
153+
if (periode.getTilOgMed() == null) {
154+
feil.add(lagFeil(felt, "påkrevd", "Til og med (TOM) må være satt."));
155+
}
156+
if (periode.getFraOgMed() == null) {
157+
feil.add(lagFeil(felt, "påkrevd", "Fra og med (FOM) må være satt."));
158+
}
159+
}
160+
161+
private void validerPerioderIkkeErInvertert(Periode periode, String felt, List<Feil> feil) {
162+
if (periode.getFraOgMed() != null && periode.getTilOgMed() != null && periode.getTilOgMed().isBefore(periode.getFraOgMed())) {
163+
feil.add(lagFeil(felt, "ugyldigPeriode", "Fra og med (FOM) må være før eller lik til og med (TOM)."));
164+
}
165+
}
166+
167+
private Feil toFeil(Periode periode, String felt, String feilkode, String feilmelding) {
168+
return lagFeil(felt, feilkode, feilmelding + periode.toString());
169+
}
170+
171+
private Feil lagFeil(String felt, String feilkode, String feilmelding) {
172+
return new Feil("ytelse." + felt, feilkode, feilmelding);
173+
}
174+
175+
176+
}

soknad/src/main/java/no/nav/k9/søknad/ytelse/omsorgspenger/v1/OmsorgspengerUtbetalingValidator.java

Lines changed: 17 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
package no.nav.k9.søknad.ytelse.omsorgspenger.v1;
22

3+
import java.time.Duration;
4+
import java.util.ArrayList;
5+
import java.util.HashMap;
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Objects;
10+
import java.util.Optional;
11+
import java.util.Set;
12+
313
import no.nav.fpsak.tidsserie.LocalDateSegment;
414
import no.nav.fpsak.tidsserie.LocalDateTimeline;
515
import no.nav.k9.søknad.PeriodeValidator;
@@ -15,12 +25,6 @@
1525
import no.nav.k9.søknad.ytelse.Ytelse;
1626
import no.nav.k9.søknad.ytelse.YtelseValidator;
1727

18-
import java.time.Duration;
19-
import java.util.*;
20-
21-
import static no.nav.k9.søknad.TidsserieUtils.tilPeriodeList;
22-
import static no.nav.k9.søknad.TidsserieUtils.toLocalDateTimeline;
23-
2428
class OmsorgspengerUtbetalingValidator extends YtelseValidator {
2529
private final String YTELSE_FELT = "ytelse.";
2630

@@ -54,100 +58,20 @@ public List<Feil> valider(Ytelse ytelse, List<Periode> gyldigeEndringsperioder)
5458
Objects.requireNonNull(gyldigeEndringsperioder, "gyldigeEndringsperioder");
5559
final List<Feil> feil = new ArrayList<>();
5660
feil.addAll(valider(ytelse));
57-
feil.addAll(validerMedGyldigEndringsperodeHvisDenFinnes(ytelse, gyldigeEndringsperioder));
58-
return feil;
59-
}
60-
61-
List<Feil> validerMedGyldigEndringsperodeHvisDenFinnes(Ytelse ytelse, List<Periode> gyldigeEndringsperioder) {
62-
Objects.requireNonNull(gyldigeEndringsperioder, "gyldigeEndringsperioder");
63-
64-
var omsorgspengerUtbetaling = (OmsorgspengerUtbetaling) ytelse;
65-
var feil = new ArrayList<Feil>();
66-
67-
try {
68-
feil.addAll(validerMotGyldigePerioder(omsorgspengerUtbetaling, gyldigeEndringsperioder));
69-
} catch (ValideringsAvbrytendeFeilException valideringsAvbrytendeFeilException) {
70-
feil.addAll(valideringsAvbrytendeFeilException.getFeilList());
71-
}
7261

62+
feil.addAll(new OmsorgspengerUbetalingDelvalidatorEndringsperioder().validerMotGyldigEndringsperode(ytelse, gyldigeEndringsperioder));
7363
return feil;
7464
}
7565

76-
List<Feil> validerMotGyldigePerioder(OmsorgspengerUtbetaling omp, List<Periode> gyldigeEndringsperioder) {
77-
if (omp.getFraværsperioder() != null && !omp.getFraværsperioder().isEmpty()) {
78-
79-
List<Periode> fraværsperioder = omp.getFraværsperioder().stream().map(FraværPeriode::getPeriode).toList();
80-
final LocalDateTimeline<Boolean> fraværsperioderTidslinje = lagTidslinjeOgValider(fraværsperioder, "fraværsperioder.perioder");
81-
final LocalDateTimeline<Boolean> gyldigEndringsperiodeTidslinje = lagTidslinjeOgValider(gyldigeEndringsperioder, "gyldigeEndringsperioder.perioder");
82-
83-
return validerAtYtelsePerioderErInnenforIntervalForEndring(fraværsperioderTidslinje, gyldigEndringsperiodeTidslinje, "fraværsperioder.perioder");
84-
85-
} else if (omp.getFraværsperioderKorrigeringIm() != null && !omp.getFraværsperioderKorrigeringIm().isEmpty()) {
86-
87-
List<Periode> fraværsperioderKorrigeringIm = omp.getFraværsperioderKorrigeringIm().stream().map(FraværPeriode::getPeriode).toList();
88-
final LocalDateTimeline<Boolean> fraværsperioderKorrigeringImTidslinje = lagTidslinjeOgValider(fraværsperioderKorrigeringIm, "fraværsperioderKorrigeringIm.perioder");
89-
final LocalDateTimeline<Boolean> gyldigEndringsperiodeTidslinje = lagTidslinjeOgValider(gyldigeEndringsperioder, "gyldigeEndringsperioder.perioder");
90-
91-
return validerAtYtelsePerioderErInnenforIntervalForEndring(fraværsperioderKorrigeringImTidslinje, gyldigEndringsperiodeTidslinje, "fraværsperioderKorrigeringIm.perioder");
92-
}
93-
94-
else return List.of();
95-
}
96-
97-
private List<Feil> validerPerioderErLukketOgGyldig(List<Periode> periodeList, String felt) {
98-
var feil = new ArrayList<Feil>();
99-
for (int i = 0; i < periodeList.size(); i++) {
100-
var periode = periodeList.get(i);
101-
if (periode != null) {
102-
validerPerioderErLukket(periode, felt + "[" + i + "]", feil);
103-
validerPerioderIkkeErInvertert(periode, felt + "[" + i + "]", feil);
104-
}
105-
}
66+
public List<Feil> valider(Ytelse ytelse, Map<AktivitetFravær, List<Periode>> gyldigeEndringsperioderSøknad, Map<Organisasjonsnummer, List<Periode>> gyldigeKorrigeringsperioderIm) {
67+
Objects.requireNonNull(gyldigeEndringsperioderSøknad, "gyldigeEndringsperioder");
68+
Objects.requireNonNull(gyldigeKorrigeringsperioderIm, "gyldigeKorrigeringsperioderIm");
69+
final List<Feil> feil = new ArrayList<>();
70+
feil.addAll(valider(ytelse));
71+
feil.addAll(new OmsorgspengerUbetalingDelvalidatorEndringsperioder().validerMotGyldigEndringsperode(ytelse, gyldigeEndringsperioderSøknad, gyldigeKorrigeringsperioderIm));
10672
return feil;
10773
}
10874

109-
private void validerPerioderErLukket(Periode periode, String felt, List<Feil> feil) {
110-
if (periode.getTilOgMed() == null) {
111-
feil.add(lagFeil(felt, "påkrevd", "Til og med (TOM) må være satt."));
112-
}
113-
if (periode.getFraOgMed() == null) {
114-
feil.add(lagFeil(felt, "påkrevd", "Fra og med (FOM) må være satt."));
115-
}
116-
}
117-
118-
private void validerPerioderIkkeErInvertert(Periode periode, String felt, List<Feil> feil) {
119-
if (periode.getFraOgMed() != null && periode.getTilOgMed() != null && periode.getTilOgMed().isBefore(periode.getFraOgMed())) {
120-
feil.add(lagFeil(felt, "ugyldigPeriode", "Fra og med (FOM) må være før eller lik til og med (TOM)."));
121-
}
122-
}
123-
124-
private LocalDateTimeline<Boolean> lagTidslinjeOgValider(List<Periode> periodeList, String felt) throws ValideringsAvbrytendeFeilException {
125-
var nyFeil = validerPerioderErLukketOgGyldig(periodeList, felt);
126-
if (!nyFeil.isEmpty()) {
127-
throw new ValideringsAvbrytendeFeilException(nyFeil);
128-
}
129-
try {
130-
return toLocalDateTimeline(periodeList);
131-
} catch (RuntimeException e) {
132-
throw new ValideringsAvbrytendeFeilException(List.of(lagFeil(felt, e.getClass().getSimpleName(), e.getMessage())));
133-
}
134-
}
135-
136-
private List<Feil> validerAtYtelsePerioderErInnenforIntervalForEndring(
137-
LocalDateTimeline<Boolean> søknadsperiodeTidslinje,
138-
LocalDateTimeline<Boolean> gyldigePerioderTidslinje,
139-
String felt
140-
) {
141-
142-
LocalDateTimeline<Boolean> fellesPerioder = søknadsperiodeTidslinje.disjoint(gyldigePerioderTidslinje);
143-
144-
return tilPeriodeList(fellesPerioder)
145-
.stream()
146-
.map((Periode ugyldigPeriode) -> toFeil(ugyldigPeriode, felt, "ugyldigPeriode",
147-
"Perioden er utenfor gyldig interval. Gyldig interval: (" + gyldigePerioderTidslinje.getLocalDateIntervals() + "), Ugyldig periode: "))
148-
.toList();
149-
}
150-
15175
private List<Feil> validerPeriodeInnenforEttÅr(OmsorgspengerUtbetaling ytelse) {
15276
if (ytelse.getFraværsperioder() != null && ytelse.getFraværsperioder().stream().anyMatch(OmsorgspengerUtbetalingValidator::erPeriodeUgyldig)) {
15377
//avbryter her for å unngå NPE i koden under når periode ikke er satt, eller ikke er satt ordentlig
@@ -539,20 +463,4 @@ private Feil lagFeil(String felt, String feilkode, String feilmelding) {
539463
return new Feil(YTELSE_FELT + felt, feilkode, feilmelding);
540464
}
541465

542-
private Feil toFeil(Periode periode, String felt, String feilkode, String feilmelding) {
543-
return lagFeil(felt, feilkode, feilmelding + periode.toString());
544-
}
545-
546-
static class ValideringsAvbrytendeFeilException extends RuntimeException {
547-
548-
private final List<Feil> feilList;
549-
550-
public ValideringsAvbrytendeFeilException(List<Feil> feilList) {
551-
this.feilList = feilList;
552-
}
553-
554-
public List<Feil> getFeilList() {
555-
return feilList;
556-
}
557-
}
558466
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package no.nav.k9.søknad.ytelse.omsorgspenger.v1;
2+
3+
import java.util.List;
4+
5+
import no.nav.k9.søknad.felles.Feil;
6+
7+
class ValideringsAvbrytendeFeilException extends RuntimeException {
8+
9+
private final List<Feil> feilList;
10+
11+
public ValideringsAvbrytendeFeilException(List<Feil> feilList) {
12+
this.feilList = feilList;
13+
}
14+
15+
public List<Feil> getFeilList() {
16+
return feilList;
17+
}
18+
}

0 commit comments

Comments
 (0)