Skip to content

Commit

Permalink
Grenseverdiregel tar ikkje hensyn til fordeling (#426)
Browse files Browse the repository at this point in the history
  • Loading branch information
espenjv authored Sep 6, 2023
1 parent 59c99a1 commit e2ba846
Show file tree
Hide file tree
Showing 10 changed files with 2,275 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<BigDecimal> getAktivitetsgrad() {
return Optional.ofNullable(aktivitetsgrad);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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<BeregningsgrunnlagPeriode> {
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<String, Object> 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<BeregningsgrunnlagPrArbeidsforhold> 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<BeregningsgrunnlagPrStatus> bgpsSorted = finnAlleBGUtenArbeidsForholdSorterte(grunnlag);
Iterator<BeregningsgrunnlagPrStatus> 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<BeregningsgrunnlagPrStatus> 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<String, Object> 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<String, Object> resultater) {
BeregningsgrunnlagPrStatus.builder(bgps).medAndelsmessigFørGraderingPrAar(avkortetBrukersAndel).build();
resultater.put("avkortetPrÅr.status." + bgps.getAktivitetStatus().name(), bgps.getAvkortetPrÅr());
}
}
Original file line number Diff line number Diff line change
@@ -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<BeregningsgrunnlagPeriode> {
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<BeregningsgrunnlagPrArbeidsforhold> arbeidsforholdene = grunnlag.getBeregningsgrunnlagPrStatus(AktivitetStatus.ATFL).getArbeidsforholdIkkeFrilans();
Map<String, Object> resultater = new HashMap<>();
resultat.setEvaluationProperties(resultater);
BigDecimal grenseverdi = grunnlag.getGrenseverdi();
resultater.put("grenseverdi", grenseverdi);
fastsettAndelerPrArbeidsforhold(arbeidsforholdene, resultater, grenseverdi);
return resultat;
}

private void fastsettAndelerPrArbeidsforhold(List<BeregningsgrunnlagPrArbeidsforhold> arbeidsforholdList, Map<String, Object> 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());
});
}
}
Original file line number Diff line number Diff line change
@@ -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<BeregningsgrunnlagPeriode> {
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<String, Object> 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;
}



}
Original file line number Diff line number Diff line change
@@ -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<BeregningsgrunnlagPeriode> {

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();

}

}
Loading

0 comments on commit e2ba846

Please sign in to comment.