Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slår sammen over helg dersom tilkommet inntekt er lik på begge sider #573

Merged
merged 2 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import no.nav.folketrygdloven.kalkulator.modell.typer.InternArbeidsforholdRefDto;
import no.nav.folketrygdloven.kalkulator.modell.typer.StatusOgArbeidsgiver;
import no.nav.folketrygdloven.kalkulator.tid.Intervall;
import no.nav.folketrygdloven.kalkulator.tid.TimelineWeekendCompressor;
import no.nav.folketrygdloven.kalkulus.kodeverk.AktivitetStatus;
import no.nav.folketrygdloven.kalkulus.kodeverk.AndelKilde;
import no.nav.folketrygdloven.kalkulus.kodeverk.UttakArbeidType;
Expand Down Expand Up @@ -90,7 +91,15 @@ public static LocalDateTimeline<Set<StatusOgArbeidsgiver>> finnTilkommetInntekts
var utbetalingTidslinje = finnTidslinjeForUtbetalingsperiode((UtbetalingsgradGrunnlag) utbetalingsgradGrunnlag);
aktivitetTidslinje = aktivitetTidslinje.intersection(utbetalingTidslinje, StandardCombinators::leftOnly);
}
return aktivitetTidslinje.map(s -> mapTilkommetTidslinje(andelerFraStart, yrkesaktiviteter, utbetalingsgradGrunnlag, s, ikkeFiltrerVedFulltFravær)).compress();
var tilkommetTidslinje = aktivitetTidslinje.map(s -> mapTilkommetTidslinje(andelerFraStart, yrkesaktiviteter, utbetalingsgradGrunnlag, s, ikkeFiltrerVedFulltFravær)).compress();
return slåSammenOverHelgDersomLike(tilkommetTidslinje);
}

private static <T> LocalDateTimeline<T> slåSammenOverHelgDersomLike(LocalDateTimeline<T> tidslinje) {
var factory = new TimelineWeekendCompressor.CompressorFactory<T>(Objects::equals, (i, lhs, rhs) -> new LocalDateSegment<>(i, lhs.getValue()));
TimelineWeekendCompressor<T> compressor = tidslinje.toSegments().stream()
.collect(factory::get, TimelineWeekendCompressor::accept, TimelineWeekendCompressor::combine);
return new LocalDateTimeline<>(compressor.getSegmenter());
}

