Skip to content

Commit 10b1e81

Browse files
committed
Merge branch 'master' into feature/react-compiler-migration
2 parents 244c681 + c06bbd9 commit 10b1e81

33 files changed

Lines changed: 534 additions & 19 deletions

File tree

apps/dolly-backend/config.test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ spec:
4646
- application: testnav-tps-messaging-service
4747
- application: testnav-yrkesskade-proxy
4848
- application: testnorge-profil-api-dev
49+
- application: etterlatte-testdata
50+
namespace: etterlatte
4951
external:
5052
- host: testnav-arena-forvalteren-proxy.dev-fss-pub.nais.io
5153
- host: testnav-brregstub-proxy.dev-fss-pub.nais.io

apps/dolly-backend/config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ spec:
4545
- application: testnav-tps-messaging-service
4646
- application: testnav-yrkesskade-proxy
4747
- application: testnorge-profil-api
48+
- application: etterlatte-testdata
49+
namespace: etterlatte
4850
external:
4951
- host: testnav-arena-forvalteren-proxy.dev-fss-pub.nais.io
5052
- host: testnav-brregstub-proxy.dev-fss-pub.nais.io
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package no.nav.dolly.bestilling.etterlatte;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import ma.glasnost.orika.MapperFacade;
6+
import no.nav.dolly.bestilling.ClientFuture;
7+
import no.nav.dolly.bestilling.ClientRegister;
8+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakRequestDTO;
9+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakResponseDTO;
10+
import no.nav.dolly.bestilling.personservice.PersonServiceConsumer;
11+
import no.nav.dolly.domain.PdlPerson;
12+
import no.nav.dolly.domain.PdlPersonBolk;
13+
import no.nav.dolly.domain.jpa.BestillingProgress;
14+
import no.nav.dolly.domain.resultset.RsDollyUtvidetBestilling;
15+
import no.nav.dolly.domain.resultset.dolly.DollyPerson;
16+
import no.nav.dolly.mapper.MappingContextUtils;
17+
import no.nav.dolly.util.FoedselsdatoUtility;
18+
import no.nav.dolly.util.TransactionHelperService;
19+
import org.springframework.stereotype.Service;
20+
import reactor.core.publisher.Flux;
21+
import reactor.core.publisher.Mono;
22+
23+
import java.util.Collection;
24+
import java.util.HashMap;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.Objects;
28+
import java.util.function.Function;
29+
import java.util.stream.Stream;
30+
31+
import static no.nav.dolly.errorhandling.ErrorStatusDecoder.encodeStatus;
32+
import static org.apache.commons.lang3.BooleanUtils.isTrue;
33+
import static org.apache.poi.util.StringUtil.isBlank;
34+
35+
@Slf4j
36+
@Service
37+
@RequiredArgsConstructor
38+
public class EtterlatteClient implements ClientRegister {
39+
40+
private static final String OKAY = "OK";
41+
42+
private final TransactionHelperService transactionHelperService;
43+
private final EtterlatteConsumer etterlatteConsumer;
44+
private final PersonServiceConsumer personServiceConsumer;
45+
private final MapperFacade mapperFacade;
46+
47+
@Override
48+
public Flux<ClientFuture> gjenopprett(RsDollyUtvidetBestilling bestilling, DollyPerson dollyPerson, BestillingProgress progress, boolean isOpprettEndre) {
49+
50+
if (!bestilling.getEtterlatteYtelser().isEmpty()) {
51+
52+
return Flux.from(getPersoner(dollyPerson.getIdent())
53+
.flatMapMany(vedtakRequestDTO -> Flux.fromIterable(bestilling.getEtterlatteYtelser())
54+
.flatMap(etterlattYtelse -> {
55+
var context = MappingContextUtils.getMappingContext();
56+
context.setProperty("etterlattYtelse", etterlattYtelse);
57+
var nyVedtakRequest = mapperFacade.map(vedtakRequestDTO, VedtakRequestDTO.class, context);
58+
return etterlatteConsumer.opprettVedtak(nyVedtakRequest)
59+
.map(EtterlatteClient::decodeResponse);
60+
})
61+
)
62+
.collectList()
63+
.map(statusList -> statusList.stream()
64+
.filter(status -> !OKAY.equals(status))
65+
.findFirst().orElse(OKAY))
66+
.map(status -> futurePersist(progress, status)));
67+
}
68+
return Flux.empty();
69+
}
70+
71+
@Override
72+
public void release(List<String> identer) {
73+
74+
// Etterlatte tilbyr pt ikke sletting
75+
}
76+
77+
private ClientFuture futurePersist(BestillingProgress progress, String status) {
78+
79+
return () -> {
80+
transactionHelperService.persister(progress, BestillingProgress::setEtterlatteStatus, status);
81+
return progress;
82+
};
83+
}
84+
85+
private static String decodeResponse(VedtakResponseDTO response) {
86+
87+
return response.getStatus().is2xxSuccessful() ? OKAY :
88+
"Feil= %s%s".formatted(response.getStatus(), getMessage(response));
89+
}
90+
91+
private static String getMessage(VedtakResponseDTO response) {
92+
93+
return isBlank(response.getMessage()) ? "" :
94+
"= %s".formatted(encodeStatus(response.getMessage()));
95+
}
96+
97+
private Mono<VedtakRequestDTO> getPersoner(String ident) {
98+
99+
return personServiceConsumer.getPdlPersoner(List.of(ident))
100+
.map(PdlPersonBolk::getData)
101+
.map(PdlPersonBolk.Data::getHentPersonBolk)
102+
.flatMap(Flux::fromIterable)
103+
.flatMap(personBolk -> personServiceConsumer.getPdlPersoner(
104+
Stream.of(Stream.of(ident),
105+
personBolk.getPerson().getForelderBarnRelasjon().stream()
106+
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
107+
.filter(Objects::nonNull),
108+
personBolk.getPerson().getSivilstand().stream()
109+
.filter(sivilstand -> sivilstand.isGift() || sivilstand.isGjenlevende())
110+
.map(PdlPerson.Sivilstand::getRelatertVedSivilstand)
111+
.filter(Objects::nonNull)
112+
)
113+
.flatMap(Function.identity())
114+
.distinct()
115+
.toList()))
116+
.map(PdlPersonBolk::getData)
117+
.map(PdlPersonBolk.Data::getHentPersonBolk)
118+
.flatMap(Flux::fromIterable)
119+
.map(personBolk -> Map.of(personBolk.getIdent(), personBolk))
120+
.reduce(new HashMap<String, PdlPersonBolk.PersonBolk>(), (map, element) -> {
121+
map.putAll(element);
122+
return map;
123+
})
124+
.flatMap(personer -> {
125+
if (isTrue(FoedselsdatoUtility.isMyndig(personer.get(ident)))) {
126+
return Mono.just(VedtakRequestDTO.builder()
127+
.barn(personer.get(ident).getPerson().getForelderBarnRelasjon().stream()
128+
.filter(PdlPerson.ForelderBarnRelasjon::isBarn)
129+
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
130+
.distinct()
131+
.toList())
132+
.avdoed(getForelderFraForelder(personer, ident, bolk -> !bolk.getPerson().getDoedsfall().isEmpty()))
133+
.gjenlevende(getForelderFraForelder(personer, ident, bolk -> bolk.getPerson().getDoedsfall().isEmpty()))
134+
.build());
135+
} else {
136+
return Mono.just(VedtakRequestDTO.builder()
137+
.barn(List.of(personer.get(ident).getIdent()))
138+
.gjenlevende(getForlderfraBarn(personer, ident,
139+
bolk -> bolk.getPerson().getDoedsfall().isEmpty()))
140+
.avdoed(getForlderfraBarn(personer, ident, bolk -> !bolk.getPerson().getDoedsfall().isEmpty()))
141+
.build());
142+
}
143+
});
144+
}
145+
146+
private static String getForlderfraBarn(HashMap<String, PdlPersonBolk.PersonBolk> personer, String ident, Gjenlevende gjenlevende) {
147+
return personer.get(ident).getPerson().getForelderBarnRelasjon().stream()
148+
.filter(PdlPerson.ForelderBarnRelasjon::isForelder)
149+
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
150+
.map(personer::get)
151+
.filter(gjenlevende::apply)
152+
.map(PdlPersonBolk.PersonBolk::getIdent)
153+
.findFirst().orElse(null);
154+
}
155+
156+
private static String getForelderFraForelder(HashMap<String, PdlPersonBolk.PersonBolk> personer, String ident, Gjenlevende gjenlevende) {
157+
158+
return personer.get(ident).getPerson().getForelderBarnRelasjon().stream()
159+
.filter(PdlPerson.ForelderBarnRelasjon::isBarn)
160+
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
161+
.map(personer::get)
162+
.map(PdlPersonBolk.PersonBolk::getPerson)
163+
.map(PdlPerson.Person::getForelderBarnRelasjon)
164+
.flatMap(Collection::stream)
165+
.filter(PdlPerson.ForelderBarnRelasjon::isForelder)
166+
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
167+
.map(personer::get)
168+
.filter(gjenlevende::apply)
169+
.map(PdlPersonBolk.PersonBolk::getIdent)
170+
.findFirst().orElse(null);
171+
}
172+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package no.nav.dolly.bestilling.etterlatte;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import no.nav.dolly.bestilling.etterlatte.command.EtterlattePostCommand;
5+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakRequestDTO;
6+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakResponseDTO;
7+
import no.nav.dolly.config.Consumers;
8+
import no.nav.dolly.metrics.Timed;
9+
import no.nav.testnav.libs.reactivecore.logging.WebClientLogger;
10+
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
11+
import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.web.reactive.function.client.WebClient;
14+
import reactor.core.publisher.Mono;
15+
16+
@Slf4j
17+
@Service
18+
public class EtterlatteConsumer {
19+
20+
private final WebClient webClient;
21+
private final TokenExchange tokenService;
22+
private final ServerProperties serverProperties;
23+
24+
public EtterlatteConsumer(
25+
TokenExchange tokenService,
26+
Consumers consumers,
27+
WebClient webClient,
28+
WebClientLogger webClientLogger) {
29+
this.tokenService = tokenService;
30+
this.serverProperties = consumers.getEtterlatte();
31+
var webClientBuilder = webClient
32+
.mutate();
33+
webClientLogger.customize(webClientBuilder);
34+
this.webClient = webClientBuilder
35+
.baseUrl(serverProperties.getUrl())
36+
.build();
37+
}
38+
39+
@Timed(name = "providers", tags = {"operation", "etterlatte_createData"})
40+
public Mono<VedtakResponseDTO> opprettVedtak(VedtakRequestDTO vedtakRequest) {
41+
42+
log.info("Etterlatte opprett {}", vedtakRequest);
43+
return tokenService.exchange(serverProperties)
44+
.flatMap(token -> new EtterlattePostCommand(webClient, vedtakRequest, token.getTokenValue()).call());
45+
}
46+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package no.nav.dolly.bestilling.etterlatte;
2+
3+
import no.nav.dolly.domain.PdlPersonBolk;
4+
5+
import java.util.function.Function;
6+
7+
@FunctionalInterface
8+
public interface Gjenlevende extends Function<PdlPersonBolk.PersonBolk, Boolean> {
9+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package no.nav.dolly.bestilling.etterlatte.command;
2+
3+
import co.elastic.clients.util.ContentType;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakRequestDTO;
7+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakResponseDTO;
8+
import no.nav.testnav.libs.reactivecore.web.WebClientError;
9+
import no.nav.testnav.libs.reactivecore.web.WebClientHeader;
10+
import org.springframework.web.reactive.function.client.WebClient;
11+
import reactor.core.publisher.Mono;
12+
13+
import java.util.concurrent.Callable;
14+
15+
import static no.nav.dolly.util.TokenXUtil.getUserJwt;
16+
import static org.apache.http.HttpHeaders.ACCEPT_ENCODING;
17+
18+
@Slf4j
19+
@RequiredArgsConstructor
20+
public class EtterlattePostCommand implements Callable<Mono<VedtakResponseDTO>> {
21+
22+
private static final String VEDTAK_URL = "/dolly/api/v1/opprett-ytelse";
23+
24+
private final WebClient webClient;
25+
private final VedtakRequestDTO vedtakRequest;
26+
private final String token;
27+
28+
@Override
29+
public Mono<VedtakResponseDTO> call() {
30+
31+
return webClient
32+
.post()
33+
.uri(uriBuilder -> uriBuilder.path(VEDTAK_URL).build())
34+
.header(ACCEPT_ENCODING, ContentType.APPLICATION_JSON)
35+
.headers(WebClientHeader.bearer(token))
36+
.headers(WebClientHeader.jwt(getUserJwt()))
37+
.bodyValue(vedtakRequest)
38+
.retrieve()
39+
.bodyToMono(VedtakResponseDTO.class)
40+
.retryWhen(WebClientError.is5xxException())
41+
.doOnError(WebClientError.logTo(log))
42+
.onErrorResume(throwable -> VedtakResponseDTO.of(WebClientError.describe(throwable)));
43+
}
44+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package no.nav.dolly.bestilling.etterlatte.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
import no.nav.dolly.domain.resultset.etterlatte.EtterlatteYtelse;
8+
9+
import java.util.List;
10+
11+
@Data
12+
@Builder
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
public class VedtakRequestDTO {
16+
17+
private EtterlatteYtelse.YtelseType type;
18+
private String avdoed;
19+
private String gjenlevende;
20+
private List<String> barn;
21+
private String soeker;
22+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package no.nav.dolly.bestilling.etterlatte.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
import no.nav.testnav.libs.reactivecore.web.WebClientError;
8+
import org.springframework.http.HttpStatus;
9+
import reactor.core.publisher.Mono;
10+
11+
@Data
12+
@Builder
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
public class VedtakResponseDTO {
16+
17+
private HttpStatus status;
18+
private String message;
19+
20+
public static Mono<VedtakResponseDTO> of(WebClientError.Description description) {
21+
22+
return Mono.just(VedtakResponseDTO
23+
.builder()
24+
.status(description.getStatus())
25+
.message(description.getMessage())
26+
.build());
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package no.nav.dolly.bestilling.etterlatte.mapper;
2+
3+
import ma.glasnost.orika.CustomMapper;
4+
import ma.glasnost.orika.MapperFactory;
5+
import ma.glasnost.orika.MappingContext;
6+
import no.nav.dolly.bestilling.etterlatte.dto.VedtakRequestDTO;
7+
import no.nav.dolly.domain.resultset.etterlatte.EtterlatteYtelse;
8+
import no.nav.dolly.mapper.MappingStrategy;
9+
import org.springframework.stereotype.Component;
10+
11+
@Component
12+
public class EtterlatteVedtakMappingStrategy implements MappingStrategy {
13+
14+
@Override
15+
public void register(MapperFactory factory) {
16+
factory.classMap(VedtakRequestDTO.class, VedtakRequestDTO.class)
17+
.customize(new CustomMapper<>() {
18+
@Override
19+
public void mapAtoB(VedtakRequestDTO kilde, VedtakRequestDTO destinasjon, MappingContext context) {
20+
21+
var etterlatteYtelse = (EtterlatteYtelse) context.getProperty("etterlattYtelse");
22+
destinasjon.setType(etterlatteYtelse.getYtelse());
23+
destinasjon.setSoeker(etterlatteYtelse.getSoeker());
24+
}
25+
})
26+
.byDefault()
27+
.register();
28+
}
29+
}

apps/dolly-backend/src/main/java/no/nav/dolly/config/Consumers.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ public class Consumers {
4848
private ServerProperties arbeidssoekerregisteretProxy;
4949
private ServerProperties brukerService;
5050
private ServerProperties safProxy;
51+
private ServerProperties etterlatte;
5152
}

0 commit comments

Comments
 (0)