From 0481b1fc91e93f6b541e3fbc5db95818a79830a1 Mon Sep 17 00:00:00 2001 From: Morten Osvik <33130876+mortenoosvik@users.noreply.github.com> Date: Mon, 27 Jan 2025 12:53:07 +0100 Subject: [PATCH] =?UTF-8?q?TSFF-1073=20Oppdater=20Kurs=20og=20reise=20for?= =?UTF-8?q?=20oppl=C3=A6ringspenger=20(#483)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Bakgrunn** Utformingen av den digitale søknaden for opplæringspenger fører til at Kursobjektet ser litt anerledes ut. Vi ønsker at objektene i k9-sak skal samsvare. **Endringer** - Trekker alt som har med reise ut fra `KursPerioder` og i det nye `Reise`-objektet. - Fjerner `KursPerioder` som nå kun inneholder perioder - Navn på kursholder må sendes inn fra søknaden så vi fjerner @Deprecated og renamer til `navn` i stedet for `holder` - Tilpasser validering --- ...pl\303\246ringspengerYtelseValidator.java" | 46 +++++++----- .../ytelse/olp/v1/kurs/Kurs.java" | 17 ++++- .../olp/v1/kurs/KursPeriodeMedReisetid.java" | 75 ------------------- .../ytelse/olp/v1/kurs/Kursholder.java" | 15 ++-- .../ytelse/olp/v1/kurs/Reise.java" | 51 +++++++++++++ ...03\246ringspengerYtelseValidatorTest.java" | 6 +- 6 files changed, 100 insertions(+), 110 deletions(-) delete mode 100644 "soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/KursPeriodeMedReisetid.java" create mode 100644 "soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Reise.java" diff --git "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidator.java" "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidator.java" index 56f29d81..dcb24689 100644 --- "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidator.java" +++ "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidator.java" @@ -18,7 +18,7 @@ import no.nav.k9.søknad.felles.type.Periode; import no.nav.k9.søknad.ytelse.Ytelse; import no.nav.k9.søknad.ytelse.YtelseValidator; -import no.nav.k9.søknad.ytelse.olp.v1.kurs.KursPeriodeMedReisetid; +import no.nav.k9.søknad.ytelse.olp.v1.kurs.Reise; class OpplæringspengerYtelseValidator extends YtelseValidator { @@ -86,7 +86,7 @@ List validerOgLeggTilFeilene(Opplæringspenger olp, feilene.addAll(validerAtIngenPerioderOverlapperMedTrekkKravPerioder(trekkKravPerioderTidslinje, søknadsperiodeTidslinje, "trekkKravPerioder")); for (var ytelsePeriode : PerioderMedEndringUtil.getAllePerioderSomMåVæreInnenforSøknadsperiode(olp)) { - if (ytelsePeriode.getPeriodeMap().keySet().stream().anyMatch(Periode::isTilOgMedFørFraOgMed)){ + if (ytelsePeriode.getPeriodeMap().keySet().stream().anyMatch(Periode::isTilOgMedFørFraOgMed)) { continue; //fortsette validering med ugyldige perioder gir bare duplikate feil } var ytelsePeriodeTidsserie = lagTidslinjeOgValider(ytelsePeriode.getPeriodeMap(), ytelsePeriode.getFelt() + ".perioder", feilene); @@ -96,7 +96,8 @@ List validerOgLeggTilFeilene(Opplæringspenger olp, validerAtYtelsePeriodenErKomplettMedSøknad(søknadsperiodeTidslinje, olp.getUttak().getPerioder(), "uttak", feilene); - validerReisetidMotKursperioden(olp.getKurs().getKursperioder(), "kurs.kursperioder", feilene); + validerReise(olp.getKurs().getReise(), "kurs.reise", feilene); + validerReisetidMotKursperioden(olp.getKurs().getKursperioder(), olp.getKurs().getReise(), "kurs.reise", feilene); return feilene; } @@ -129,23 +130,28 @@ private List validerAtYtelsePerioderErInnenforIntervalForEndring(LocalDate .collect(Collectors.toCollection(ArrayList::new))); } - private void validerReisetidMotKursperioden(List kursperioder, String felt, List feil) { - for (KursPeriodeMedReisetid kursPeriode : kursperioder) { - if (kursPeriode != null) { - LocalDate avreise = kursPeriode.getAvreise(); - LocalDate hjemkomst = kursPeriode.getHjemkomst(); - Periode periode = kursPeriode.getPeriode(); - - if (avreise != null && hjemkomst != null && periode != null) { - if (hjemkomst.isBefore(avreise)) { - feil.add(toFeil(periode, felt, "ugyldigKursPeriode", "hjemkomst er før avreise: ")); - } - if (avreise.isAfter(periode.getFraOgMed())) { - feil.add(toFeil(periode, felt, "ugyldigKursPeriode", "avreise er etter kursstart: ")); - } - if (hjemkomst.isBefore(periode.getTilOgMed())) { - feil.add(toFeil(periode, felt, "ugyldigKursPeriode", "hjemkomst er før kursslutt: ")); - } + private void validerReise(Reise reise, String felt, List feilene) { + if (reise.isReiserUtenforKursdager()) { + if (reise.getReisedager() == null || reise.getReisedager().isEmpty()) { + feilene.add(lagFeil(felt, "påkrevd", "Reisedager må inneholde minst en dag når reiserUtenforKursdager er satt.")); + } + if (reise.getReisedagerBeskrivelse() == null) { + feilene.add(lagFeil(felt, "påkrevd", "Beskrivelse må være satt når reiserUtenforKursdager er satt.")); + } + } + } + + private void validerReisetidMotKursperioden(List kursperioder, Reise reise, String felt, List feil) { + var reisedager = reise.getReisedager(); + if (reisedager == null || reisedager.isEmpty()) { + return; + } + + // En reisedag må være innenfor en kursperiode + for (LocalDate reisedag : reisedager) { + if (reisedag != null) { + if (kursperioder.stream().noneMatch(kursPeriode -> kursPeriode.inneholder(new Periode(reisedag, reisedag)))) { + feil.add(lagFeil(felt, "ugyldigReise", "Reisedagen er ikke innenfor en kursperiode: " + reisedag)); } } } diff --git "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kurs.java" "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kurs.java" index 29603465..82cab7d7 100644 --- "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kurs.java" +++ "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kurs.java" @@ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import no.nav.k9.søknad.felles.type.Periode; @JsonIgnoreProperties(ignoreUnknown = true) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE) @@ -24,21 +25,31 @@ public class Kurs { @NotNull @Size(min = 1) @Valid - private List<@NotNull @Valid KursPeriodeMedReisetid> kursperioder; + private List<@NotNull @Valid Periode> kursperioder; + + @JsonProperty(value = "reise", required = true) + @NotNull + @Valid + private Reise reise; public Kurs() { } - public Kurs(Kursholder kursholder, List kursperioder) { + public Kurs(Kursholder kursholder, List kursperioder, Reise reise) { this.kursholder = kursholder; this.kursperioder = kursperioder; + this.reise = reise; } public Kursholder getKursholder() { return kursholder; } - public List getKursperioder() { + public List getKursperioder() { return new ArrayList<>(kursperioder); } + + public Reise getReise() { + return reise; + } } diff --git "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/KursPeriodeMedReisetid.java" "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/KursPeriodeMedReisetid.java" deleted file mode 100644 index 316dcec3..00000000 --- "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/KursPeriodeMedReisetid.java" +++ /dev/null @@ -1,75 +0,0 @@ -package no.nav.k9.søknad.ytelse.olp.v1.kurs; - -import java.time.LocalDate; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Pattern; -import jakarta.validation.constraints.Size; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -import no.nav.k9.søknad.felles.type.Periode; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE) -public class KursPeriodeMedReisetid { - - @JsonProperty(value = "periode", required = true) - @NotNull - @Valid - private Periode periode; - - @JsonProperty(value = "avreise", required = true) - @NotNull - @Valid - private LocalDate avreise; - - @JsonProperty(value = "hjemkomst", required = true) - @NotNull - @Valid - private LocalDate hjemkomst; - - @JsonProperty(value = "begrunnelseReisetidTil") - @Size(max = 4000) - @Pattern(regexp = "^[\\p{Pd}\\p{Graph}\\p{Space}\\p{Sc}\\p{L}\\p{M}\\p{N}§]*$", message = "[${validatedValue}] matcher ikke tillatt pattern [{regexp}]") - private String begrunnelseReisetidTil; - - @JsonProperty(value = "begrunnelseReisetidHjem") - @Size(max = 4000) - @Pattern(regexp = "^[\\p{Pd}\\p{Graph}\\p{Space}\\p{Sc}\\p{L}\\p{M}\\p{N}§]*$", message = "[${validatedValue}] matcher ikke tillatt pattern [{regexp}]") - private String begrunnelseReisetidHjem; - - public KursPeriodeMedReisetid() { - } - - public KursPeriodeMedReisetid(Periode periode, LocalDate avreise, LocalDate hjemkomst, String begrunnelseReisetidTil, String begrunnelseReisetidHjem) { - this.periode = periode; - this.avreise = avreise; - this.hjemkomst = hjemkomst; - this.begrunnelseReisetidTil = begrunnelseReisetidTil; - this.begrunnelseReisetidHjem = begrunnelseReisetidHjem; - } - - public Periode getPeriode() { - return periode; - } - - public LocalDate getAvreise() { - return avreise; - } - - public LocalDate getHjemkomst() { - return hjemkomst; - } - - public String getBegrunnelseReisetidTil() { - return begrunnelseReisetidTil; - } - - public String getBegrunnelseReisetidHjem() { - return begrunnelseReisetidHjem; - } -} diff --git "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kursholder.java" "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kursholder.java" index 35b78433..ff05c4af 100644 --- "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kursholder.java" +++ "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Kursholder.java" @@ -14,12 +14,11 @@ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE) public class Kursholder { - @Deprecated(forRemoval = true) - @JsonProperty(value = "holder") + @JsonProperty(value = "navn") @Valid @Size(max = 100) @Pattern(regexp = "^[\\p{Pd}\\p{Graph}\\p{Space}\\p{Sc}\\p{L}\\p{M}\\p{N}§]*$", message = "[${validatedValue}] matcher ikke tillatt pattern [{regexp}]") - private String holder; + private String navn; @JsonProperty(value = "institusjonsidentifikator", required = true) @Valid @@ -32,15 +31,13 @@ public Kursholder(UUID institusjonUuid) { this.institusjonUuid = institusjonUuid; } - @Deprecated(forRemoval = true) - public Kursholder(String holder, UUID institusjonUuid) { - this.holder = holder; + public Kursholder(String navn, UUID institusjonUuid) { + this.navn = navn; this.institusjonUuid = institusjonUuid; } - @Deprecated(forRemoval = true) - public String getHolder() { - return holder; + public String getNavn() { + return navn; } public UUID getInstitusjonUuid() { diff --git "a/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Reise.java" "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Reise.java" new file mode 100644 index 00000000..9ef44ea7 --- /dev/null +++ "b/soknad/src/main/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/kurs/Reise.java" @@ -0,0 +1,51 @@ +package no.nav.k9.søknad.ytelse.olp.v1.kurs; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +import java.time.LocalDate; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE) +public class Reise { + @JsonProperty(value = "reiserUtenforKursdager", required = true) + @NotNull + @Valid + private boolean reiserUtenforKursdager; + + @JsonProperty(value="reisedager") + @Valid + private List<@NotNull @Valid LocalDate> reisedager; + + @JsonProperty(value = "reisedagerBeskrivelse") + @Size(max = 4000) + @Pattern(regexp = "^[\\p{Pd}\\p{Graph}\\p{Space}\\p{Sc}\\p{L}\\p{M}\\p{N}§]*$", message = "[${validatedValue}] matcher ikke tillatt pattern [{regexp}]") + private String reisedagerBeskrivelse; + + public Reise() { + } + + public Reise(boolean reiserUtenforKursdager, List reisedager, String reisedagerBeskrivelse) { + this.reiserUtenforKursdager = reiserUtenforKursdager; + this.reisedager = reisedager; + this.reisedagerBeskrivelse = reisedagerBeskrivelse; + } + + public boolean isReiserUtenforKursdager() { + return reiserUtenforKursdager; + } + + public List getReisedager() { + return reisedager; + } + + public String getReisedagerBeskrivelse() { + return reisedagerBeskrivelse; + } +} diff --git "a/soknad/src/test/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidatorTest.java" "b/soknad/src/test/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidatorTest.java" index 7afd5f4b..d013045d 100644 --- "a/soknad/src/test/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidatorTest.java" +++ "b/soknad/src/test/java/no/nav/k9/s\303\270knad/ytelse/olp/v1/Oppl\303\246ringspengerYtelseValidatorTest.java" @@ -11,8 +11,8 @@ import no.nav.k9.søknad.felles.Feil; import no.nav.k9.søknad.felles.type.Periode; import no.nav.k9.søknad.ytelse.olp.v1.kurs.Kurs; -import no.nav.k9.søknad.ytelse.olp.v1.kurs.KursPeriodeMedReisetid; import no.nav.k9.søknad.ytelse.olp.v1.kurs.Kursholder; +import no.nav.k9.søknad.ytelse.olp.v1.kurs.Reise; import no.nav.k9.søknad.ytelse.psb.YtelseEksempel; class OpplæringspengerYtelseValidatorTest { @@ -21,8 +21,8 @@ class OpplæringspengerYtelseValidatorTest { private Opplæringspenger lagYtelse() { Periode søknadsperiode = new Periode(LocalDate.now(), LocalDate.now().plusWeeks(1)); - KursPeriodeMedReisetid kursPeriode = new KursPeriodeMedReisetid(søknadsperiode, søknadsperiode.getFraOgMed(), søknadsperiode.getTilOgMed(), null, null); - Kurs kurs = new Kurs(new Kursholder(UUID.randomUUID()), List.of(kursPeriode)); + Reise reise = new Reise(true, List.of(LocalDate.now()), "Langt å kjøre"); + Kurs kurs = new Kurs(new Kursholder(UUID.randomUUID()), List.of(søknadsperiode), reise); return new Opplæringspenger().medBarn(YtelseEksempel.lagBarn()).medSøknadsperiode(List.of(søknadsperiode)).medUttak(YtelseEksempel.lagUttak(søknadsperiode)).medKurs(kurs); }