Skip to content

Commit c23c066

Browse files
authored
Pleiepenger i livets sluttfase - med validatorer og tester (#225)
1 parent 41f0be3 commit c23c066

File tree

12 files changed

+736
-31
lines changed

12 files changed

+736
-31
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package no.nav.k9.søknad.ytelse.pls.v1;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
6+
import javax.validation.Validation;
7+
import javax.validation.ValidatorFactory;
8+
9+
import no.nav.k9.søknad.Søknad;
10+
import no.nav.k9.søknad.SøknadValidator;
11+
import no.nav.k9.søknad.felles.Feil;
12+
import no.nav.k9.søknad.felles.Versjon;
13+
import no.nav.k9.søknad.felles.personopplysninger.Søker;
14+
import no.nav.k9.søknad.felles.type.Person;
15+
16+
public class PleiepengerLivetsSluttfaseSøknadValidator extends SøknadValidator<Søknad> {
17+
18+
private static final ValidatorFactory VALIDATOR_FACTORY = Validation.buildDefaultValidatorFactory();
19+
20+
@Override
21+
public List<Feil> valider(Søknad søknad) {
22+
var validate = VALIDATOR_FACTORY.getValidator().validate(søknad);
23+
24+
List<Feil> feil = validate.stream()
25+
.map(Feil::toFeil)
26+
.collect(Collectors.toList());
27+
28+
validerVersjon(søknad.getVersjon(), feil);
29+
validerPleietrengendeIkkeErSøker(søknad.getSøker(), søknad.getBerørtePersoner(), feil);
30+
validerPleietrengendeIkkeErSøker(søknad.getSøker(), List.of(((PleipengerLivetsSluttfase) søknad.getYtelse()).getPleietrengende()), feil);
31+
feil.addAll(new PleiepengerLivetsSluttfaseYtelseValidator().valider(søknad.getYtelse()));
32+
33+
return feil;
34+
}
35+
36+
private static void validerVersjon(Versjon versjon, List<Feil> feil) {
37+
if (versjon != null && !versjon.erGyldig()) {
38+
feil.add(new Feil("versjon", "ugyldigVersjon", "Versjonen er på ugyldig format."));
39+
}
40+
}
41+
42+
private static void validerPleietrengendeIkkeErSøker(Søker søker, List<Person> pleietrengende, List<Feil> feil) {
43+
if (søker == null || pleietrengende == null || pleietrengende.isEmpty()) {
44+
return;
45+
}
46+
if (pleietrengende.stream().anyMatch(person -> person.getPersonIdent() != null && person.getPersonIdent().equals(søker.getPersonIdent()))) {
47+
feil.add(new Feil("søker", "søkerSammeSomPleietrengende", "Søker kan ikke være samme person som er i livets sluttfase."));
48+
}
49+
}
50+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package no.nav.k9.søknad.ytelse.pls.v1;
2+
3+
import static no.nav.k9.søknad.TidsserieUtils.toLocalDateTimeline;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
import no.nav.fpsak.tidsserie.LocalDateTimeline;
10+
import no.nav.k9.søknad.felles.Feil;
11+
import no.nav.k9.søknad.felles.opptjening.AnnenAktivitet;
12+
import no.nav.k9.søknad.felles.opptjening.SelvstendigNæringsdrivende;
13+
import no.nav.k9.søknad.felles.type.Periode;
14+
import no.nav.k9.søknad.ytelse.Ytelse;
15+
import no.nav.k9.søknad.ytelse.YtelseValidator;
16+
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstaker;
17+
18+
public class PleiepengerLivetsSluttfaseYtelseValidator extends YtelseValidator {
19+
@Override
20+
public List<Feil> valider(Ytelse søknad) {
21+
return valider((PleipengerLivetsSluttfase) søknad);
22+
}
23+
24+
public List<Feil> valider(PleipengerLivetsSluttfase søknad) {
25+
List<Feil> feilene = new ArrayList<>();
26+
try {
27+
if (søknad.getSøknadsperiode() == null) {
28+
feilene.add(lagFeil("arbeidstid", "påkrevd", "det finnes ingen søknadsperiode"));
29+
}
30+
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getBosteder().getPerioder(), "bosteder.perioder"));
31+
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getBosteder().getPerioderSomSkalSlettes(), "bosteder.perioderSomSkalSlettes"));
32+
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getUtenlandsopphold().getPerioder(), "utenlandsopphold.perioder"));
33+
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getUtenlandsopphold().getPerioderSomSkalSlettes(), "utenlandsopphold.perioderSomSkalSlettes"));
34+
validerArbeidstid(søknad, feilene);
35+
validerOpptjening(søknad, feilene);
36+
} catch (ValideringsAvbrytendeFeilException valideringsAvbrytendeFeilException) {
37+
feilene.addAll(valideringsAvbrytendeFeilException.getFeilList());
38+
}
39+
return feilene;
40+
}
41+
42+
private void validerArbeidstid(PleipengerLivetsSluttfase søknad, List<Feil> feilene) {
43+
List<Arbeidstaker> arbeidstakerList = søknad.getArbeidstid().getArbeidstakerList();
44+
for (int i = 0; i < arbeidstakerList.size(); i++) {
45+
lagTidslinjeOgValider(arbeidstakerList.get(i).getArbeidstidInfo().getPerioder(), "arbeidstid.arbeidstakerList[" + i + "].perioder", feilene);
46+
}
47+
søknad.getArbeidstid().getSelvstendigNæringsdrivendeArbeidstidInfo().ifPresent(sn -> lagTidslinjeOgValider(sn.getPerioder(), "arbeidstid.selvstendigNæringsdrivendeArbeidstidInfo", feilene));
48+
søknad.getArbeidstid().getFrilanserArbeidstidInfo().ifPresent(fl -> lagTidslinjeOgValider(fl.getPerioder(), "arbeidstid.frilanserArbeidstidInfo", feilene));
49+
}
50+
51+
private void validerOpptjening(PleipengerLivetsSluttfase søknad, List<Feil> feilene) {
52+
List<SelvstendigNæringsdrivende> snAktiviteter = søknad.getOpptjeningAktivitet().getSelvstendigNæringsdrivende();
53+
for (int i = 0; i < snAktiviteter.size(); i++) {
54+
lagTidslinjeOgValider(snAktiviteter.get(i).getPerioder(), "opptjeningAktivitet.selvstendigNæringsdrivende[" + i + "].perioder", feilene);
55+
}
56+
57+
List<AnnenAktivitet> andreAktiviteter = søknad.getOpptjeningAktivitet().getAndreAktiviteter();
58+
for (int i = 0; i < andreAktiviteter.size(); i++) {
59+
validerPeriodeErLukketOgGyldig(andreAktiviteter.get(i).getPeriode(), "opptjeningAktivitet.andreAktiviteter[" + i + "].perioder", feilene);
60+
}
61+
}
62+
63+
private LocalDateTimeline<Boolean> lagTidslinjeOgValider(Map<Periode, ?> periodeMap, String felt, List<Feil> feil) throws ValideringsAvbrytendeFeilException {
64+
var nyFeil = validerPerioderErLukketOgGyldig(periodeMap, felt);
65+
if (!nyFeil.isEmpty()) {
66+
throw new ValideringsAvbrytendeFeilException(nyFeil);
67+
}
68+
try {
69+
return toLocalDateTimeline(new ArrayList<>(periodeMap.keySet()));
70+
} catch (IllegalArgumentException e) {
71+
throw new ValideringsAvbrytendeFeilException(List.of(lagFeil(felt, "IllegalArgumentException", e.getMessage())));
72+
}
73+
}
74+
75+
private List<Feil> validerPerioderErLukketOgGyldig(Map<Periode, ?> perioder, String felt) {
76+
var feil = new ArrayList<Feil>();
77+
perioder.keySet().forEach(p -> {
78+
validerPerioderErLukket(p, felt + "['" + p + "']", feil);
79+
validerPerioderIkkeErInvertert(p, felt + "['" + p + "']", feil);
80+
});
81+
return feil;
82+
}
83+
84+
private List<Feil> validerPerioderErLukketOgGyldig(List<Periode> periodeList, String felt) {
85+
var feil = new ArrayList<Feil>();
86+
for (int i = 0; i < periodeList.size(); i++) {
87+
var periode = periodeList.get(i);
88+
if (periode != null) {
89+
validerPerioderErLukket(periode, felt + "[" + i + "]", feil);
90+
validerPerioderIkkeErInvertert(periode, felt + "[" + i + "]", feil);
91+
}
92+
}
93+
return feil;
94+
}
95+
96+
private void validerPeriodeErLukketOgGyldig(Periode periode, String felt, List<Feil> feil) {
97+
validerPerioderErLukket(periode, felt, feil);
98+
validerPerioderIkkeErInvertert(periode, felt, feil);
99+
}
100+
101+
private void validerPerioderErLukket(Periode periode, String felt, List<Feil> feil) {
102+
if (periode.getTilOgMed() == null) {
103+
feil.add(lagFeil(felt, "påkrevd", "Til og med (TOM) må være satt."));
104+
}
105+
if (periode.getFraOgMed() == null) {
106+
feil.add(lagFeil(felt, "påkrevd", "Fra og med (FOM) må være satt."));
107+
}
108+
}
109+
110+
private void validerPerioderIkkeErInvertert(Periode periode, String felt, List<Feil> feil) {
111+
if (periode.getFraOgMed() != null && periode.getTilOgMed() != null && periode.getTilOgMed().isBefore(periode.getFraOgMed())) {
112+
feil.add(lagFeil(felt, "ugyldigPeriode", "Fra og med (FOM) må være før eller lik til og med (TOM)."));
113+
}
114+
}
115+
116+
private Feil lagFeil(String felt, String feilkode, String feilmelding) {
117+
return new Feil("ytelse." + felt, feilkode, feilmelding);
118+
}
119+
120+
static class ValideringsAvbrytendeFeilException extends RuntimeException {
121+
122+
private final List<Feil> feilList;
123+
124+
public ValideringsAvbrytendeFeilException(List<Feil> feilList) {
125+
this.feilList = feilList;
126+
}
127+
128+
public List<Feil> getFeilList() {
129+
return feilList;
130+
}
131+
}
132+
}

