diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrArbeidsforhold.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrArbeidsforhold.java index d8650772..4f1cb22f 100644 --- a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrArbeidsforhold.java +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrArbeidsforhold.java @@ -76,6 +76,17 @@ public String getBeskrivelse() { return inntektsgrunnlagPrÅr != null ? inntektsgrunnlagPrÅr : BigDecimal.ZERO; } + public BigDecimal getGradertInntektsgrunnlagInkludertNaturalytelsePrÅr() { + return finnGradert(getInntektsgrunnlagInkludertNaturalytelsePrÅr()); + } + + + public BigDecimal getInntektsgrunnlagInkludertNaturalytelsePrÅr() { + BigDecimal bortfaltNaturalytelse = naturalytelseBortfaltPrÅr != null ? naturalytelseBortfaltPrÅr : BigDecimal.ZERO; + BigDecimal tilkommetNaturalytelse = naturalytelseTilkommetPrÅr != null ? naturalytelseTilkommetPrÅr : BigDecimal.ZERO; + return getInntektsgrunnlagPrÅr().add(bortfaltNaturalytelse).subtract(tilkommetNaturalytelse); // NOSONAR + } + public Optional getAktivitetsgrad() { return Optional.ofNullable(aktivitetsgrad); } diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrStatus.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrStatus.java index a6565116..0071ee96 100644 --- a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrStatus.java +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/regelmodell/fastsett/BeregningsgrunnlagPrStatus.java @@ -69,6 +69,12 @@ public AktivitetStatus getAktivitetStatus() { .orElse(BigDecimal.ZERO); } + public BigDecimal getGradertInntektsgrunnlagInkludertNaturalytelsePrÅr() { + return inntektsgrunnlagPrÅr != null ? finnGradert(inntektsgrunnlagPrÅr) : getArbeidsforhold().stream() + .map(BeregningsgrunnlagPrArbeidsforhold::getGradertInntektsgrunnlagInkludertNaturalytelsePrÅr) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } public boolean erArbeidstakerEllerFrilanser() { return AktivitetStatus.erArbeidstaker(aktivitetStatus) || AktivitetStatus.erFrilanser(aktivitetStatus); @@ -127,6 +133,12 @@ private BigDecimal finnGradert(BigDecimal verdi) { return brutto.add(samletNaturalytelse); } + public BigDecimal getInntektsgrunnlagInkludertNaturalytelsePrÅr() { + BigDecimal inntektsgrunnlag = getInntektsgrunnlagPrÅr(); + BigDecimal samletNaturalytelse = samletNaturalytelseBortfaltMinusTilkommetPrÅr(); + return inntektsgrunnlag.add(samletNaturalytelse); + } + public BigDecimal getGradertBruttoInkludertNaturalytelsePrÅr() { return bruttoPrÅr != null ? finnGradert(getBruttoInkludertNaturalytelsePrÅr()) : getArbeidsforhold().stream() .map(BeregningsgrunnlagPrArbeidsforhold::getGradertBruttoInkludertNaturalytelsePrÅr) diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.java new file mode 100644 index 00000000..f047cff0 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.java @@ -0,0 +1,99 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import java.math.BigDecimal; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.fpsak.nare.doc.RuleDocumentation; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.specification.LeafSpecification; + +@RuleDocumentation(AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.ID) +public class AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling extends LeafSpecification { + public static final String ID = "FP_BR 29.8.4"; + public static final String BESKRIVELSE = "Avkort alle beregningsgrunnlagsandeler som ikke gjelder arbeidsforhold andelsmessig."; + + AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling() { + super(ID, BESKRIVELSE); + } + + @Override + public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { + Map resultater = new HashMap<>(); + BeregningsgrunnlagPrStatus atfl = grunnlag.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL); + BigDecimal sumBeregningsgrunnlagArbeidsforhold = atfl == null ? BigDecimal.ZERO : atfl.getArbeidsforholdIkkeFrilans() + .stream() + .map(BeregningsgrunnlagPrArbeidsforhold::getInntektsgrunnlagInkludertNaturalytelsePrÅr) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal grenseverdi = grunnlag.getGrenseverdi(); + resultater.put("grenseverdi", grenseverdi); + BigDecimal bGUtenArbeidsforholdTilFordeling = grenseverdi.subtract(sumBeregningsgrunnlagArbeidsforhold); + + // inntekt knyttet til frilans må fordeles først + if (atfl != null) { + Optional frilansArbeidsforholdOpt = atfl.getFrilansArbeidsforhold(); + if (frilansArbeidsforholdOpt.isPresent()) { + BeregningsgrunnlagPrArbeidsforhold af = frilansArbeidsforholdOpt.get(); + BigDecimal bruttoBeregningsgrunnlagForAndelen = af.getInntektsgrunnlagInkludertNaturalytelsePrÅr(); + BigDecimal avkortetBrukersAndel; + if (bruttoBeregningsgrunnlagForAndelen.compareTo(bGUtenArbeidsforholdTilFordeling) >= 0) { + avkortetBrukersAndel = bGUtenArbeidsforholdTilFordeling; + lagResultaterFrilanser(af, avkortetBrukersAndel, resultater); + grunnlag.getBeregningsgrunnlagPrStatusSomSkalBrukes().stream() + .filter(bgps -> !bgps.erArbeidstakerEllerFrilanser()) + .forEach(bgp -> lagResultaterUtenArbeidsforhold(bgp, BigDecimal.ZERO, resultater)); + return beregnet(resultater); + } else { + avkortetBrukersAndel = bruttoBeregningsgrunnlagForAndelen; + bGUtenArbeidsforholdTilFordeling = bGUtenArbeidsforholdTilFordeling.subtract(avkortetBrukersAndel); + lagResultaterFrilanser(af, avkortetBrukersAndel, resultater); + } + } + } + + // sortere etter avkorting prioritet for beregningsgrunnlag uten arbeidsforhold + List bgpsSorted = finnAlleBGUtenArbeidsForholdSorterte(grunnlag); + Iterator bgpsIter = bgpsSorted.iterator(); + while (bgpsIter.hasNext()) { + BeregningsgrunnlagPrStatus bgps = bgpsIter.next(); + BigDecimal bruttoBeregningsgrunnlagForAndelen = bgps.getInntektsgrunnlagPrÅr(); + BigDecimal avkortetBrukersAndel; + if (bruttoBeregningsgrunnlagForAndelen.compareTo(bGUtenArbeidsforholdTilFordeling) >= 0) { + avkortetBrukersAndel = bGUtenArbeidsforholdTilFordeling; + lagResultaterUtenArbeidsforhold(bgps, avkortetBrukersAndel, resultater); + bgpsIter.forEachRemaining(bgp -> lagResultaterUtenArbeidsforhold(bgp, BigDecimal.ZERO, resultater)); + return beregnet(resultater); + } else { + avkortetBrukersAndel = bruttoBeregningsgrunnlagForAndelen; + bGUtenArbeidsforholdTilFordeling = bGUtenArbeidsforholdTilFordeling.subtract(avkortetBrukersAndel); + lagResultaterUtenArbeidsforhold(bgps, avkortetBrukersAndel, resultater); + } + } + return beregnet(resultater); + } + + private List finnAlleBGUtenArbeidsForholdSorterte(BeregningsgrunnlagPeriode grunnlag) { + return grunnlag.getBeregningsgrunnlagPrStatus().stream() + .filter(bgps -> !bgps.erArbeidstakerEllerFrilanser()) + .sorted(Comparator.comparingInt(bgps -> bgps.getAktivitetStatus().getAvkortingPrioritet())) + .toList(); + } + + private void lagResultaterFrilanser(BeregningsgrunnlagPrArbeidsforhold af, BigDecimal avkortetBrukersAndel, Map resultater) { + BeregningsgrunnlagPrArbeidsforhold.builder(af).medAndelsmessigFørGraderingPrAar(avkortetBrukersAndel).build(); + resultater.put("avkortetPrÅr.arbeidsforhold." + af.getArbeidsgiverId(), af.getAvkortetBrukersAndelPrÅr()); + } + + private void lagResultaterUtenArbeidsforhold(BeregningsgrunnlagPrStatus bgps, BigDecimal avkortetBrukersAndel, Map resultater) { + BeregningsgrunnlagPrStatus.builder(bgps).medAndelsmessigFørGraderingPrAar(avkortetBrukersAndel).build(); + resultater.put("avkortetPrÅr.status." + bgps.getAktivitetStatus().name(), bgps.getAvkortetPrÅr()); + } +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForArbeidsforholdUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForArbeidsforholdUtenFordeling.java new file mode 100644 index 00000000..2429c835 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForArbeidsforholdUtenFordeling.java @@ -0,0 +1,56 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.fpsak.nare.doc.RuleDocumentation; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.evaluation.node.SingleEvaluation; +import no.nav.fpsak.nare.specification.LeafSpecification; + +@RuleDocumentation(FastsettAndelForArbeidsforholdUtenFordeling.ID) +class FastsettAndelForArbeidsforholdUtenFordeling extends LeafSpecification { + static final String ID = "FP_BR 29.8.6"; + static final String BESKRIVELSE = "Fastsett andeleler pr Arbeidsforhold"; + + FastsettAndelForArbeidsforholdUtenFordeling() { + super(ID, BESKRIVELSE); + } + + @Override + public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { + SingleEvaluation resultat = ja(); + List arbeidsforholdene = grunnlag.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL).getArbeidsforholdIkkeFrilans(); + Map resultater = new HashMap<>(); + resultat.setEvaluationProperties(resultater); + BigDecimal grenseverdi = grunnlag.getGrenseverdi(); + resultater.put("grenseverdi", grenseverdi); + fastsettAndelerPrArbeidsforhold(arbeidsforholdene, resultater, grenseverdi); + return resultat; + } + + private void fastsettAndelerPrArbeidsforhold(List arbeidsforholdList, Map resultater, + BigDecimal ikkeFordelt) { + BigDecimal sumBruttoBG = arbeidsforholdList.stream() + .map(BeregningsgrunnlagPrArbeidsforhold::getInntektsgrunnlagInkludertNaturalytelsePrÅr) + .reduce(BigDecimal.ZERO, BigDecimal::add); + arbeidsforholdList.forEach(af -> { + BigDecimal prosentandel = BigDecimal.valueOf(100) + .multiply(af.getInntektsgrunnlagInkludertNaturalytelsePrÅr()) + .divide(sumBruttoBG, 10, RoundingMode.HALF_EVEN); + resultater.put("gjenstårÅFastsetteRefusjon.prosentandel." + af.getArbeidsgiverId(), prosentandel); + BigDecimal andel = ikkeFordelt.multiply(af.getInntektsgrunnlagInkludertNaturalytelsePrÅr()) + .divide(sumBruttoBG, 10, RoundingMode.HALF_EVEN); + BeregningsgrunnlagPrArbeidsforhold.builder(af) + .medAndelsmessigFørGraderingPrAar(andel) + .build(); + resultater.put("brukersAndel." + af.getArbeidsgiverId(), af.getAvkortetBrukersAndelPrÅr()); + }); + } +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling.java new file mode 100644 index 00000000..c35de005 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling.java @@ -0,0 +1,45 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.fpsak.nare.doc.RuleDocumentation; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.evaluation.node.SingleEvaluation; +import no.nav.fpsak.nare.specification.LeafSpecification; + +@RuleDocumentation(FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling.ID) +class FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling extends LeafSpecification { + static final String ID = "FP_BR 29.8.10"; + static final String BESKRIVELSE = "Fastsett brukers andel for alle beregningsgrunnlagsandeler som gjelder arbeidsforhold."; + + FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling() { + super(ID, BESKRIVELSE); + } + + @Override + public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { + SingleEvaluation resultat = ja(); + BeregningsgrunnlagPrStatus atfl = grunnlag.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL); + if (atfl != null) { + Map resultater = new HashMap<>(); + resultat.setEvaluationProperties(resultater); + atfl.getArbeidsforholdIkkeFrilans().forEach(arbeidsforhold -> { + BigDecimal avkortetPrÅr = arbeidsforhold.getInntektsgrunnlagInkludertNaturalytelsePrÅr(); + BeregningsgrunnlagPrArbeidsforhold.builder(arbeidsforhold) + .medAndelsmessigFørGraderingPrAar(avkortetPrÅr) + .build(); + resultater.put("avkortetPrÅr" + "." + arbeidsforhold.getArbeidsgiverId(), avkortetPrÅr); + }); + } + return resultat; + } + + + +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelLikBruttoBGUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelLikBruttoBGUtenFordeling.java new file mode 100644 index 00000000..bc8bb3fd --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FastsettAndelLikBruttoBGUtenFordeling.java @@ -0,0 +1,45 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import java.math.BigDecimal; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.fpsak.nare.doc.RuleDocumentation; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.specification.LeafSpecification; + +@RuleDocumentation(FastsettAndelLikBruttoBGUtenFordeling.ID) +public class FastsettAndelLikBruttoBGUtenFordeling extends LeafSpecification { + + static final String ID = "FP_BR 29.6.2"; + static final String BESKRIVELSE = "Fastsett andel lik brutto bg"; + + public FastsettAndelLikBruttoBGUtenFordeling() { + super(ID, BESKRIVELSE); + } + + @Override + public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { + + for (BeregningsgrunnlagPrStatus beregningsgrunnlagPrStatus : grunnlag.getBeregningsgrunnlagPrStatus()) { + if (AktivitetStatus.erArbeidstaker(beregningsgrunnlagPrStatus.getAktivitetStatus())) { + for (BeregningsgrunnlagPrArbeidsforhold af : beregningsgrunnlagPrStatus.getArbeidsforhold()) { + BigDecimal inntekt = af.getInntektsgrunnlagInkludertNaturalytelsePrÅr(); + BeregningsgrunnlagPrArbeidsforhold.builder(af) + .medAndelsmessigFørGraderingPrAar(inntekt) + .build(); + } + } else { + BigDecimal avkortetPrStatus = beregningsgrunnlagPrStatus.getInntektsgrunnlagPrÅr(); + BeregningsgrunnlagPrStatus.builder(beregningsgrunnlagPrStatus) + .medAndelsmessigFørGraderingPrAar(avkortetPrStatus) + .build(); + } + } + return ja(); + + } + +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java new file mode 100644 index 00000000..93cda4b7 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/FinnGrenseverdiUtenFordeling.java @@ -0,0 +1,167 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.MidlertidigInaktivType; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; +import no.nav.fpsak.nare.doc.RuleDocumentation; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.evaluation.node.SingleEvaluation; +import no.nav.fpsak.nare.specification.LeafSpecification; + +@RuleDocumentation(FinnGrenseverdiUtenFordeling.ID) +public class FinnGrenseverdiUtenFordeling extends LeafSpecification { + + public static final String ID = "FP_BR 6.2"; + public static final String BESKRIVELSE = "Finn grenseverdi"; + + public FinnGrenseverdiUtenFordeling() { + super(ID, BESKRIVELSE); + } + + @Override + public Evaluation evaluate(BeregningsgrunnlagPeriode grunnlag) { + Map resultater = new HashMap<>(); + + //gradering mot uttak + BigDecimal summerAvkortetGradertMotUttak = summerAvkortetGradertMotUttak(grunnlag); + var grenseverdi = summerAvkortetGradertMotUttak; + BigDecimal sumAvkortet = summerAvkortet(grunnlag); + BigDecimal totalUtbetalingsgradFraUttak = sumAvkortet.signum() != 0 ? summerAvkortetGradertMotUttak.divide(sumAvkortet, 4, RoundingMode.HALF_UP) : BigDecimal.ZERO; + grunnlag.setTotalUtbetalingsgradFraUttak(totalUtbetalingsgradFraUttak); + resultater.put("totalUtbetalingsgradFraUttak", totalUtbetalingsgradFraUttak); + + //hvis §8-47a, skaler med fast faktor + var erInaktivTypeA = MidlertidigInaktivType.A.equals(grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivType()); + if (erInaktivTypeA) { + BigDecimal reduksjonsfaktor = grunnlag.getBeregningsgrunnlag().getMidlertidigInaktivTypeAReduksjonsfaktor(); + grenseverdi = grenseverdi.multiply(reduksjonsfaktor); + resultater.put("grad847a", reduksjonsfaktor); + } + + //juster ned med tilkommet inntekt hvis det gir lavere utbetaling enn overstående + if (grunnlag.getBeregningsgrunnlag().getToggles().isEnabled("GRADERING_MOT_INNTEKT", false) && !grunnlag.getTilkommetInntektsforholdListe().isEmpty()) { + BigDecimal graderingPåToppenAvUttakgraderingPgaTilkommetInntekt = andelBeholdtEtterGradertMotTilkommetInntekt(grunnlag); + resultater.put("graderingPåToppenAvUttakgraderingPgaTilkommetInntekt", min(BigDecimal.ONE, graderingPåToppenAvUttakgraderingPgaTilkommetInntekt)); + BigDecimal totalUtbetalingsgradEtterReduksjonVedTilkommetInntekt = min(BigDecimal.ONE, totalUtbetalingsgradFraUttak.multiply(graderingPåToppenAvUttakgraderingPgaTilkommetInntekt)); + resultater.put("totalUtbetalingsgradEtterReduksjonVedTilkommetInntekt", totalUtbetalingsgradEtterReduksjonVedTilkommetInntekt); + grunnlag.setTotalUtbetalingsgradEtterReduksjonVedTilkommetInntekt(totalUtbetalingsgradEtterReduksjonVedTilkommetInntekt); + + //deprecated etter totalUtbetalingsgradEtterReduksjonVedTilkommetInntekt ble lagt til? + grenseverdi = graderingPåToppenAvUttakgraderingPgaTilkommetInntekt.compareTo(BigDecimal.ONE) < 0 ? grenseverdi.multiply(graderingPåToppenAvUttakgraderingPgaTilkommetInntekt) : grenseverdi; + if (grunnlag.getInntektsgraderingFraBruttoBeregningsgrunnlag() != null) { + resultater.put("inntektgraderingsprosent", grunnlag.getInntektsgraderingFraBruttoBeregningsgrunnlag()); + } + } + resultater.put("grenseverdi", grenseverdi); + grunnlag.setGrenseverdi(grenseverdi); + SingleEvaluation resultat = ja(); + resultat.setEvaluationProperties(resultater); + return resultat; + + } + + static BigDecimal min(BigDecimal a, BigDecimal b){ + return a.compareTo(b) > 0 ? b : a; + } + + private static BigDecimal summerAvkortetGradertMotUttak(BeregningsgrunnlagPeriode grunnlag) { + BigDecimal sum = BigDecimal.ZERO; + for (BeregningsgrunnlagPrStatus bps : grunnlag.getBeregningsgrunnlagPrStatusSomSkalBrukes()) { + if (bps.erArbeidstakerEllerFrilanser()) { + sum = sum.add(bps.getArbeidsforholdSomSkalBrukes().stream() + .map(arb -> arb.getAndelsmessigFørGraderingPrAar().multiply(arb.getUtbetalingsprosent().scaleByPowerOfTen(-2))) + .reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); + } else { + sum = sum.add(bps.getAndelsmessigFørGraderingPrAar().multiply(bps.getUtbetalingsprosent().scaleByPowerOfTen(-2))); + } + } + return sum; + } + + private static BigDecimal summerAvkortet(BeregningsgrunnlagPeriode grunnlag) { + BigDecimal sum = BigDecimal.ZERO; + for (BeregningsgrunnlagPrStatus bps : grunnlag.getBeregningsgrunnlagPrStatusSomSkalBrukes()) { + if (bps.erArbeidstakerEllerFrilanser()) { + sum = sum.add(bps.getArbeidsforholdSomSkalBrukes().stream() + .map(arb -> arb.getAndelsmessigFørGraderingPrAar()) + .reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); + } else { + sum = sum.add(bps.getAndelsmessigFørGraderingPrAar()); + } + } + return sum; + } + + private BigDecimal andelBeholdtEtterGradertMotTilkommetInntekt(BeregningsgrunnlagPeriode grunnlag) { + BigDecimal bortfalt = finnBortfaltInntekt(grunnlag); + var totaltGradertGrunnlag = grunnlag.getBeregningsgrunnlagPrStatus().stream() + .map(BeregningsgrunnlagPrStatus::getGradertInntektsgrunnlagInkludertNaturalytelsePrÅr) + .reduce(BigDecimal.ZERO, BigDecimal::add); + if (totaltGradertGrunnlag.compareTo(BigDecimal.ZERO) == 0) { + return BigDecimal.ZERO; + } + var totaltGrunnlag = grunnlag.getBeregningsgrunnlagPrStatus().stream() + .map(BeregningsgrunnlagPrStatus::getInntektsgrunnlagInkludertNaturalytelsePrÅr) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + var graderingMotTotal = bortfalt.divide(totaltGrunnlag, 10, RoundingMode.HALF_UP); + grunnlag.setInntektsgraderingFraBruttoBeregningsgrunnlag(graderingMotTotal.multiply(BigDecimal.valueOf(100))); + + return bortfalt.divide(totaltGradertGrunnlag, 10, RoundingMode.HALF_UP); + } + + private BigDecimal finnBortfaltInntekt(BeregningsgrunnlagPeriode grunnlag) { + var bortfalt = BigDecimal.ZERO; + for (BeregningsgrunnlagPrStatus bps : grunnlag.getBeregningsgrunnlagPrStatus()) { + if (bps.erArbeidstakerEllerFrilanser()) { + bortfalt = bortfalt.add(finnBortfaltFraATFL(bps.getArbeidsforhold())); + } else { + bortfalt = bortfalt.add(finnBortfaltForStatus(bps)); + } + } + + var tilkommetInntekt = grunnlag.getTilkommetInntektsforholdListe().stream() + .map(TilkommetInntekt::getTilkommetPrÅr) + .reduce(BigDecimal::add) + .orElse(BigDecimal.ZERO); + + var bruttoBortfalt = bortfalt.subtract(tilkommetInntekt); + return bruttoBortfalt.max(BigDecimal.ZERO); + } + + private BigDecimal finnBortfaltForStatus(BeregningsgrunnlagPrStatus bps) { + var aktivitetsgradOpt = bps.getAktivitetsgrad(); + if (aktivitetsgradOpt.isPresent()) { + var aktivitetsgrad = aktivitetsgradOpt.get().divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP); + var opprettholdtInntekt = bps.getInntektsgrunnlagPrÅr().multiply(aktivitetsgrad); + return bps.getInntektsgrunnlagPrÅr().subtract(opprettholdtInntekt); + } + var utbetalingsprosent = bps.getUtbetalingsprosent(); + var utbetalingsgrad = utbetalingsprosent.divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP); + return bps.getInntektsgrunnlagPrÅr().multiply(utbetalingsgrad); + } + + private BigDecimal finnBortfaltFraATFL(List arbeidsforhold1) { + return arbeidsforhold1.stream() + .map(arbeidsforhold -> { + var aktivitetsgradOpt = arbeidsforhold.getAktivitetsgrad(); + if (aktivitetsgradOpt.isPresent()) { + var aktivitetsgrad = aktivitetsgradOpt.get().divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP); + var opprettholdtInntekt = arbeidsforhold.getInntektsgrunnlagPrÅr().multiply(aktivitetsgrad); + return arbeidsforhold.getInntektsgrunnlagPrÅr().subtract(opprettholdtInntekt); + } + var utbetalingsprosent = arbeidsforhold.getUtbetalingsprosent(); + var utbetalingsgrad = utbetalingsprosent.divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_UP); + return arbeidsforhold.getInntektsgrunnlagPrÅr().multiply(utbetalingsgrad); + }) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFastsettAndelBGOver6GUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFastsettAndelBGOver6GUtenFordeling.java new file mode 100644 index 00000000..b081ce87 --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFastsettAndelBGOver6GUtenFordeling.java @@ -0,0 +1,61 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.Fastsatt; +import no.nav.fpsak.nare.RuleService; +import no.nav.fpsak.nare.Ruleset; +import no.nav.fpsak.nare.specification.Specification; + +public class RegelFastsettAndelBGOver6GUtenFordeling implements RuleService { + public static final String ID = "FP_BR_29.8"; + public static final String BESKRIVELSE = "Fastsett avkortet BG over 6G når refusjon under 6G"; + private BeregningsgrunnlagPeriode regelmodell; + + public RegelFastsettAndelBGOver6GUtenFordeling(BeregningsgrunnlagPeriode regelmodell) { + super(); + this.regelmodell = regelmodell; + } + + @SuppressWarnings("unchecked") + @Override + public Specification getSpecification() { + BeregningsgrunnlagPrStatus bgpsa = regelmodell.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL); + + Ruleset rs = new Ruleset<>(); + + //FP_BR_29.8.10 For alle beregningsgrunnlagsandeler som gjelder arbeidsforhold, fastsett Brukers Andel + //FP_BR_29.8.4 Avkort alle beregningsgrunnlagsander som ikke gjelder arbeidsforhold andelsmessig + Specification avkortAndelerAndelsmessigOgFastsettBrukersAndel = rs.beregningsRegel( + AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.ID, + AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling.BESKRIVELSE, + new AvkortBGAndelerSomIkkeGjelderArbeidsforholdAndelsmessigUtenFordeling(), + new FastsettAndelForBGAndelerSomGjelderArbeidsforholdUtenFordeling()); + + Specification avkortAndelerSomIkkegjelderAFtil0 = new Fastsatt(); + + if (bgpsa != null) { + Specification fastsettAndelerForArbeidsforhold = rs.beregningsRegel( + FastsettAndelForArbeidsforholdUtenFordeling.ID, + FastsettAndelForArbeidsforholdUtenFordeling.BESKRIVELSE, + new FastsettAndelForArbeidsforholdUtenFordeling(), + new Fastsatt()); + + //FP_BR_29.8.3 Avkort alle beregningsgrunnlagsandeler som ikke gjelder arbeidsforhold til 0 + avkortAndelerSomIkkegjelderAFtil0 = rs.beregningsRegel( + AvkortBGAndelerSomIkkeGjelderArbeidsforholdTil0.ID, + AvkortBGAndelerSomIkkeGjelderArbeidsforholdTil0.BESKRIVELSE, + new AvkortBGAndelerSomIkkeGjelderArbeidsforholdTil0(), + fastsettAndelerForArbeidsforhold); + } + + //FP_BR_29.8.2 Er totalt BG for beregningsgrunnlagsandeler fra arbeidsforhold > 6G? + Specification erTotaltBGFraArbeidforholdStørreEnn6G = rs.beregningHvisRegel(new SjekkOmTotaltBGForArbeidsforholdStørreEnnGrenseverdi(), + avkortAndelerSomIkkegjelderAFtil0, avkortAndelerAndelsmessigOgFastsettBrukersAndel); + + + return erTotaltBGFraArbeidforholdStørreEnn6G; + } + +} diff --git a/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordeling.java b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordeling.java new file mode 100644 index 00000000..787cdbfb --- /dev/null +++ b/src/main/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordeling.java @@ -0,0 +1,57 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import no.nav.folketrygdloven.beregningsgrunnlag.fastsette.SjekkBeregningsgrunnlagStørreEnnGrenseverdi; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.Fastsatt; +import no.nav.folketrygdloven.regelmodelloversetter.EksportRegel; +import no.nav.fpsak.nare.Ruleset; +import no.nav.fpsak.nare.evaluation.Evaluation; +import no.nav.fpsak.nare.specification.Specification; + +public class RegelFinnGrenseverdiUtenFordeling implements EksportRegel { + + public static final String ID = "FP_BR_29_uten_fordeling"; + + private BeregningsgrunnlagPeriode regelmodell; + + public RegelFinnGrenseverdiUtenFordeling(BeregningsgrunnlagPeriode regelmodell) { + this.regelmodell = regelmodell; + } + + @Override + public Evaluation evaluer(BeregningsgrunnlagPeriode regelmodell) { + return getSpecification().evaluate(regelmodell); + } + + @SuppressWarnings("unchecked") + @Override + public Specification getSpecification() { + Ruleset rs = new Ruleset<>(); + + // Fastsett grenseverdi for fastsetting av beregningsgrunnlag + Specification fastsettGrenseverdi = rs.beregningsRegel(FinnGrenseverdiUtenFordeling.ID, FinnGrenseverdiUtenFordeling.BESKRIVELSE, + new FinnGrenseverdiUtenFordeling(), new Fastsatt()); + + // Fastsett avkortet BG + Specification fastsettAvkortet = rs.beregningsRegel( + RegelFastsettAndelBGOver6GUtenFordeling.ID, + RegelFastsettAndelBGOver6GUtenFordeling.BESKRIVELSE, + new RegelFastsettAndelBGOver6GUtenFordeling(regelmodell).getSpecification(), + fastsettGrenseverdi); + + // Fastsett uten avkorting + Specification fastsettUtenAvkorting = rs.beregningsRegel( + "FP_BR_29.6", + "Fastsett BG uten avkorting", + new FastsettAndelLikBruttoBGUtenFordeling(), + fastsettGrenseverdi); + + // FP_BR_29.4 4. Brutto beregnings-grunnlag totalt > 6G? + Specification beregnEventuellAvkorting = rs.beregningHvisRegel( + new SjekkBeregningsgrunnlagStørreEnnGrenseverdi(), + fastsettAvkortet, + fastsettUtenAvkorting); + + return beregnEventuellAvkorting; + } +} diff --git a/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java new file mode 100644 index 00000000..58e937e8 --- /dev/null +++ b/src/test/java/no/nav/folketrygdloven/beregningsgrunnlag/ytelse/svp/RegelFinnGrenseverdiUtenFordelingTest.java @@ -0,0 +1,1722 @@ +package no.nav.folketrygdloven.beregningsgrunnlag.ytelse.svp; + +import static no.nav.folketrygdloven.beregningsgrunnlag.util.DateUtil.TIDENES_ENDE; +import static org.assertj.core.api.Assertions.assertThat; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.AktivitetStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.MidlertidigInaktivType; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.Periode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.RegelResultat; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.Beregningsgrunnlag; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPeriode; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrArbeidsforhold; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.BeregningsgrunnlagPrStatus; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.fastsett.TilkommetInntekt; +import no.nav.folketrygdloven.beregningsgrunnlag.regelmodell.grunnlag.inntekt.Arbeidsforhold; + +class RegelFinnGrenseverdiUtenFordelingTest { + + public static final String ORGNR = "910"; + private static final String ORGNR_2 = "974760673"; + private static final String ORGNR_3 = "976967631"; + public static final Arbeidsforhold AF_1 = Arbeidsforhold.nyttArbeidsforholdHosVirksomhet(ORGNR); + public static final Arbeidsforhold AF_2 = Arbeidsforhold.nyttArbeidsforholdHosVirksomhet(ORGNR_2); + public static final Arbeidsforhold AF_3 = Arbeidsforhold.nyttArbeidsforholdHosVirksomhet(ORGNR_3); + + @Test + void ett_arbeidsforhold_under_6G() { + //Arrange + double beregnetPrÅr = 400_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(beregnetPrÅr)); + } + + @Test + void ett_arbeidsforhold_under_6G_midlertidig_inaktiv_type_A() { + //Arrange + double beregnetPrÅr = 400_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medMidlertidigInaktivType(MidlertidigInaktivType.A) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + var forventet = 260_000; + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(forventet)); + } + + + @Test + void ett_arbeidsforhold_under_6G_ikkje_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 400_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(0)); + } + + @Test + void ett_arbeidsforhold_over_6G() { + //Arrange + double beregnetPrÅr = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void to_arbeidsforhold_under_6G() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(550_000)); + } + + @Test + void to_arbeidsforhold_under_6G_tilkommet_inntekt_i_det_ene() { + //Arrange + double beregnetPrÅr = 250_000; + double tilkommetPrÅr2 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, null, null, 100D, 0D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(150_000)); + } + + @Test + void to_arbeidsforhold_under_6G_tilkommet_inntekt_i_det_ene_mer_enn_totalt_grunnlag_på_stp() { + //Arrange + double beregnetPrÅr = 250_000; + double tilkommetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, null, null, 100D, 0D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.ZERO); + } + + @Test + void to_arbeidsforhold_under_6G_fordelt_og_tilkommet_inntekt_i_det_ene() { + //Arrange + double beregnetPrÅr = 250_000; + double fordeltPrÅr = 150_000; + + double tilkommetPrÅr2 = 25_000; + double fordeltPrÅr2 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, fordeltPrÅr, 100d,0D); + leggTilArbeidsforhold(periode, AF_2, null, fordeltPrÅr2, 50d,50D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(225_000)); + } + + + + @Test + void to_arbeidsforhold_over_6G() { + //Arrange + double beregnetPrÅr = 350_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void to_arbeidsforhold_over_6G_pluss_et_tilkommet() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 300_000; + double tilkommetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_3, null, null, 100D, 0D); + leggTilTilkommet(periode, AF_3, tilkommetPrÅr); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(450_000)); + } + + + @Test + void to_arbeidsforhold_under_6G_søkt_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(250_000)); + } + + @Test + void to_arbeidsforhold_under_6G_søkt_ytelse_for_en_pluss_et_tilkommet() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + double tilkommetPrÅr = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + leggTilArbeidsforhold(periode, AF_3, null, null, 100D, 100D); + leggTilTilkommet(periode, AF_3, tilkommetPrÅr); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(150_000)); + } + + + @Test + void to_arbeidsforhold_til_sammen_over_6G_søkt_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 500_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void to_arbeidsforhold_til_sammen_over_6G_søkt_ytelse_for_en_pluss_et_tilkommet() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 500_000; + double tilkommetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + leggTilArbeidsforhold(periode, AF_3, null, null, 0D, 100D); + leggTilTilkommet(periode, AF_3,tilkommetPrÅr); + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(180_000)); + } + + @Test + void to_arbeidsforhold_til_sammen_over_6G_søkt_ytelse_for_begge_gradert_pluss_et_tilkommet() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 500_000; + double tilkommetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 20D, 80D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_3, null, null, 0D, 100D); + leggTilTilkommet(periode, AF_3, tilkommetPrÅr); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi().setScale(2, RoundingMode.HALF_UP)).isEqualByComparingTo(BigDecimal.valueOf(90_000)); + } + + @Test + void to_arbeidsforhold_den_ene_over_6G_søkt_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(480_000)); + } + + @Test + void to_arbeidsforhold_under_6G_delvis_søkt_ytelse_for_en_full_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void to_arbeidsforhold_over_6G_for_begge_delvis_søkt_ytelse_for_en_full_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 600_000; + double beregnetPrÅr2 = 600_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(450_000)); + } + + @Test + void to_arbeidsforhold_over_6G_for_en_delvis_søkt_ytelse_for_en_full_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(540_000)); + } + + @Test + void to_arbeidsforhold_over_6G_for_en_delvis_søkt_ytelse_for_en_full_ytelse_for_den_over_6G() { + //Arrange + double beregnetPrÅr = 600_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + + @Test + void to_arbeidsforhold_under_6G_delvis_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(275_000)); + } + + @Test + void to_arbeidsforhold_over_6G_for_begge_delvis_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 600_000; + double beregnetPrÅr2 = 600_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void to_arbeidsforhold_over_6G_for_en_delvis_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 600_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void to_arbeidsforhold_over_6G_delvis_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 250_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(275_000)); + } + + + @Test + void tre_arbeidsforhold_over_6G_søkt_ytelse_for_en() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 300_000; + double beregnetPrÅr3 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 0D, 100D); + leggTilArbeidsforhold(periode, AF_3, beregnetPrÅr3, null, 0D, 100D); + + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void tre_arbeidsforhold_over_6G_søkt_ytelse_for_to() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 300_000; + double beregnetPrÅr3 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_3, beregnetPrÅr3, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void tre_arbeidsforhold_over_6G_delvis_søkt_ytelse_for_en_full_for_en() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 300_000; + double beregnetPrÅr3 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 50D, 50D); + leggTilArbeidsforhold(periode, AF_3, beregnetPrÅr3, null, 0D, 100D); + + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void tre_arbeidsforhold_over_6G_søkt_ytelse_for_alle() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 300_000; + double beregnetPrÅr3 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr2, null, 100D, 0D); + leggTilArbeidsforhold(periode, AF_3, beregnetPrÅr3, null, 100D, 0D); + + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void frilans_under_6G_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void frilans_under_6G_ikkje_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(0)); + } + + @Test + void frilans_over_6G_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void frilans_under_6G_delvis_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(150_000)); + } + + @Test + void frilans_over_6G_delvis_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + + @Test + void frilans_og_et_arbeidsforhold_under_6G_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(500_000)); + } + + + @Test + void et_arbeidsforhold_under_6G_tilkommet_frilansinntekt() { + //Arrange + double beregnetPrÅr = 300_000; + double tilkommetFrilansinntekt = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, null, 100D, 0D); + leggTilTilkommet(periode, Arbeidsforhold.frilansArbeidsforhold(), tilkommetFrilansinntekt); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi().setScale(2, RoundingMode.HALF_UP)).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_under_6G_søkt_ytelse_for_begge_tilkommet_frilansinntekt() { + //Arrange + double beregnetPrÅr = 300_000; + double beregnetPrÅr2 = 200_000; + double tilkommetFrilansinntekt = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilTilkommet(periode, Arbeidsforhold.frilansArbeidsforhold(), tilkommetFrilansinntekt); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_søkt_ytelse_for_begge_tilkommet_frilansinntekt() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 200_000; + double tilkommetFrilansinntekt = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilTilkommet(periode, Arbeidsforhold.frilansArbeidsforhold(), tilkommetFrilansinntekt); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(480_000)); + } + + + @Test + void frilans_og_et_arbeidsforhold_over_6G_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + + @Test + void frilans_og_et_arbeidsforhold_under_6G_søkt_ytelse_for_kun_frilans() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_under_6G_søkt_ytelse_for_kun_arbeid() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 300_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_til_sammen_søkt_ytelse_for_kun_frilans() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 500_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_til_sammen_søkt_ytelse_for_kun_arbeid() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 500_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(500_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_for_arbeidsforhold_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_for_arbeidsforhold_søkt_ytelse_for_kun_frilans() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(0)); + } + + @Test + void frilans_og_et_arbeidsforhold_over_6G_for_arbeidsforhold_søkt_ytelse_for_kun_arbeid() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + + @Test + void næring_under_6G_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void næring_under_6G_søkt_delvis_ytelse() { + //Arrange + double beregnetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 50D, 50D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void næring_under_6G_søkt_delvis_ytelse_tilkommet_inntekt() { + //Arrange + double beregnetPrÅr = 200_000; + double tilkommet = 50_000; + + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 50D, 50D); + leggTilTilkommet(periode, null, tilkommet); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(50_000)); + } + + @Test + void næring_under_6G_ikkje_søkt_ytelse() { + //Arrange + double beregnetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(0)); + } + + @Test + void næring_og_frilans_under_6G_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void næring_og_frilans_over_6G_søkt_ytelse_for_begge() { + //Arrange + double beregnetPrÅr = 500_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void næring_og_frilans_over_6G_søkt_ytelse_for_begge_tilkommet_næring() { + //Arrange + double beregnetPrÅr = 500_000; + double tilkommet = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilTilkommet(periode, null, tilkommet); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(540_000)); + } + + @Test + void næring_og_frilans_over_6G_for_næring_søkt_ytelse_for_næring() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void næring_og_frilans_over_6G_for_frilans_søkt_ytelse_for_næring() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(0)); + } + + @Test + void næring_og_frilans_over_6G_for_frilans_søkt_ytelse_for_frilans() { + //Arrange + double beregnetPrÅr = 200_000; + double beregnetPrÅr2 = 800_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 0D, 100D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(600_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_under_6G_søkt_ytelse_for_alle() { + //Arrange + double beregnetPrÅr = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 100D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(300_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_under_6G_søkt_ytelse_for_næring() { + //Arrange + double beregnetPrÅr = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_under_6G_søkt_ytelse_for_arbeid() { + //Arrange + double beregnetPrÅr = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 0D, 100D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_over_6G_for_næring_søkt_ytelse_for_arbeid() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 100_000; + double beregnetPrÅr3 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 0D, 100D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr3, null, 100D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_over_6G_for_næring_søkt_ytelse_for_næring() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 100_000; + double beregnetPrÅr3 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 100D, 0D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr3, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(400_000)); + } + + @Test + void næring_frilans_og_arbeidsforhold_over_6G_for_næring_søkt_delvis_ytelse_for_næring() { + //Arrange + double beregnetPrÅr = 800_000; + double beregnetPrÅr2 = 100_000; + double beregnetPrÅr3 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 50D, 50D); + leggTilStatus(periode, AktivitetStatus.FL, beregnetPrÅr2, 0D, 100D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr3, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void næring_og_arbeidsforhold_over_6G_til_sammen_søkt_delvis_ytelse_for_næring_rest_etter_arbeid_mindre_enn_bg_for_frilans() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 200_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 50D, 50D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 0D, 100D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(200_000)); + } + + @Test + void næring_og_arbeidsforhold_over_6G_til_sammen_søkt_delvis_ytelse_for_næring_rest_etter_arbeid_mindre_enn_gradert_bg_for_frilans() { + //Arrange + double beregnetPrÅr = 500_000; + double beregnetPrÅr2 = 400_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilStatus(periode, AktivitetStatus.SN, beregnetPrÅr, 50D, 0D); + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr2, null, 0D, 0D); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(100_000)); + } + + @Test + void to_arbeidsforhold_under_6G_aktivitetsgrad_høyere_enn_utbetalingsgrad() { + //Arrange + double beregnetPrÅr = 250_000; + double tilkommetPrÅr2 = 100_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 70D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr, null, 50D, 70D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(50_000)); + } + + @Test + void to_arbeidsforhold_under_6G_aktivitetsgrad_mye_høyere_enn_utbetalingsgrad() { + //Arrange + double beregnetPrÅr = 250_000; + double tilkommetPrÅr2 = 30_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 50D, 90D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr, null, 30D, 90D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi()).isEqualByComparingTo(BigDecimal.valueOf(20_000)); + } + + @Test + void to_arbeidsforhold_under_6G_aktivitetsgrad_lavere_enn_utbetalingsgrad() { + //Arrange + double beregnetPrÅr = 250_000; + double tilkommetPrÅr2 = 30_000; + + BeregningsgrunnlagPeriode periode = BeregningsgrunnlagPeriode.builder() + .medPeriode(Periode.of(LocalDate.now(), TIDENES_ENDE)) + .build(); + + Beregningsgrunnlag.builder() + .leggTilToggle("GRADERING_MOT_INNTEKT", true) + .medBeregningsgrunnlagPeriode(periode) + .medGrunnbeløp(BigDecimal.valueOf(100_000)); + + leggTilArbeidsforhold(periode, AF_1, beregnetPrÅr, null, 90D, 20D); + leggTilArbeidsforhold(periode, AF_2, beregnetPrÅr, null, 95D, 10D); + leggTilTilkommet(periode, AF_2, tilkommetPrÅr2); + + //Act + kjørRegel(periode); + + assertThat(periode.getGrenseverdi().setScale(2, RoundingMode.HALF_UP)).isEqualByComparingTo(BigDecimal.valueOf(395_000)); + } + + + private RegelResultat kjørRegel(BeregningsgrunnlagPeriode periode) { + return new RegelFinnGrenseverdiUtenFordeling(periode).evaluerRegel(periode); + } + + private void leggTilArbeidsforhold(BeregningsgrunnlagPeriode periode, + Arbeidsforhold arbeidsforhold, + Double beregnetPrÅr, + Double fordeltPrÅr, + Double utbetalingsgrad, + Double aktivitetsgrad) { + BeregningsgrunnlagPrStatus atfl = periode.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL); + if (atfl == null) { + BeregningsgrunnlagPeriode.oppdater(periode) + .medBeregningsgrunnlagPrStatus(BeregningsgrunnlagPrStatus + .builder() + .medAktivitetStatus(AktivitetStatus.ATFL) + .medArbeidsforhold(lagBeregningsgrunnlagPrArbeidsforhold(finnHøyestLedigeAndelsnr(periode), beregnetPrÅr, fordeltPrÅr, 100_000, utbetalingsgrad, aktivitetsgrad, arbeidsforhold)) + .build()); + } else { + BeregningsgrunnlagPrStatus.builder(atfl) + .medArbeidsforhold(lagBeregningsgrunnlagPrArbeidsforhold(finnHøyestLedigeAndelsnr(periode), beregnetPrÅr, fordeltPrÅr, 100_000, utbetalingsgrad, aktivitetsgrad, arbeidsforhold)) + .build(); + } + } + + + private void leggTilTilkommet(BeregningsgrunnlagPeriode periode, + Arbeidsforhold arbeidsforhold, + Double tilkommetPrÅr) { + AktivitetStatus status; + if (arbeidsforhold == null) { + status = AktivitetStatus.SN; + } else { + status = arbeidsforhold.erFrilanser() ? AktivitetStatus.FL : AktivitetStatus.AT; + } + lagTilkommet(periode, tilkommetPrÅr, arbeidsforhold, status); + } + + private void lagTilkommet(BeregningsgrunnlagPeriode periode, Double tilkommetPrÅr, Arbeidsforhold arbeidsforhold, AktivitetStatus aktivitetStatus) { + if (tilkommetPrÅr != null) { + var tilkommetInntekt = new TilkommetInntekt(aktivitetStatus, arbeidsforhold, BigDecimal.valueOf(tilkommetPrÅr)); + BeregningsgrunnlagPeriode.oppdater(periode).leggTilTilkommetInntektsforhold(List.of(tilkommetInntekt)); + } + } + private void leggTilStatus(BeregningsgrunnlagPeriode periode, + AktivitetStatus status, + Double beregnetPrÅr, + Double utbetalingsgrad, + Double aktivitetsgrad) { + finnHøyestLedigeAndelsnr(periode); + if (status.equals(AktivitetStatus.FL)) { + Arbeidsforhold arbeidsforhold = Arbeidsforhold.frilansArbeidsforhold(); + BeregningsgrunnlagPrStatus atfl = periode.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL); + if (atfl == null) { + BeregningsgrunnlagPeriode.oppdater(periode) + .medBeregningsgrunnlagPrStatus(BeregningsgrunnlagPrStatus + .builder() + .medAktivitetStatus(AktivitetStatus.ATFL) + .medArbeidsforhold(lagBeregningsgrunnlagPrArbeidsforhold(finnHøyestLedigeAndelsnr(periode), beregnetPrÅr, null, 0, utbetalingsgrad, aktivitetsgrad, arbeidsforhold)) + .build()); + } else { + BeregningsgrunnlagPrStatus.builder(atfl) + .medArbeidsforhold(lagBeregningsgrunnlagPrArbeidsforhold(finnHøyestLedigeAndelsnr(periode), beregnetPrÅr, null, 0, utbetalingsgrad, aktivitetsgrad, arbeidsforhold)) + .build(); + } + } else if (status.equals(AktivitetStatus.SN)) { + var bruttoPrÅr = beregnetPrÅr != null ? BigDecimal.valueOf(beregnetPrÅr) : null; + BeregningsgrunnlagPrStatus prStatus = BeregningsgrunnlagPrStatus + .builder() + .medAndelNr(finnHøyestLedigeAndelsnr(periode)) + .medAktivitetStatus(AktivitetStatus.SN) + .medBruttoPrÅr(bruttoPrÅr) + .medInntektsgrunnlagPrÅr(bruttoPrÅr) + .medAktivitetsgrad(aktivitetsgrad == null ? null : BigDecimal.valueOf(aktivitetsgrad)) + .medUtbetalingsprosent(BigDecimal.valueOf(utbetalingsgrad)) + .build(); + prStatus.setErSøktYtelseFor(utbetalingsgrad > 0); + BeregningsgrunnlagPeriode.oppdater(periode) + .medBeregningsgrunnlagPrStatus(prStatus); + + } + + } + + private BeregningsgrunnlagPrArbeidsforhold lagBeregningsgrunnlagPrArbeidsforhold(long andelsnr, + Double beregnetPrÅr, + Double fordeltPrÅr, + double refusjonskrav, + double utbetalingsgrad, + Double aktivitetsgrad, + Arbeidsforhold arbeidsforhold) { + var bruttoPrÅr = finnBrutto(beregnetPrÅr, fordeltPrÅr); + BeregningsgrunnlagPrArbeidsforhold arb = BeregningsgrunnlagPrArbeidsforhold.builder() + .medAndelNr(andelsnr) + .medArbeidsforhold(arbeidsforhold) + .medInntektsgrunnlagPrÅr(beregnetPrÅr != null ? BigDecimal.valueOf(beregnetPrÅr) : null) + .medBruttoPrÅr(bruttoPrÅr) + .medRefusjonPrÅr(BigDecimal.valueOf(refusjonskrav)) + .medUtbetalingsprosent(BigDecimal.valueOf(utbetalingsgrad)) + .medAktivitetsgrad(aktivitetsgrad == null ? null : BigDecimal.valueOf(aktivitetsgrad)) + .build(); + arb.setErSøktYtelseFor(utbetalingsgrad > 0); + return arb; + } + + private BigDecimal finnBrutto(Double beregnetPrÅr, Double fordeltPrÅr) { + if (fordeltPrÅr != null) { + return BigDecimal.valueOf(fordeltPrÅr); + } + return beregnetPrÅr != null ? BigDecimal.valueOf(beregnetPrÅr) : BigDecimal.ZERO; + } + + private static long finnHøyestLedigeAndelsnr(BeregningsgrunnlagPeriode periode) { + return periode.getBeregningsgrunnlagPrStatus().stream() + .mapToLong(bga -> bga.getAndelNr() != null + ? bga.getAndelNr() + : bga.getArbeidsforhold().stream().mapToLong(BeregningsgrunnlagPrArbeidsforhold::getAndelNr).max().orElse(0L)) + .max() + .orElse(0L); + } + + +}