Skip to content

Commit de0be60

Browse files
authored
TFP-5818: rydding i kobling. Bruker kobling aktiv flagg for skriv beskytelse. (#2609)
* feat: legger inn en avsluttet kolonne i databasen. * Refaktorering av kobling delen. Forenkling. * review: lagt inn validering ved lagring av kobling. Bump felles og bom.
1 parent b6a8d2a commit de0be60

File tree

14 files changed

+90
-159
lines changed

14 files changed

+90
-159
lines changed

domenetjenester/iay/src/main/java/no/nav/foreldrepenger/abakus/iay/tjeneste/InntektsmeldingerRestTjeneste.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,14 @@ public Response hentRefusjonskravDatoForSak(@NotNull @Valid InntektsmeldingerReq
111111
var aktørId = new AktørId(spesifikasjon.getPerson().getIdent());
112112
var saksnummer = new Saksnummer(spesifikasjon.getSaksnummer());
113113
var ytelseType = spesifikasjon.getYtelseType();
114-
var inntektsmeldinger = iayTjeneste.hentAlleInntektsmeldingerFor(aktørId, saksnummer, ytelseType);
115114
var kobling = koblingTjeneste.hentSisteFor(aktørId, saksnummer, ytelseType);
116115
if (kobling.isEmpty()) {
117116
response = Response.ok(new InntektsmeldingerDto().medInntektsmeldinger(Collections.emptyList())).build();
118117
} else {
119118
LoggUtil.setupLogMdc(spesifikasjon.getYtelseType(), spesifikasjon.getSaksnummer(), kobling.get().getKoblingReferanse().asString());
120-
InntektArbeidYtelseGrunnlag nyesteGrunnlag = iayTjeneste.hentAggregat(kobling.get().getKoblingReferanse());
121-
RefusjonskravDatoerDto refusjonskravDatoerDto = MapInntektsmeldinger.mapRefusjonskravdatoer(inntektsmeldinger, nyesteGrunnlag);
119+
var inntektsmeldinger = iayTjeneste.hentAlleInntektsmeldingerFor(aktørId, saksnummer, ytelseType);
120+
var nyesteGrunnlag = iayTjeneste.hentAggregat(kobling.get().getKoblingReferanse());
121+
var refusjonskravDatoerDto = MapInntektsmeldinger.mapRefusjonskravdatoer(inntektsmeldinger, nyesteGrunnlag);
122122
response = Response.ok(refusjonskravDatoerDto).build();
123123
}
124124
return response;

domenetjenester/iay/src/main/java/no/nav/foreldrepenger/abakus/registerdata/RegisterdataInnhentingTask.java

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class RegisterdataInnhentingTask extends KoblingTask {
3333
private IAYRegisterInnhentingTjeneste innhentTjeneste;
3434

3535
RegisterdataInnhentingTask() {
36+
// CDI proxy
3637
}
3738

3839
@Inject

domenetjenester/kobling/src/main/java/no/nav/foreldrepenger/abakus/kobling/Kobling.java

+14-21
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import java.time.LocalDate;
44
import java.util.Objects;
5-
import java.util.Set;
5+
6+
import org.hibernate.annotations.NaturalId;
67

78
import jakarta.persistence.AttributeOverride;
8-
import jakarta.persistence.AttributeOverrides;
99
import jakarta.persistence.Column;
1010
import jakarta.persistence.Convert;
1111
import jakarta.persistence.Embedded;
@@ -15,10 +15,6 @@
1515
import jakarta.persistence.Id;
1616
import jakarta.persistence.Table;
1717
import jakarta.persistence.Version;
18-
19-
import org.hibernate.annotations.NaturalId;
20-
21-
import no.nav.abakus.iaygrunnlag.kodeverk.Fagsystem;
2218
import no.nav.abakus.iaygrunnlag.kodeverk.IndexKey;
2319
import no.nav.abakus.iaygrunnlag.kodeverk.YtelseType;
2420
import no.nav.foreldrepenger.abakus.felles.diff.ChangeTracked;
@@ -42,46 +38,48 @@ public class Kobling extends BaseEntitet implements IndexKey {
4238
* Saksnummer (gruppererer alle koblinger under samme saksnummer - typisk generert av FPSAK, eller annet saksbehandlingsystem)
4339
*/
4440
@Embedded
45-
@AttributeOverrides(@AttributeOverride(name = "saksnummer", column = @Column(name = "saksnummer")))
41+
@AttributeOverride(name = "saksnummer", column = @Column(name = "saksnummer"))
4642
private Saksnummer saksnummer;
4743

4844
/**
4945
* Ekstern Referanse (eks. behandlingUuid).
5046
*/
5147
@NaturalId
5248
@Embedded
53-
@AttributeOverrides({@AttributeOverride(name = "referanse", column = @Column(name = "kobling_referanse", updatable = false, unique = true))})
49+
@AttributeOverride(name = "referanse", column = @Column(name = "kobling_referanse", updatable = false, unique = true))
5450
private KoblingReferanse koblingReferanse;
5551

5652
@Convert(converter = YtelseTypeKodeverdiConverter.class)
5753
@Column(name = "ytelse_type", nullable = false)
5854
private YtelseType ytelseType = YtelseType.UDEFINERT;
5955

6056
@Embedded
61-
@AttributeOverrides(@AttributeOverride(name = "aktørId", column = @Column(name = "bruker_aktoer_id", nullable = false, updatable = false)))
57+
@AttributeOverride(name = "aktørId", column = @Column(name = "bruker_aktoer_id", nullable = false, updatable = false))
6258
private AktørId aktørId;
6359

6460
@Embedded
6561
@ChangeTracked
66-
@AttributeOverrides({@AttributeOverride(name = "fomDato", column = @Column(name = "opplysning_periode_fom")), @AttributeOverride(name = "tomDato", column = @Column(name = "opplysning_periode_tom"))})
62+
@AttributeOverride(name = "fomDato", column = @Column(name = "opplysning_periode_fom"))
63+
@AttributeOverride(name = "tomDato", column = @Column(name = "opplysning_periode_tom"))
6764
private IntervallEntitet opplysningsperiode;
6865

6966
@Embedded
7067
@ChangeTracked
71-
@AttributeOverrides({@AttributeOverride(name = "fomDato", column = @Column(name = "opplysning_periode_skattegrunnlag_fom")), @AttributeOverride(name = "tomDato", column = @Column(name = "opplysning_periode_skattegrunnlag_tom"))})
68+
@AttributeOverride(name = "fomDato", column = @Column(name = "opplysning_periode_skattegrunnlag_fom"))
69+
@AttributeOverride(name = "tomDato", column = @Column(name = "opplysning_periode_skattegrunnlag_tom"))
7270
private IntervallEntitet opplysningsperiodeSkattegrunnlag;
7371

72+
@Embedded
73+
@AttributeOverride(name = "fomDato", column = @Column(name = "opptjening_periode_fom"))
74+
@AttributeOverride(name = "tomDato", column = @Column(name = "opptjening_periode_tom"))
75+
private IntervallEntitet opptjeningsperiode;
7476

7577
/**
76-
* inaktive koblinger skal ikke brukes. må filtreres vekk.
78+
* Inaktive koblinger skal ikke kunne endres. Det betyr oftest at koblingsreferansen er avsluttet i fagsystemet også.
7779
*/
7880
@Column(name = "aktiv", nullable = false)
7981
private Boolean aktiv = true;
8082

81-
@Embedded
82-
@AttributeOverrides({@AttributeOverride(name = "fomDato", column = @Column(name = "opptjening_periode_fom")), @AttributeOverride(name = "tomDato", column = @Column(name = "opptjening_periode_tom"))})
83-
private IntervallEntitet opptjeningsperiode;
84-
8583
@Version
8684
@Column(name = "versjon", nullable = false)
8785
private long versjon;
@@ -96,11 +94,6 @@ public Kobling(YtelseType ytelseType, Saksnummer saksnummer, KoblingReferanse ko
9694
this.ytelseType = ytelseType == null ? YtelseType.UDEFINERT : ytelseType;
9795
}
9896

99-
public static Fagsystem gjelderFagsystem(Kobling k) {
100-
return Set.of(YtelseType.ENGANGSTØNAD, YtelseType.FORELDREPENGER, YtelseType.SVANGERSKAPSPENGER)
101-
.contains(k.getYtelseType()) ? Fagsystem.FPSAK : Fagsystem.K9SAK;
102-
}
103-
10497
@Override
10598
public String getIndexKey() {
10699
return String.valueOf(koblingReferanse);
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,3 @@
11
package no.nav.foreldrepenger.abakus.kobling;
22

3-
import java.util.Objects;
4-
5-
public class KoblingLås {
6-
/**
7-
* brukes kun for nye behandlinger som dummy.
8-
*/
9-
private Long koblingId;
10-
11-
/**
12-
* protected, unngå å opprette utenfor denne pakken. Kan overstyres kun til test
13-
*/
14-
public KoblingLås(Long koblingId) {
15-
this.koblingId = koblingId;
16-
}
17-
18-
public Long getKoblingId() {
19-
return this.koblingId;
20-
}
21-
22-
void setKoblingId(long koblingId) {
23-
if (this.koblingId != null && !Objects.equals(koblingId, this.koblingId)) {
24-
throw new IllegalStateException("Kan ikke endre koblingId til annen verdi, var [" +
25-
this.koblingId + "], forsøkte å sette til [" +
26-
koblingId + "]");
27-
}
28-
this.koblingId = koblingId;
29-
}
30-
31-
@Override
32-
public boolean equals(Object obj) {
33-
if (obj == this) {
34-
return true;
35-
} else if (!(obj instanceof KoblingLås)) {
36-
return false;
37-
}
38-
KoblingLås other = (KoblingLås) obj;
39-
return Objects.equals(getKoblingId(), other.getKoblingId());
40-
}
41-
42-
@Override
43-
public int hashCode() {
44-
return Objects.hash(getKoblingId());
45-
}
46-
47-
@Override
48-
public String toString() {
49-
return getClass().getSimpleName() + "<koblingId=" + getKoblingId() +
50-
">";
51-
}
52-
}
3+
public record KoblingLås(Long koblingId) {}

domenetjenester/kobling/src/main/java/no/nav/foreldrepenger/abakus/kobling/KoblingTask.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@ public abstract class KoblingTask implements ProsessTaskHandler {
1111

1212
private LåsRepository låsRepository;
1313

14-
public KoblingTask() {
14+
protected KoblingTask() {
15+
// CDI proxy
1516
}
1617

17-
public KoblingTask(LåsRepository låsRepository) {
18+
protected KoblingTask(LåsRepository låsRepository) {
1819
this.låsRepository = låsRepository;
1920
}
2021

2122
@Override
2223
public void doTask(ProsessTaskData prosessTaskData) {
23-
String nyKoblingId = prosessTaskData.getPropertyValue(TaskConstants.KOBLING_ID);
24-
Long koblingId = nyKoblingId != null ? Long.valueOf(nyKoblingId) : Long.valueOf(prosessTaskData.getBehandlingId());
24+
var nyKoblingId = prosessTaskData.getPropertyValue(TaskConstants.KOBLING_ID);
25+
var koblingId = nyKoblingId != null ? Long.valueOf(nyKoblingId) : prosessTaskData.getBehandlingIdAsLong();
2526
LOG_CONTEXT.add("koblingId", koblingId);
2627

27-
KoblingLås koblingLås = låsRepository.taLås(koblingId);
28+
var koblingLås = låsRepository.taLås(koblingId);
2829

2930
prosesser(prosessTaskData);
3031

domenetjenester/kobling/src/main/java/no/nav/foreldrepenger/abakus/kobling/KoblingTjeneste.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package no.nav.foreldrepenger.abakus.kobling;
22

3-
import java.util.List;
43
import java.util.Optional;
54

65
import jakarta.enterprise.context.ApplicationScoped;
76
import jakarta.inject.Inject;
8-
97
import no.nav.abakus.iaygrunnlag.kodeverk.YtelseType;
108
import no.nav.foreldrepenger.abakus.kobling.repository.KoblingRepository;
119
import no.nav.foreldrepenger.abakus.kobling.repository.LåsRepository;
@@ -19,6 +17,7 @@ public class KoblingTjeneste {
1917
private LåsRepository låsRepository;
2018

2119
KoblingTjeneste() {
20+
// CDI proxy
2221
}
2322

2423
@Inject
@@ -58,7 +57,4 @@ public Kobling hent(Long koblingId) {
5857
låsRepository.oppdaterLåsVersjon(lås);
5958
}
6059

61-
public List<Saksnummer> hentAlleSaksnummer() {
62-
return repository.hentAlleSaksnummer();
63-
}
6460
}

domenetjenester/kobling/src/main/java/no/nav/foreldrepenger/abakus/kobling/repository/KoblingRepository.java

+29-26
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package no.nav.foreldrepenger.abakus.kobling.repository;
22

3-
import java.util.List;
43
import java.util.Objects;
54
import java.util.Optional;
65

6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
79
import jakarta.enterprise.context.ApplicationScoped;
810
import jakarta.inject.Inject;
911
import jakarta.persistence.EntityManager;
1012
import jakarta.persistence.LockModeType;
11-
import jakarta.persistence.TypedQuery;
12-
13-
import org.slf4j.Logger;
14-
import org.slf4j.LoggerFactory;
15-
1613
import no.nav.abakus.iaygrunnlag.kodeverk.Kodeverdi;
1714
import no.nav.abakus.iaygrunnlag.kodeverk.YtelseType;
1815
import no.nav.foreldrepenger.abakus.felles.diff.DiffEntity;
@@ -46,26 +43,26 @@ public Optional<Kobling> hentForKoblingReferanse(KoblingReferanse referanse) {
4643
}
4744

4845
public Optional<Kobling> hentForKoblingReferanse(KoblingReferanse referanse, boolean taSkriveLås) {
49-
TypedQuery<Kobling> query = entityManager.createQuery("FROM Kobling k WHERE koblingReferanse = :referanse", Kobling.class);
46+
var query = entityManager.createQuery("FROM Kobling k WHERE koblingReferanse = :referanse", Kobling.class);
5047
query.setParameter("referanse", referanse);
5148
if (taSkriveLås) {
5249
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
5350
}
5451
var k = HibernateVerktøy.hentUniktResultat(query);
55-
validerErAktiv(k);
56-
return k;
57-
}
58-
59-
private void validerErAktiv(Optional<Kobling> k) {
60-
if (k.isPresent() && !k.get().erAktiv()) {
61-
throw new IllegalStateException("Etterspør kobling: " + k.get().getKoblingReferanse() + ", men denne er ikke aktiv");
52+
if (taSkriveLås) {
53+
validerErAktiv(k);
6254
}
55+
return k;
6356
}
6457

6558
public Optional<Kobling> hentSisteKoblingReferanseFor(AktørId aktørId, Saksnummer saksnummer, YtelseType ytelseType) {
66-
TypedQuery<Kobling> query = entityManager.createQuery(
67-
"FROM Kobling k " + " WHERE k.saksnummer = :ref AND k.ytelseType = :ytelse and k.aktørId = :aktørId and k.aktiv=true" +
68-
" ORDER BY k.opprettetTidspunkt desc, k.id desc", Kobling.class);
59+
var query = entityManager.createQuery("""
60+
FROM Kobling k
61+
WHERE k.saksnummer = :ref
62+
AND k.ytelseType = :ytelse
63+
AND k.aktørId = :aktørId
64+
ORDER BY k.opprettetTidspunkt desc, k.id desc""", Kobling.class);
65+
6966
query.setParameter("ref", saksnummer);
7067
query.setParameter("ytelse", ytelseType);
7168
query.setParameter("aktørId", aktørId);
@@ -75,23 +72,33 @@ public Optional<Kobling> hentSisteKoblingReferanseFor(AktørId aktørId, Saksnum
7572
return k;
7673
}
7774

78-
public Optional<Long> hentKoblingIdForKoblingReferanse(KoblingReferanse referanse) {
79-
var k = hentForKoblingReferanse(referanse);
80-
return k.map(Kobling::getId);
75+
private void validerErAktiv(Optional<Kobling> kobling) {
76+
if (kobling.isPresent() && !kobling.get().erAktiv()) {
77+
throw new IllegalStateException("Etterspør kobling: " + kobling.get().getKoblingReferanse() + ", men denne er ikke aktiv");
78+
}
8179
}
8280

8381
public void lagre(Kobling nyKobling) {
84-
Optional<Kobling> eksisterendeKobling = hentForKoblingReferanse(nyKobling.getKoblingReferanse());
82+
var eksisterendeKobling = hentForKoblingReferanse(nyKobling.getKoblingReferanse());
8583

86-
DiffResult diff = getDiff(eksisterendeKobling.orElse(null), nyKobling);
84+
validerErAktiv(eksisterendeKobling);
85+
validerLikKoblingReferanse(nyKobling, eksisterendeKobling);
8786

87+
var diff = getDiff(eksisterendeKobling.orElse(null), nyKobling);
8888
if (!diff.isEmpty()) {
8989
LOG.info("Detekterte endringer på kobling med referanse={}, endringer={}", nyKobling.getId(), diff.getLeafDifferences());
9090
entityManager.persist(nyKobling);
9191
entityManager.flush();
9292
}
9393
}
9494

95+
private static void validerLikKoblingReferanse(Kobling nyKobling, Optional<Kobling> eksisterendeKobling) {
96+
var eksisterendeKoblingId = eksisterendeKobling.map(Kobling::getId).orElse(null);
97+
if (!Objects.equals(eksisterendeKoblingId, nyKobling.getId())) { // for nye koblinger bør både eksisterende og ny være null.
98+
throw new IllegalStateException("Utviklerfeil: Kan ikke lagre en ny kobling for eksisterende kobling referanse.");
99+
}
100+
}
101+
95102
private DiffResult getDiff(Kobling eksisterendeKobling, Kobling nyKobling) {
96103
var config = new TraverseJpaEntityGraphConfig();
97104
config.setIgnoreNulls(true);
@@ -107,8 +114,4 @@ public Kobling hentForKoblingId(Long koblingId) {
107114
return entityManager.find(Kobling.class, koblingId);
108115
}
109116

110-
public List<Saksnummer> hentAlleSaksnummer() {
111-
TypedQuery<Saksnummer> query = entityManager.createQuery("SELECT k.saksnummer FROM Kobling k", Saksnummer.class);
112-
return query.getResultList();
113-
}
114117
}

domenetjenester/kobling/src/main/java/no/nav/foreldrepenger/abakus/kobling/repository/LåsRepository.java

+13-27
Original file line numberDiff line numberDiff line change
@@ -30,41 +30,27 @@ public class LåsRepository {
3030
*/
3131
public KoblingLås taLås(Long koblingId) {
3232
if (koblingId != null) {
33-
final LockModeType lockModeType = LockModeType.PESSIMISTIC_WRITE;
34-
lås(koblingId, lockModeType);
35-
KoblingLås lås = new KoblingLås(koblingId);
36-
return lås;
37-
} else {
38-
return new KoblingLås(null);
33+
entityManager.createQuery("from Kobling k where k.id = :id and k.aktiv = true")
34+
.setParameter("id", koblingId)
35+
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
36+
.getSingleResult();
3937
}
40-
41-
}
42-
43-
private Long lås(final Long behandlingId, LockModeType lockModeType) {
44-
Object[] result = (Object[]) entityManager.createQuery("select k.id, k.versjon from Kobling k where k.id=:id and k.aktiv=true")
45-
.setParameter("id", behandlingId)
46-
.setLockMode(lockModeType).getSingleResult();
47-
return (Long) result[0];
38+
return new KoblingLås(koblingId);
4839
}
4940

5041
/**
5142
* Verifiser lås ved å sjekke mot underliggende lager.
5243
*/
5344
public void oppdaterLåsVersjon(KoblingLås lås) {
54-
if (lås.getKoblingId() != null) {
55-
verifisertLås(lås.getKoblingId());
56-
} // else NO-OP (for ny behandling uten id)
57-
}
58-
59-
private Object verifisertLås(Long id) {
60-
LockModeType lockMode = LockModeType.PESSIMISTIC_FORCE_INCREMENT;
61-
Object entity = entityManager.find(Kobling.class, id);
62-
if (entity == null) {
63-
throw new TekniskException("FP-131239", String.format("Fant ikke entitet for låsing [%s], id=%s.", Kobling.class.getSimpleName(), id));
64-
} else {
65-
entityManager.lock(entity, lockMode);
45+
if (lås.koblingId() != null) {
46+
var koblingId = lås.koblingId();
47+
var kobling = entityManager.find(Kobling.class, koblingId);
48+
if (kobling == null) {
49+
throw new TekniskException("FP-131239", String.format("Fant ikke entitet for låsing [%s], koblingId=%s.", Kobling.class.getSimpleName(), koblingId));
50+
} else {
51+
entityManager.lock(kobling, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
52+
}
6653
}
67-
return entity;
6854
}
6955

7056
}

0 commit comments

Comments
 (0)