Skip to content

Commit efccf04

Browse files
authored
Legger inn endringssøknad for PPN (#260)
* Legger inn endringssøknad for PPN * Fjerner duplikat kode * Gjør avhengighet til felles Pleiepenger-kode eksplisitt * Endringer etter kodereview
1 parent eb8eae2 commit efccf04

13 files changed

+449
-148
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
8+
import no.nav.k9.søknad.TidsserieUtils;
9+
import no.nav.k9.søknad.felles.type.Periode;
10+
import no.nav.k9.søknad.ytelse.psb.v1.PerioderMedEndring;
11+
import no.nav.k9.søknad.ytelse.psb.v1.PerioderMedEndringUtil;
12+
13+
public class PleiepengerLivetsSluttfasePerioderMedEndringUtil {
14+
15+
public static List<Periode> getEndringsperiode(PleipengerLivetsSluttfase ppn) {
16+
var allePerioderMedEndringTidsserie =
17+
PerioderMedEndringUtil.tilTidsserie(getAllePerioderSomMåVæreInnenforSøknadsperiode(ppn));
18+
var søknadsperiode = toLocalDateTimeline(ppn.getSøknadsperiodeList());
19+
var endringsperiodeTidsserie = allePerioderMedEndringTidsserie.disjoint(søknadsperiode);
20+
return TidsserieUtils.tilPeriodeList(endringsperiodeTidsserie);
21+
}
22+
23+
public static List<PerioderMedEndring> getAllePerioderSomMåVæreInnenforSøknadsperiode(PleipengerLivetsSluttfase ppn) {
24+
var listen = new ArrayList<PerioderMedEndring>();
25+
listen.add(new PerioderMedEndring().medPerioder("uttak", ppn.getUttak().getPerioder()));
26+
listen.addAll(PerioderMedEndringUtil.getArbeidstidPerioder(ppn.getArbeidstid()));
27+
return listen;
28+
}
29+
30+
}

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import no.nav.k9.søknad.felles.Feil;
1212
import no.nav.k9.søknad.felles.Versjon;
1313
import no.nav.k9.søknad.felles.personopplysninger.Søker;
14+
import no.nav.k9.søknad.felles.type.Periode;
1415
import no.nav.k9.søknad.felles.type.Person;
1516

1617
public class PleiepengerLivetsSluttfaseSøknadValidator extends SøknadValidator<Søknad> {
@@ -19,20 +20,34 @@ public class PleiepengerLivetsSluttfaseSøknadValidator extends SøknadValidator
1920

2021
@Override
2122
public List<Feil> valider(Søknad søknad) {
23+
return valider(søknad, List.of());
24+
}
25+
26+
public List<Feil> valider(Søknad søknad, List<Periode> gyldigeEndringsperioder) {
2227
var validate = VALIDATOR_FACTORY.getValidator().validate(søknad);
2328

2429
List<Feil> feil = validate.stream()
2530
.map(Feil::toFeil)
2631
.collect(Collectors.toList());
2732

33+
validerInneholderBegrunnelseDersomTrekkAvPerioder(søknad, feil);
2834
validerVersjon(søknad.getVersjon(), feil);
2935
validerPleietrengendeIkkeErSøker(søknad.getSøker(), søknad.getBerørtePersoner(), feil);
3036
validerPleietrengendeIkkeErSøker(søknad.getSøker(), List.of(((PleipengerLivetsSluttfase) søknad.getYtelse()).getPleietrengende()), feil);
31-
feil.addAll(new PleiepengerLivetsSluttfaseYtelseValidator().valider(søknad.getYtelse()));
37+
feil.addAll(new PleiepengerLivetsSluttfaseYtelseValidator().valider(søknad.getYtelse(), gyldigeEndringsperioder));
3238

3339
return feil;
3440
}
3541

42+
private static void validerInneholderBegrunnelseDersomTrekkAvPerioder(Søknad søknad, List<Feil> feil) {
43+
PleipengerLivetsSluttfase ytelse = søknad.getYtelse();
44+
if (ytelse.getTrekkKravPerioder() != null && !ytelse.getTrekkKravPerioder().isEmpty()) {
45+
if (søknad.getBegrunnelseForInnsending().getTekst() == null || søknad.getBegrunnelseForInnsending().getTekst().isEmpty()) {
46+
feil.add(new Feil("begrunnelseForInnsending", "påkrevd", "Søknad inneholder trekk krav perioder uten begrunnelse for innsending."));
47+
}
48+
}
49+
}
50+
3651
private static void validerVersjon(Versjon versjon, List<Feil> feil) {
3752
if (versjon != null && !versjon.erGyldig()) {
3853
feil.add(new Feil("versjon", "ugyldigVersjon", "Versjonen er på ugyldig format."));

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

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,37 @@
88
import java.util.ArrayList;
99
import java.util.List;
1010
import java.util.Map;
11+
import java.util.Objects;
1112
import java.util.stream.Collectors;
1213

13-
import no.nav.fpsak.tidsserie.LocalDateSegment;
1414
import no.nav.fpsak.tidsserie.LocalDateTimeline;
15+
import no.nav.fpsak.tidsserie.StandardCombinators;
16+
import no.nav.k9.søknad.ValideringsFeil;
1517
import no.nav.k9.søknad.felles.Feil;
1618
import no.nav.k9.søknad.felles.opptjening.AnnenAktivitet;
1719
import no.nav.k9.søknad.felles.opptjening.Frilanser;
1820
import no.nav.k9.søknad.felles.opptjening.SelvstendigNæringsdrivende;
1921
import no.nav.k9.søknad.felles.type.Periode;
2022
import no.nav.k9.søknad.ytelse.Ytelse;
2123
import no.nav.k9.søknad.ytelse.YtelseValidator;
24+
import no.nav.k9.søknad.ytelse.psb.v1.PerioderMedEndring;
2225
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstaker;
23-
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstid;
2426

2527
public class PleiepengerLivetsSluttfaseYtelseValidator extends YtelseValidator {
2628
@Override
2729
public List<Feil> valider(Ytelse søknad) {
28-
return valider((PleipengerLivetsSluttfase) søknad);
30+
return valider((PleipengerLivetsSluttfase) søknad, List.of());
2931
}
3032

31-
public List<Feil> valider(PleipengerLivetsSluttfase søknad) {
33+
public List<Feil> valider(PleipengerLivetsSluttfase søknad, List<Periode> gyldigeEndringsperioder) {
34+
return validerMedGyldigEndringsperodeHvisDenFinnes(søknad, gyldigeEndringsperioder);
35+
}
36+
37+
List<Feil> validerMedGyldigEndringsperodeHvisDenFinnes(PleipengerLivetsSluttfase søknad, List<Periode> gyldigeEndringsperioder) {
3238
List<Feil> feilene = new ArrayList<>();
3339
try {
34-
if (søknad.getSøknadsperiode() == null) {
35-
feilene.add(lagFeil("søknadsperiode", "påkrevd", "det finnes ingen søknadsperiode"));
36-
}
40+
validerLovligEndring(søknad, gyldigeEndringsperioder);
41+
3742
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getBosteder().getPerioder(), "bosteder.perioder"));
3843
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getBosteder().getPerioderSomSkalSlettes(), "bosteder.perioderSomSkalSlettes"));
3944
feilene.addAll(validerPerioderErLukketOgGyldig(søknad.getUtenlandsopphold().getPerioder(), "utenlandsopphold.perioder"));
@@ -45,13 +50,41 @@ public List<Feil> valider(PleipengerLivetsSluttfase søknad) {
4550
var uttakTidslinje = lagTidslinjeOgValider(new ArrayList<>(søknad.getUttak().getPerioder().keySet()), "uttak.perioder", feilene);
4651
validerAtUttakErKomplettForSøknadsperiode(søknadsperiodeTidslinje, uttakTidslinje, "uttak.perioder", feilene);
4752

48-
validerTrekkKravPerioder(søknad.getTrekkKravPerioder(), søknadsperiodeTidslinje, feilene);
53+
var trekkKravPerioderTidslinje = lagTidslinjeOgValider(søknad.getTrekkKravPerioder(), "trekkKravPerioder.perioder", feilene);
54+
validerTrekkKravPerioder(trekkKravPerioderTidslinje, søknadsperiodeTidslinje, feilene);
55+
56+
var gyldigEndringsperiodeTidslinje = lagTidslinjeOgValider(gyldigeEndringsperioder, "gyldigeEndringsperioder.perioder", feilene);
57+
var intervalForEndringTidslinje = søknadsperiodeTidslinje.union(gyldigEndringsperiodeTidslinje, StandardCombinators::coalesceLeftHandSide);
58+
for (PerioderMedEndring ytelsePeriode : PleiepengerLivetsSluttfasePerioderMedEndringUtil.getAllePerioderSomMåVæreInnenforSøknadsperiode(søknad)) {
59+
var ytelsePeriodeTidslinje = lagTidslinjeOgValider(ytelsePeriode.getPeriodeMap(), ytelsePeriode.getFelt() + ".perioder", feilene);
60+
feilene.addAll(validerAtYtelsePerioderErInnenforIntervalForEndring(intervalForEndringTidslinje, ytelsePeriodeTidslinje, ytelsePeriode.getFelt() + ".perioder"));
61+
feilene.addAll(validerAtIngenPerioderOverlapperMedTrekkKravPerioder(trekkKravPerioderTidslinje, ytelsePeriodeTidslinje, ytelsePeriode.getFelt() + ".perioder"));
62+
}
63+
4964
} catch (ValideringsAvbrytendeFeilException valideringsAvbrytendeFeilException) {
5065
feilene.addAll(valideringsAvbrytendeFeilException.getFeilList());
5166
}
5267
return feilene;
5368
}
5469

70+
// Brukes av Punsj for å sende inn endringer på allerede mottatte søknadsperioder. Komplett datasett kreves ikke for disse perioden
71+
@Override
72+
public void forsikreValidert(Ytelse ytelse, List<Periode> gyldigeEndringsperioder) {
73+
Objects.requireNonNull(gyldigeEndringsperioder, "gyldigeEndringsperioder");
74+
75+
var feilene = valider((PleipengerLivetsSluttfase) ytelse, gyldigeEndringsperioder);
76+
if (!feilene.isEmpty()) {
77+
throw new ValideringsFeil(feilene);
78+
}
79+
}
80+
81+
private void validerLovligEndring(PleipengerLivetsSluttfase ytelse, List<Periode> gyldigeEndringsperioder) {
82+
if (ytelse.getSøknadsperiodeList().isEmpty() && gyldigeEndringsperioder.isEmpty()) {
83+
throw new ValideringsAvbrytendeFeilException(List.of(
84+
lagFeil("søknadsperiode", "missingArgument", "Mangler søknadsperiode eller gyldigeEndringsperioder.")));
85+
}
86+
}
87+
5588
private void validerArbeidstid(PleipengerLivetsSluttfase søknad) throws ValideringsAvbrytendeFeilException {
5689
List<Arbeidstaker> arbeidstakerList = søknad.getArbeidstid().getArbeidstakerList();
5790
for (int i = 0; i < arbeidstakerList.size(); i++) {
@@ -75,16 +108,6 @@ private void validerOpptjening(PleipengerLivetsSluttfase søknad, List<Feil> fei
75108
if (fl != null) {
76109
validerPerioderIkkeErInvertert(new Periode(fl.getStartdato(), fl.getSluttdato()), "opptjeningAktivitet.frilanser.startdato/sluttdato", feilene);
77110
}
78-
79-
}
80-
81-
private LocalDateTimeline<Boolean> lagArbeidstidTidslinje(Arbeidstid arbeidstid) {
82-
var arbeidstidTidslinje = arbeidstid.getArbeidstakerList().stream()
83-
.flatMap(it -> it.getArbeidstidInfo().getPerioder().keySet().stream())
84-
.map(it -> new LocalDateSegment<>(it.getFraOgMed(), it.getTilOgMed(), Boolean.TRUE))
85-
.collect(Collectors.toList());
86-
var arbeidstidTidslinjeSammenslått = LocalDateTimeline.buildGroupOverlappingSegments(arbeidstidTidslinje).mapValue(s -> Boolean.TRUE);
87-
return arbeidstidTidslinjeSammenslått;
88111
}
89112

90113

@@ -94,8 +117,7 @@ private LocalDateTimeline<Boolean> lagArbeidstidTidslinje(Arbeidstid arbeidstid)
94117
List<Feil> feil) {
95118

96119
var søknadsperioderUtenUttak = tilPeriodeList(søknadsperioderTidslinje.disjoint(uttakTidslinje));
97-
feil.addAll( søknadsperioderUtenUttak.stream()
98-
// TODO: Avklare om det er spesiell logikk rundt helg
120+
feil.addAll(søknadsperioderUtenUttak.stream()
99121
.filter(this::periodeInneholderDagerSomIkkeErHelg)
100122
.map(p -> toFeil(p, felt, "ikkeKomplettPeriode", "Periodene er ikke komplett, periode som mangler er: "))
101123
.collect(Collectors.toCollection(ArrayList::new)));
@@ -112,15 +134,39 @@ private boolean periodeInneholderDagerSomIkkeErHelg(Periode periode) {
112134
return false;
113135
}
114136

115-
private void validerTrekkKravPerioder(List<Periode> trekkKravPerioder, LocalDateTimeline<Boolean> søknadsperiodeTidslinje, List<Feil> feilene) {
116-
LocalDateTimeline<Boolean> trekkKravPerioderTidslinje = lagTidslinjeOgValider(trekkKravPerioder, "trekkKravPerioder.perioder", feilene);
137+
private List<Feil> validerAtYtelsePerioderErInnenforIntervalForEndring(LocalDateTimeline<Boolean> intervalForEndringTidslinje,
138+
LocalDateTimeline<Boolean> ytelsePeriodeLinje,
139+
String felt) {
140+
return tilPeriodeList(
141+
ytelsePeriodeLinje.disjoint(intervalForEndringTidslinje)).stream()
142+
.filter(this::periodeInneholderDagerSomIkkeErHelg)
143+
.map(p -> toFeil(p, felt, "ugyldigPeriode",
144+
"Perioden er utenfor gyldig interval. Gyldig interval: (" + intervalForEndringTidslinje.getLocalDateIntervals() + "), Ugyldig periode: "))
145+
.collect(Collectors.toCollection(ArrayList::new));
146+
}
147+
148+
private void validerTrekkKravPerioder(LocalDateTimeline<Boolean> trekkKravPerioderTidslinje, LocalDateTimeline<Boolean> søknadsperiodeTidslinje, List<Feil> feilene) {
117149
feilene.addAll(validerAtIngenPerioderOverlapperMedTrekkKravPerioder(trekkKravPerioderTidslinje, søknadsperiodeTidslinje, "trekkKravPerioder"));
118150
}
119151

120152
private LocalDateTimeline<Boolean> lagTidslinjeMedStøtteForÅpenPeriodeOgValider(Map<Periode, ?> periodeMap, String felt) throws ValideringsAvbrytendeFeilException {
121153
return lagTidslinjeOgValider(periodeMap, felt, true);
122154
}
123155

156+
private LocalDateTimeline<Boolean> lagTidslinjeOgValider(Map<Periode, ? > periodeMap, String felt, List<Feil> feil) throws ValideringsAvbrytendeFeilException{
157+
var nyFeil = validerPerioderErLukketOgGyldig(periodeMap, felt);
158+
if (!nyFeil.isEmpty()) {
159+
feil.addAll(nyFeil);
160+
throw new ValideringsAvbrytendeFeilException(feil);
161+
}
162+
try {
163+
return toLocalDateTimeline(new ArrayList<>(periodeMap.keySet()));
164+
} catch (IllegalArgumentException e) {
165+
feil.add(lagFeil(felt, "IllegalArgumentException", e.getMessage()));
166+
throw new ValideringsAvbrytendeFeilException(feil);
167+
}
168+
}
169+
124170
private LocalDateTimeline<Boolean> lagTidslinjeOgValider(Map<Periode, ?> periodeMap, String felt) throws ValideringsAvbrytendeFeilException {
125171
return lagTidslinjeOgValider(periodeMap, felt, false);
126172
}

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

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
import java.time.LocalDate;
44
import java.util.ArrayList;
55
import java.util.Collections;
6-
import java.util.Comparator;
76
import java.util.List;
87
import java.util.Objects;
9-
import java.util.Optional;
10-
import java.util.stream.Collectors;
118

129
import javax.validation.Valid;
1310
import javax.validation.constraints.NotNull;
@@ -26,9 +23,7 @@
2623
import no.nav.k9.søknad.ytelse.Ytelse;
2724
import no.nav.k9.søknad.ytelse.YtelseValidator;
2825
import no.nav.k9.søknad.ytelse.psb.v1.Uttak;
29-
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstaker;
3026
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.Arbeidstid;
31-
import no.nav.k9.søknad.ytelse.psb.v1.arbeidstid.ArbeidstidInfo;
3227

3328
@JsonIgnoreProperties(ignoreUnknown = true)
3429
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
@@ -41,9 +36,9 @@ public class PleipengerLivetsSluttfase implements Ytelse {
4136
private Pleietrengende pleietrengende;
4237

4338
@Valid
39+
@NotNull
4440
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
45-
@JsonProperty(value = "søknadsperiode" /* ,required = true TODO skal skrus på før lansering */)
46-
//@NotNull --TODO skal bli NotNull før lansering
41+
@JsonProperty(value = "søknadsperiode", required = true)
4742
private List<Periode> søknadsperiode = new ArrayList<>();
4843

4944
@Valid
@@ -98,39 +93,28 @@ public Person getAnnenPart() {
9893

9994
@Override
10095
public Periode getSøknadsperiode() {
101-
if (!søknadsperiode.isEmpty()) {
102-
return new Periode(
103-
søknadsperiode.stream().map(Periode::getFraOgMed).min(Comparator.naturalOrder()).orElseThrow(),
104-
søknadsperiode.stream().map(Periode::getTilOgMed).max(Comparator.naturalOrder()).orElseThrow()
105-
);
106-
}
107-
108-
//TODO deprecated, erstattes av søknadsperiode (se over), fjernes før lansering
109-
List<ArbeidstidInfo> fraværsperioder = new ArrayList<>();
110-
arbeidstid.getFrilanserArbeidstidInfo().ifPresent(fraværsperioder::add);
111-
arbeidstid.getSelvstendigNæringsdrivendeArbeidstidInfo().ifPresent(fraværsperioder::add);
112-
arbeidstid.getArbeidstakerList().stream()
113-
.map(Arbeidstaker::getArbeidstidInfo)
114-
.forEach(fraværsperioder::add);
115-
List<Periode> allePerioder = fraværsperioder.stream()
116-
.flatMap(ai -> ai.getPerioder().keySet().stream())
117-
.collect(Collectors.toList());
118-
Optional<LocalDate> fom = allePerioder.stream()
96+
final List<Periode> perioder = new ArrayList<>(søknadsperiode);
97+
perioder.addAll(getEndringsperiode());
98+
99+
var fom = perioder
100+
.stream()
119101
.map(Periode::getFraOgMed)
120-
.filter(Objects::nonNull)
121-
.min(Comparator.naturalOrder());
122-
Optional<LocalDate> tom = allePerioder.stream()
102+
.min(LocalDate::compareTo)
103+
.orElseThrow();
104+
var tom = perioder
105+
.stream()
123106
.map(Periode::getTilOgMed)
124-
.filter(Objects::nonNull)
125-
.max(Comparator.naturalOrder());
126-
if (fom.isPresent() && tom.isPresent()) {
127-
return new Periode(fom.get(), tom.get());
128-
}
129-
return null;
107+
.max(LocalDate::compareTo)
108+
.orElseThrow();
109+
return new Periode(fom, tom);
130110
}
131111

132112
public List<Periode> getSøknadsperiodeList() {
133-
return søknadsperiode == null ? null : Collections.unmodifiableList(søknadsperiode);
113+
return Collections.unmodifiableList(søknadsperiode);
114+
}
115+
116+
public List<Periode> getEndringsperiode() {
117+
return PleiepengerLivetsSluttfasePerioderMedEndringUtil.getEndringsperiode(this);
134118
}
135119

136120
public OpptjeningAktivitet getOpptjeningAktivitet() {
@@ -201,5 +185,4 @@ public PleipengerLivetsSluttfase medUttak(Uttak uttak) {
201185
this.uttak = Objects.requireNonNull(uttak, "uttak");
202186
return this;
203187
}
204-
205188
}
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.psb.v1;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
import no.nav.k9.søknad.felles.type.Periode;
8+
9+
public class PerioderMedEndring {
10+
private String felt;
11+
private Map<Periode, ?> periodeMap;
12+
13+
public PerioderMedEndring() {
14+
15+
}
16+
17+
public String getFelt() {
18+
return felt;
19+
}
20+
21+
public Map<Periode, ?> getPeriodeMap() {
22+
return periodeMap;
23+
}
24+
25+
public List<Periode> getPeriodeList() {
26+
return new ArrayList<>(periodeMap.keySet());
27+
}
28+
29+
public PerioderMedEndring medPerioder(String felt, Map<Periode, ?> periodeMap) {
30+
this.felt = felt;
31+
this.periodeMap = periodeMap;
32+
return this;
33+
}
34+
}

0 commit comments

Comments
 (0)