private static LocalDateTimeline<Set<Inntektsforhold>> finnDagpengetidslinje(InntektArbeidYtelseGrunnlagDto iayGrunnlag, LocalDate skjæringstidspunkt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import no.nav.folketrygdloven.kalkulator.modell.iay.AktivitetsAvtaleDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.AktivitetsAvtaleDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseAggregatBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseGrunnlagDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseGrunnlagDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektspostDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.VersjonTypeDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.YrkesaktivitetDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.YrkesaktivitetDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.YtelseAnvistDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.YtelseAnvistDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.YtelseDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.permisjon.PermisjonDtoBuilder;
Expand Down Expand Up @@ -594,6 +594,15 @@ private Set<StatusOgArbeidsgiver> finnTilkomneAndeler(Intervall periode,
PleiepengerSyktBarnGrunnlag utbetalingsgradGrunnlag,
LocalDate skjæringstidspunkt) {

var iay = lagIAY(yrkesaktiviteter, dagpengePerioder, inntekter);
var tidslinje = TilkommetInntektsforholdTjeneste.finnTilkommetInntektsforholdTidslinje(skjæringstidspunkt,
andelerFraStart, utbetalingsgradGrunnlag, iay);
var segmenter = tidslinje.intersection(new LocalDateInterval(periode.getFomDato(), periode.getTomDato())).compress().toSegments();
return segmenter.isEmpty() ? new LinkedHashSet<>() : segmenter.stream().map(LocalDateSegment::getValue)
.filter(s -> !s.isEmpty()).findFirst().orElse(Set.of());
}

private static InntektArbeidYtelseGrunnlagDto lagIAY(List<YrkesaktivitetDto> yrkesaktiviteter, List<Intervall> dagpengePerioder, List<InntektDtoBuilder> inntekter) {
var oppdatere = InntektArbeidYtelseAggregatBuilder.oppdatere(Optional.empty(), VersjonTypeDto.REGISTER);
var aktørArbeid = InntektArbeidYtelseAggregatBuilder.AktørArbeidBuilder.oppdatere(Optional.empty());
yrkesaktiviteter.forEach(aktørArbeid::leggTilYrkesaktivitet);
Expand All @@ -619,11 +628,8 @@ private Set<StatusOgArbeidsgiver> finnTilkomneAndeler(Intervall periode,
oppdatere.leggTilAktørYtelse(aktørYtelse);

}
var tidslinje = TilkommetInntektsforholdTjeneste.finnTilkommetInntektsforholdTidslinje(skjæringstidspunkt,
andelerFraStart, utbetalingsgradGrunnlag, InntektArbeidYtelseGrunnlagDtoBuilder.nytt().medData(oppdatere).build());
var segmenter = tidslinje.intersection(new LocalDateInterval(periode.getFomDato(), periode.getTomDato())).compress().toSegments();
return segmenter.isEmpty() ? new LinkedHashSet<>() : segmenter.stream().map(LocalDateSegment::getValue)
.filter(s -> !s.isEmpty()).findFirst().orElse(Set.of());
var iay = InntektArbeidYtelseGrunnlagDtoBuilder.nytt().medData(oppdatere).build();
return iay;
}

private List<InntektDtoBuilder> lagInntektForYrkesaktiviteter(List<YrkesaktivitetDto> yrkesaktiviteter, PleiepengerSyktBarnGrunnlag utbetalingsgradGrunnlag) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package no.nav.folketrygdloven.kalkulator.steg.tilkommetInntekt;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;

import no.nav.folketrygdloven.kalkulator.input.PleiepengerSyktBarnGrunnlag;
import no.nav.folketrygdloven.kalkulator.modell.beregningsgrunnlag.BGAndelArbeidsforholdDto;
import no.nav.folketrygdloven.kalkulator.modell.beregningsgrunnlag.BeregningsgrunnlagPrStatusOgAndelDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.AktivitetsAvtaleDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseAggregatBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseGrunnlagDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.InntektArbeidYtelseGrunnlagDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.iay.VersjonTypeDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.YrkesaktivitetDto;
import no.nav.folketrygdloven.kalkulator.modell.iay.YrkesaktivitetDtoBuilder;
import no.nav.folketrygdloven.kalkulator.modell.svp.AktivitetDto;
import no.nav.folketrygdloven.kalkulator.modell.svp.PeriodeMedUtbetalingsgradDto;
import no.nav.folketrygdloven.kalkulator.modell.svp.UtbetalingsgradPrAktivitetDto;
import no.nav.folketrygdloven.kalkulator.modell.typer.Aktivitetsgrad;
import no.nav.folketrygdloven.kalkulator.modell.typer.Arbeidsgiver;
import no.nav.folketrygdloven.kalkulator.modell.typer.InternArbeidsforholdRefDto;
import no.nav.folketrygdloven.kalkulator.tid.Intervall;
import no.nav.folketrygdloven.kalkulus.kodeverk.AktivitetStatus;
import no.nav.folketrygdloven.kalkulus.kodeverk.AndelKilde;
import no.nav.folketrygdloven.kalkulus.kodeverk.ArbeidType;
import no.nav.folketrygdloven.kalkulus.kodeverk.UttakArbeidType;
import no.nav.fpsak.tidsserie.LocalDateInterval;
import no.nav.fpsak.tidsserie.LocalDateSegment;
import no.nav.fpsak.tidsserie.LocalDateTimeline;
import no.nav.fpsak.tidsserie.StandardCombinators;

class TilkommetInntektsforholdTjenesteTest {


public static final String ARBEIDSGIVER_ORGNR = "123456789";
public static final String ARBEIDSGIVER_ORGNR2 = "123456719";

public static final LocalDate STP = LocalDate.of(2024, 11, 20);

@Test
void skal_slå_sammen_perioder_med_tilkommet_over_helg_og_returnere_første_dag_med_tilkommet_som_virkedag() {

var arbeidsgiver = Arbeidsgiver.virksomhet(ARBEIDSGIVER_ORGNR);
var arbeidstakerandelFraStart = lagArbeidstakerandel(arbeidsgiver, 1L, AndelKilde.PROSESS_START, InternArbeidsforholdRefDto.nullRef());
var utbetalingsgradFraStart = new UtbetalingsgradPrAktivitetDto(lagAktivitet(arbeidsgiver, InternArbeidsforholdRefDto.nullRef()),
lagUtbetalingsgrader(100, STP, STP.plusDays(20)));

var arbeidsgiver2 = Arbeidsgiver.virksomhet(ARBEIDSGIVER_ORGNR2);
var tilkommetDato = STP.plusDays(10);
var utbetalingsgradNyAndel = new UtbetalingsgradPrAktivitetDto(
lagAktivitet(arbeidsgiver2, InternArbeidsforholdRefDto.nullRef()),
lagUtbetalingsgrader(50, tilkommetDato, STP.plusDays(20)));

var yrkesaktivitet = lagYrkesaktivitet(arbeidsgiver, STP.minusMonths(10), STP.plusDays(9), InternArbeidsforholdRefDto.nullRef());
var nyYrkesaktivitet = lagYrkesaktivitet(arbeidsgiver2, tilkommetDato, STP.plusDays(20), InternArbeidsforholdRefDto.nullRef());


var utbetalingsgradGrunnlag = new PleiepengerSyktBarnGrunnlag(List.of(
utbetalingsgradFraStart,
utbetalingsgradNyAndel));

var iay = lagIAY(List.of(yrkesaktivitet, nyYrkesaktivitet));
var tidslinje = TilkommetInntektsforholdTjeneste.finnTilkommetInntektsforholdTidslinje(
STP,
List.of(arbeidstakerandelFraStart),
utbetalingsgradGrunnlag, iay);

var segmenter = tidslinje.toSegments();

assertThat(segmenter.size()).isEqualTo(2);
var iterator = segmenter.iterator();
var førsteSegment = iterator.next();
assertThat(førsteSegment.getValue().isEmpty()).isTrue();
assertThat(førsteSegment.getFom()).isEqualTo(STP);
assertThat(førsteSegment.getTom()).isEqualTo(tilkommetDato.minusDays(1));

var andreSegment = iterator.next();
var førsteVirkedagMedTilkommet = tilkommetDato.plusDays(2);
assertThat(andreSegment.getValue().size()).isEqualTo(1);
assertThat(andreSegment.getFom()).isEqualTo(førsteVirkedagMedTilkommet);
assertThat(andreSegment.getTom()).isEqualTo(STP.plusDays(20));

}

private static InntektArbeidYtelseGrunnlagDto lagIAY(List<YrkesaktivitetDto> yrkesaktiviteter) {
var oppdatere = InntektArbeidYtelseAggregatBuilder.oppdatere(Optional.empty(), VersjonTypeDto.REGISTER);
var aktørArbeid = InntektArbeidYtelseAggregatBuilder.AktørArbeidBuilder.oppdatere(Optional.empty());
yrkesaktiviteter.forEach(aktørArbeid::leggTilYrkesaktivitet);
oppdatere.leggTilAktørArbeid(aktørArbeid);
var iay = InntektArbeidYtelseGrunnlagDtoBuilder.nytt().medData(oppdatere).build();
return iay;
}

private BeregningsgrunnlagPrStatusOgAndelDto lagArbeidstakerandel(Arbeidsgiver arbeidsgiver2, long andelsnr, AndelKilde kilde, InternArbeidsforholdRefDto arbeidsforholdRef) {
return BeregningsgrunnlagPrStatusOgAndelDto.ny()
.medAndelsnr(andelsnr)
.medBGAndelArbeidsforhold(BGAndelArbeidsforholdDto.builder().medArbeidsgiver(arbeidsgiver2).medArbeidsforholdRef(arbeidsforholdRef))
.medKilde(kilde)
.medAktivitetStatus(AktivitetStatus.ARBEIDSTAKER)
.build();
}

private YrkesaktivitetDto lagYrkesaktivitet(Arbeidsgiver arbeidsgiver2, LocalDate fom, LocalDate tom, InternArbeidsforholdRefDto arbeidsforholdId) {
return YrkesaktivitetDtoBuilder.oppdatere(Optional.empty())
.medArbeidsgiver(arbeidsgiver2)
.medArbeidsforholdId(arbeidsforholdId)
.medArbeidType(ArbeidType.ORDINÆRT_ARBEIDSFORHOLD)
.leggTilAktivitetsAvtale(AktivitetsAvtaleDtoBuilder.ny()
.medPeriode(Intervall.fraOgMedTilOgMed(fom, tom))
.medErAnsettelsesPeriode(true))
.build();
}

private List<PeriodeMedUtbetalingsgradDto> lagUtbetalingsgrader(int i, LocalDate fom, LocalDate tom) {
var tidslinje = new LocalDateTimeline<>(fom, tom, true);
var utenhelg = fjernHelg(tidslinje);
var helger = new LocalDateTimeline<>(fom, tom, true).disjoint(utenhelg);

var utbetalingsgraderForHelger = lagUtbetalingsgraderFraTidslinje(0, utenhelg);
var utbetalingsgraderForUkedager = lagUtbetalingsgraderFraTidslinje(i, utenhelg);
utbetalingsgraderForUkedager.addAll(utbetalingsgraderForHelger);
return utbetalingsgraderForUkedager;
}

private List<PeriodeMedUtbetalingsgradDto> lagUtbetalingsgraderFraTidslinje(int i, LocalDateTimeline<Boolean> utenhelg) {
return utenhelg.getLocalDateIntervals().stream()
.map(p -> lagPeriodeMedUtbetalingsgrad(i, p.getFomDato(), p.getTomDato()))
.collect(Collectors.toCollection(ArrayList::new));
}


public static <T> LocalDateTimeline<T> fjernHelg(LocalDateTimeline<T> input) {
List<LocalDateSegment<Void>> helger = new ArrayList<>();
for (LocalDateInterval intervall : input.getLocalDateIntervals()) {
LocalDate d = intervall.getFomDato();
while (!d.isAfter(intervall.getTomDato())) {
if (d.getDayOfWeek() == DayOfWeek.SUNDAY) {
helger.add(new LocalDateSegment<>(d, d, null));
d = d.plusDays(6);
} else if (d.getDayOfWeek() == DayOfWeek.SATURDAY) {
helger.add(new LocalDateSegment<>(d, d.plusDays(1), null));
d = d.plusWeeks(1);
} else {
d = d.plusDays(DayOfWeek.SATURDAY.getValue() - d.getDayOfWeek().getValue());
}
}
}
LocalDateTimeline<Void> helgetidslinje = new LocalDateTimeline<>(helger, StandardCombinators::coalesceLeftHandSide);
return input.disjoint(helgetidslinje);
}

private PeriodeMedUtbetalingsgradDto lagPeriodeMedUtbetalingsgrad(int i, LocalDate fom, LocalDate tom) {
return new PeriodeMedUtbetalingsgradDto(Intervall.fraOgMedTilOgMed(fom, tom), null, Aktivitetsgrad.fra(100 - i));
}

private AktivitetDto lagAktivitet(Arbeidsgiver arbeidsgiver2, InternArbeidsforholdRefDto ref) {
return new AktivitetDto(arbeidsgiver2, ref, UttakArbeidType.ORDINÆRT_ARBEID);
}

}