soknad/src/main/java/no/nav/k9/søknad/ytelse/pls/v1/PleipengerLivetsSluttfase.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package no.nav.k9.søknad.ytelse.pls.v1;
22

3+
import java.time.LocalDate;
4+
import java.util.ArrayList;
5+
import java.util.Comparator;
36
import java.util.List;
47
import java.util.Objects;
8+
import java.util.Optional;
9+
import java.util.stream.Collectors;
510

611
import javax.validation.Valid;
712
import javax.validation.constraints.NotNull;
@@ -18,12 +23,14 @@
1823
import no.nav.k9.søknad.felles.type.Person;
1924
import no.nav.k9.søknad.ytelse.Ytelse;
2025
import no.nav.k9.søknad.ytelse.YtelseValidator;
26+
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstaker;
2127
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstid;
28+
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.ArbeidstidInfo;
2229

2330
@JsonIgnoreProperties(ignoreUnknown = true)
2431
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
2532
@JsonTypeName(Ytelse.PLEIEPENGER_LIVETS_SLUTTFASE)
26-
public class PleipengerLivetsSluttfase implements Ytelse{
33+
public class PleipengerLivetsSluttfase implements Ytelse {
2734

2835
@Valid
2936
@NotNull
@@ -54,8 +61,7 @@ public Type getType() {
5461

5562
@Override
5663
public YtelseValidator getValidator() {
57-
//TODO lage validator
58-
return null;
64+
return new PleiepengerLivetsSluttfaseYtelseValidator();
5965
}
6066

6167
@Override
@@ -74,7 +80,28 @@ public Person getAnnenPart() {
7480

7581
@Override
7682
public Periode getSøknadsperiode() {
77-
//TODO utlede omsluttende periode
83+
List<ArbeidstidInfo> fraværsperioder = new ArrayList<>();
84+
arbeidstid.getFrilanserArbeidstidInfo().ifPresent(fraværsperioder::add);
85+
arbeidstid.getSelvstendigNæringsdrivendeArbeidstidInfo().ifPresent(fraværsperioder::add);
86+
arbeidstid.getArbeidstakerList().stream()
87+
.map(Arbeidstaker::getArbeidstidInfo)
88+
.forEach(fraværsperioder::add);
89+
90+
List<Periode> allePerioder = fraværsperioder.stream()
91+
.flatMap(ai -> ai.getPerioder().keySet().stream())
92+
.collect(Collectors.toList());
93+
Optional<LocalDate> fom = allePerioder.stream()
94+
.map(Periode::getFraOgMed)
95+
.filter(Objects::nonNull)
96+
.min(Comparator.naturalOrder());
97+
Optional<LocalDate> tom = allePerioder.stream()
98+
.map(Periode::getTilOgMed)
99+
.filter(Objects::nonNull)
100+
.max(Comparator.naturalOrder());
101+
102+
if (fom.isPresent() && tom.isPresent()) {
103+
return new Periode(fom.get(), tom.get());
104+
}
78105
return null;
79106
}
80107

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package no.nav.k9.søknad.ytelse.pls;
2+
3+
import java.time.ZonedDateTime;
4+
5+
import no.nav.k9.søknad.Søknad;
6+
import no.nav.k9.søknad.felles.Versjon;
7+
import no.nav.k9.søknad.felles.personopplysninger.Søker;
8+
import no.nav.k9.søknad.felles.type.NorskIdentitetsnummer;
9+
import no.nav.k9.søknad.felles.type.Periode;
10+
import no.nav.k9.søknad.felles.type.SøknadId;
11+
import no.nav.k9.søknad.ytelse.pls.v1.PleipengerLivetsSluttfase;
12+
import no.nav.k9.søknad.ytelse.pls.v1.YtelseEksempel;
13+
14+
public class SøknadEksempel {
15+
16+
public static Søknad søknad(PleipengerLivetsSluttfase ytelse) {
17+
return new Søknad(
18+
new SøknadId("1"),
19+
new Versjon("5.4.8"),
20+
ZonedDateTime.now(),
21+
new Søker(NorskIdentitetsnummer.of("22222222222")),
22+
ytelse
23+
);
24+
}
25+
26+
27+
public static Søknad søknadMedArbeidstid(Periode søknadsperiode) {
28+
return søknad(YtelseEksempel.ytelseForArbeidstaker(søknadsperiode));
29+
}
30+
31+
public static Søknad minimumSøknad(Periode søknadsperiode) {
32+
return søknad(YtelseEksempel.ytelseForArbeidstaker(søknadsperiode));
33+
}
34+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package no.nav.k9.søknad.ytelse.pls;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
7+
import no.nav.k9.søknad.Søknad;
8+
9+
public class SøknadJsonEksempel {
10+
11+
private static String jsonFromFile(String filename) {
12+
try {
13+
return Files.readString(Path.of("src/test/resources/ytelse/pls/" + filename));
14+
} catch (IOException e) {
15+
throw new RuntimeException(e);
16+
}
17+
}
18+
19+
public static Søknad komplettSøknad() {
20+
return Søknad.SerDes.deserialize(jsonFromFile("komplett-søknad.json"));
21+
}
22+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package no.nav.k9.søknad.ytelse.pls.v1;
2+
3+
import static no.nav.k9.søknad.ytelse.pls.v1.ValiderUtil.verifyIngenFeil;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
6+
import java.time.LocalDate;
7+
8+
import org.junit.jupiter.api.Test;
9+
10+
import no.nav.k9.søknad.felles.type.Periode;
11+
import no.nav.k9.søknad.ytelse.pls.SøknadJsonEksempel;
12+
13+
class SøknadJsonTest {
14+
15+
@Test
16+
public void happycaseSøknad() {
17+
var søknad = SøknadJsonEksempel.komplettSøknad();
18+
19+
verifyIngenFeil(søknad);
20+
21+
PleipengerLivetsSluttfase ytelse = søknad.getYtelse();
22+
23+
assertThat(ytelse.getPleietrengende().getPersonIdent().getVerdi()).isEqualTo("22111111111");
24+
assertThat(ytelse.getSøknadsperiode()).isEqualTo(new Periode(LocalDate.of(2021, 12, 1), LocalDate.of(2021, 12, 13)));
25+
assertThat(ytelse.getBosteder().getPerioder().keySet()).containsExactly(new Periode(LocalDate.of(2018, 12, 30), LocalDate.of(2019, 10, 20)));
26+
27+
//TODO PLS asserte alle felter som er satt (og ikke)
28+
}
29+
}

0 commit comments

Comments
 (0)