Skip to content

Commit

Permalink
Feature/bestilling fra skattekort service (#3573)
Browse files Browse the repository at this point in the history
* Add new applications in config.yml
#deploy-skattekort-service

Updated the inbound rules in the skattekort-service config.yml to include additional applications: dolly-backend-dev, dolly-frontend-dev, and team-dolly-lokal-app. This allows better control and access for these new applications.

* Add skattekort support to bestilling

This update introduces skattekort processing in the bestilling service. New functionalities include mapping skattekort status, handling skattekort requests, and updating related configurations.

* Add skattekort error handling in bestilling
#deploy-test-dolly-backend

Enhance bestilling service to process skattekort errors. Modify the handling of skattekort statuses, returning detailed error reports when errors occur. Integrate new dependency imports and clean up deprecated code.

* Add null check for skattekort in bestilling
#deploy-test-dolly-backend

Enhanced bestilling service by filtering out null skattekort entries before processing. This prevents null pointers and ensures only valid skattekort data moves forward in the pipeline. Added necessary imports to support the new check.

* Add SkattekortRequestDTO and mapping strategy
#deploy-test-dolly-backend

Introduced SkattekortRequestDTO and integrated it into existing packages. Added a new mapping strategy to map DTO fields for skattekort service requests. This enhances the flexibility and extensibility of our code related to skattekort functionality.

* Add SkattekortRequestDTO and mapping strategy
#deploy-test-dolly-backend

Introduced SkattekortRequestDTO and integrated it into existing packages. Added a new mapping strategy to map DTO fields for skattekort service requests. This enhances the flexibility and extensibility of our code related to skattekort functionality.

* Rename Arbeidsgiver class to ArbeidsgiverSkatt
#deploy-skattekort-service #deploy-test-dolly-backend

Renamed the Arbeidsgiver class to ArbeidsgiverSkatt for clarity and improved domain specificity. Updated all occurrences and references in DTOs to reflect the change. This ensures consistency across the codebase and improves readability.

* Rename Arbeidsgiver to ArbeidsgiverSkatt
#deploy-skattekort-service

Replaced all occurrences of "Arbeidsgiver" with "ArbeidsgiverSkatt" in service, utility, and DTO classes. This change aligns the codebase with updated naming conventions and ensures consistency across different modules.
  • Loading branch information
krharum authored Aug 5, 2024
1 parent a68106e commit 02bb18a
Show file tree
Hide file tree
Showing 25 changed files with 380 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package no.nav.dolly.bestilling.skattekort;

import lombok.RequiredArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import no.nav.dolly.bestilling.ClientFuture;
import no.nav.dolly.bestilling.ClientRegister;
import no.nav.dolly.domain.jpa.BestillingProgress;
import no.nav.dolly.domain.resultset.RsDollyUtvidetBestilling;
import no.nav.dolly.domain.resultset.dolly.DollyPerson;
import no.nav.dolly.util.TransactionHelperService;
import no.nav.testnav.libs.dto.skattekortservice.v1.SkattekortRequestDTO;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.stream.Collectors;

import static java.util.Objects.nonNull;

@Service
@RequiredArgsConstructor
public class SkattekortClient implements ClientRegister {

private final SkattekortConsumer skattekortConsumer;
private final MapperFacade mapperFacade;
private final TransactionHelperService transactionHelperService;

@Override
public Flux<ClientFuture> gjenopprett(RsDollyUtvidetBestilling bestilling, DollyPerson dollyPerson,
BestillingProgress progress, boolean isOpprettEndre) {

return Flux.just(bestilling)
.filter(bestilling1 -> nonNull(bestilling1.getSkattekort()))
.map(bestilling1 -> mapperFacade.map(bestilling1.getSkattekort(), SkattekortRequestDTO.class))
.doOnNext(skattekort ->
skattekort.getArbeidsgiver()
.forEach(arbeidsgiver -> arbeidsgiver.getArbeidstaker()
.forEach(arbeidstaker -> arbeidstaker.setArbeidstakeridentifikator(dollyPerson.getIdent()))))
.flatMap(skattkort -> Flux.fromIterable(skattkort.getArbeidsgiver())
.map(arbeidsgiver -> SkattekortRequestDTO.builder()
.arbeidsgiver(List.of(arbeidsgiver))
.build())
.flatMap(skattekortConsumer::sendSkattekort)
.collect(Collectors.joining(",")))
.map(status -> futurePersist(progress, status));
}

private ClientFuture futurePersist(BestillingProgress progress, String status) {

return () -> {
transactionHelperService.persister(progress, BestillingProgress::setSkattekortStatus, status);
return progress;
};
}

@Override
public void release(List<String> identer) {
// Deletion is not yet supported
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package no.nav.dolly.bestilling.skattekort;

import no.nav.dolly.bestilling.skattekort.command.SkattekortPostCommand;
import no.nav.dolly.config.Consumers;
import no.nav.testnav.libs.dto.skattekortservice.v1.SkattekortRequestDTO;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

@Service
public class SkattekortConsumer {

private final WebClient webClient;
private final ServerProperties serverProperties;
private final TokenExchange tokenExchange;

public SkattekortConsumer(WebClient.Builder webClientBuilder, Consumers consumers, TokenExchange tokenExchange) {

this.serverProperties = consumers.getTestnavSkattekortService();
this.webClient = webClientBuilder
.baseUrl(serverProperties.getUrl())
.build();
this.tokenExchange = tokenExchange;
}

public Flux<String> sendSkattekort(SkattekortRequestDTO skattekortRequestDTO) {

return tokenExchange.exchange(serverProperties)
.flatMapMany(token -> new SkattekortPostCommand(webClient, skattekortRequestDTO, token.getTokenValue()).call());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package no.nav.dolly.bestilling.skattekort.command;

import lombok.RequiredArgsConstructor;
import no.nav.dolly.errorhandling.ErrorStatusDecoder;
import no.nav.dolly.util.RequestHeaderUtil;
import no.nav.testnav.libs.dto.skattekortservice.v1.IdentifikatorForEnhetEllerPerson;
import no.nav.testnav.libs.dto.skattekortservice.v1.SkattekortRequestDTO;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import no.nav.testnav.libs.securitycore.config.UserConstant;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

import java.time.Duration;
import java.util.concurrent.Callable;

import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CALL_ID;
import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID;
import static no.nav.dolly.util.TokenXUtil.getUserJwt;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RequiredArgsConstructor
public class SkattekortPostCommand implements Callable<Flux<String>> {

private static final String SKATTEKORT_URL = "/api/v1/skattekort";
private static final String CONSUMER = "Dolly";

private final WebClient webClient;
private final SkattekortRequestDTO request;
private final String token;

@Override
public Flux<String> call() {

return webClient.post().uri(uriBuilder -> uriBuilder
.path(SKATTEKORT_URL)
.build())
.header(ACCEPT, APPLICATION_JSON_VALUE)
.header(HEADER_NAV_CALL_ID, RequestHeaderUtil.getNavCallId())
.header(HEADER_NAV_CONSUMER_ID, CONSUMER)
.header(AUTHORIZATION, "Bearer " + token)
.header(UserConstant.USER_HEADER_JWT, getUserJwt())
.bodyValue(request)
.retrieve()
.bodyToFlux(String.class)
.map(status -> getArbeidsgiverAndYear(request) + ErrorStatusDecoder.encodeStatus(status))
.doOnError(WebClientFilter::logErrorMessage)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException))
.onErrorResume(throwable -> throwable instanceof WebClientResponseException.NotFound,
throwable -> Mono.empty());
}

private static String getArbeidsgiverAndYear(SkattekortRequestDTO skattekort) {

return skattekort.getArbeidsgiver().stream()
.findFirst()
.map(arbeidsgiver -> String.format("%s+%s:",
getArbeidsgiver(arbeidsgiver.getArbeidsgiveridentifikator()),
arbeidsgiver.getArbeidstaker().stream()
.findFirst()
.map(arbeidstaker -> arbeidstaker.getInntektsaar().toString())
.orElse("inntektsår")))
.orElse("organisasjonsnummer+inntektsår:");
}

private static String getArbeidsgiver(IdentifikatorForEnhetEllerPerson identifikator) {

return isNotBlank(identifikator.getOrganisasjonsnummer()) ?
identifikator.getOrganisasjonsnummer() :
identifikator.getPersonidentifikator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package no.nav.dolly.bestilling.skattekort.mapper;

import ma.glasnost.orika.MapperFactory;
import no.nav.dolly.domain.resultset.skattekort.SkattekortRequestDTO;
import no.nav.dolly.mapper.MappingStrategy;
import org.springframework.stereotype.Component;

@Component
public class SkattekortMappingStrategy implements MappingStrategy {

@Override
public void register(MapperFactory factory) {
factory.classMap(SkattekortRequestDTO.class, no.nav.testnav.libs.dto.skattekortservice.v1.SkattekortRequestDTO.class)
.mapNulls(false)
.field("arbeidsgiverSkatt", "arbeidsgiver")
.register();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ public class Consumers {
private ServerProperties testnavSyntSykemeldingApi;
private ServerProperties testnavTpsMessagingService;
private ServerProperties testnavUdistubProxy;
private ServerProperties testnavSkattekortService;
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ public class BestillingProgress implements Serializable {
@Column(name = "ARBEIDSPLASSENCV_STATUS")
private String arbeidsplassenCVStatus;

@Column(name = "SKATTEKORT_STATUS")
private String skattekortStatus;

@Column(name = "master")
@Enumerated(EnumType.STRING)
private Master master;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import no.nav.dolly.domain.resultset.pensjon.PensjonData;
import no.nav.dolly.domain.resultset.sigrunstub.RsLignetInntekt;
import no.nav.dolly.domain.resultset.sigrunstub.RsPensjonsgivendeForFolketrygden;
import no.nav.dolly.domain.resultset.skattekort.SkattekortRequestDTO;
import no.nav.dolly.domain.resultset.skjerming.RsSkjerming;
import no.nav.dolly.domain.resultset.sykemelding.RsSykemelding;
import no.nav.dolly.domain.resultset.tpsmessagingservice.RsTpsMessaging;
Expand Down Expand Up @@ -59,4 +60,5 @@ public class BestilteKriterier {
private RsSkjerming skjerming;
private RsSykemelding sykemelding;
private ArbeidsplassenCVDTO arbeidsplassenCV;
private SkattekortRequestDTO skattekort;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import no.nav.dolly.domain.resultset.pensjon.PensjonData;
import no.nav.dolly.domain.resultset.sigrunstub.RsLignetInntekt;
import no.nav.dolly.domain.resultset.sigrunstub.RsPensjonsgivendeForFolketrygden;
import no.nav.dolly.domain.resultset.skattekort.SkattekortRequestDTO;
import no.nav.dolly.domain.resultset.skjerming.RsSkjerming;
import no.nav.dolly.domain.resultset.sykemelding.RsSykemelding;
import no.nav.dolly.domain.resultset.tpsmessagingservice.RsTpsMessaging;
Expand Down Expand Up @@ -75,6 +76,7 @@ public class RsDollyBestilling {
private BankkontoData bankkonto;
private RsSkjerming skjerming;
private ArbeidsplassenCVDTO arbeidsplassenCV;
private SkattekortRequestDTO skattekort;

public List<RsAareg> getAareg() {
if (isNull(aareg)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum SystemTyper {
SIGRUNSTUB("Skatteinntekt grunnlag (SIGRUN)"),
SIGRUN_LIGNET("Lignet skatteinntekt (Sigrunstub)"),
SIGRUN_PENSJONSGIVENDE("Pensjonsgivende inntekt (Sigrunstub)"),
SKATTEKORT("Skattekort (SOKOS)"),
SKJERMINGSREGISTER("Skjermingsregisteret"),
SYKEMELDING("NAV sykemelding"),
TPS_MESSAGING("Meldinger til TPS"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package no.nav.dolly.domain.resultset.skattekort;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import no.nav.testnav.libs.dto.skattekortservice.v1.ArbeidsgiverSkatt;

import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.isNull;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SkattekortRequestDTO {

private List<ArbeidsgiverSkatt> arbeidsgiverSkatt;

public List<ArbeidsgiverSkatt> getArbeidsgiverSkatt() {

if (isNull(arbeidsgiverSkatt)) {

arbeidsgiverSkatt = new ArrayList<>();
}
return arbeidsgiverSkatt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import no.nav.dolly.domain.resultset.sykemelding.RsSykemelding;
import no.nav.dolly.domain.resultset.udistub.model.RsUdiPerson;
import no.nav.testnav.libs.data.arbeidsplassencv.v1.ArbeidsplassenCVDTO;
import no.nav.testnav.libs.dto.skattekortservice.v1.SkattekortRequestDTO;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;
Expand Down Expand Up @@ -94,6 +95,8 @@ public boolean isNew() {
@Field
private ArbeidsplassenCVDTO arbeidsplassenCV;
@Field
private SkattekortRequestDTO skattekort;
@Field
private List<String> identer;

@Transient
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package no.nav.dolly.mapper;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import no.nav.dolly.domain.jpa.BestillingProgress;
import no.nav.dolly.domain.resultset.RsStatusRapport;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.util.Collections.emptyList;
import static no.nav.dolly.domain.resultset.SystemTyper.SKATTEKORT;
import static no.nav.dolly.mapper.AbstractRsStatusMiljoeIdentForhold.decodeMsg;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BestillingSkattekortStatusMapper {

public static List<RsStatusRapport> buildSkattekortStatusMap(List<BestillingProgress> progressList) {

// status org+year ident
Map<String, Map<String, Set<String>>> errorEnvIdents = new HashMap<>();

progressList.forEach(progress -> {
if (isNotBlank(progress.getSkattekortStatus()) && isNotBlank(progress.getIdent())) {
var entries = progress.getSkattekortStatus().split(",");
for (var entry : entries) {
var orgYear = entry.split(":")[0];
var status = entry.split(":")[1];
if (errorEnvIdents.containsKey(status)) {
if (errorEnvIdents.get(status).containsKey(orgYear)) {
errorEnvIdents.get(status).get(orgYear).add(progress.getIdent());
} else {
errorEnvIdents.get(status).put(orgYear, new HashSet<>(Set.of(progress.getIdent())));
}
} else {
errorEnvIdents.put(status, new HashMap<>(Map.of(orgYear, new HashSet<>(Set.of(progress.getIdent())))));
}
}
}
});

if (errorEnvIdents.isEmpty()) {
return emptyList();

} else {
if (errorEnvIdents.entrySet().stream()
.allMatch(entry -> entry.getKey().equals("Skattekort lagret"))) {

return errorEnvIdents.values().stream()
.map(entry -> RsStatusRapport.builder()
.id(SKATTEKORT)
.navn(SKATTEKORT.getBeskrivelse())
.statuser(List.of(RsStatusRapport.Status.builder()
.melding("OK")
.identer(entry.values().stream()
.map(orgYear -> orgYear.stream().toList())
.flatMap(Collection::stream)
.distinct()
.toList())
.build()))
.build())
.toList();

} else {

return errorEnvIdents.entrySet().stream()
.filter(entry -> !entry.getKey().equals("Skattekort lagret"))
.map(entry -> RsStatusRapport.builder()
.id(SKATTEKORT)
.navn(SKATTEKORT.getBeskrivelse())
.statuser(entry.getValue().entrySet().stream()
.map(orgYear -> RsStatusRapport.Status.builder()
.melding(formatMelding(orgYear.getKey(), entry.getKey()))
.identer(orgYear.getValue().stream().toList())
.build())
.toList())
.build())
.toList();
}
}
}

private static String formatMelding(String orgYear, String melding) {

return "FEIL: organisasjon:%s, inntektsår:%s, melding:%s".formatted(
orgYear.split("\\+")[0],
orgYear.split("\\+")[1],
decodeMsg(melding));
}
}
Loading

0 comments on commit 02bb18a

Please sign in to comment.