Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oppdatert funksjonalitet for adressedatoer #3725

Merged
merged 2 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
import no.nav.pdl.forvalter.exception.InvalidRequestException;
import no.nav.pdl.forvalter.utils.FoedselsdatoUtility;
import no.nav.testnav.libs.data.pdlforvalter.v1.AdresseDTO;
import no.nav.testnav.libs.data.pdlforvalter.v1.BostedadresseDTO;
import no.nav.testnav.libs.data.pdlforvalter.v1.PersonDTO;
import no.nav.testnav.libs.dto.generernavnservice.v1.NavnDTO;
import org.apache.commons.lang3.StringUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static no.nav.pdl.forvalter.utils.ArtifactUtils.getKilde;
import static no.nav.pdl.forvalter.utils.ArtifactUtils.getMaster;
import static no.nav.pdl.forvalter.utils.IdenttypeUtility.isNotNpidIdent;
import static no.nav.pdl.forvalter.utils.TestnorgeIdentUtility.isTestnorgeIdent;
import static org.apache.commons.lang3.BooleanUtils.isFalse;
Expand All @@ -33,6 +29,7 @@ public abstract class AdresseService<T extends AdresseDTO, R> implements BiValid
protected static final String VALIDATION_ADRESSE_OVELAP_ERROR = "Adresse: Overlappende adressedatoer er ikke lov";

private static final String NAVN_INVALID_ERROR = "CoAdresseNavn er ikke i liste over gyldige verdier";
private static final int OUT_OF_BOUND = -1;

private final GenererNavnServiceConsumer genererNavnServiceConsumer;

Expand All @@ -50,11 +47,6 @@ protected static void validateBruksenhet(String bruksenhet) {
}
}

private static LocalDateTime getDateOrFuture(LocalDateTime dateTime) {

return nonNull(dateTime) ? dateTime : LocalDateTime.now().plusYears(100);
}

protected void validateCoAdresseNavn(AdresseDTO.CoNavnDTO navn) {

if ((isNotBlank(navn.getFornavn()) ||
Expand Down Expand Up @@ -100,133 +92,75 @@ private String buildNavn(AdresseDTO.CoNavnDTO coNavn) {
.toString();
}

protected void populateMiscFields(AdresseDTO adresse, PersonDTO person) {

if (isNull(adresse.getGyldigFraOgMed())) {
adresse.setGyldigFraOgMed(person.getBostedsadresse().stream()
.reduce((a1, a2) -> a2)
.map(BostedadresseDTO::getGyldigFraOgMed)
.filter(Objects::nonNull)
.orElse(FoedselsdatoUtility.getFoedselsdato(person)));
}
protected void oppdaterAdressedatoer(List<? extends AdresseDTO> adresser, PersonDTO person) {

adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
}
if (!adresser.isEmpty()) {

protected void enforceIntegrity(List<T> adresser) {
if (isNull(adresser.getLast().getGyldigFraOgMed())) {
adresser.getLast().setGyldigFraOgMed(FoedselsdatoUtility.getFoedselsdato(person));
}

sortAdresser(adresser);
setPendingTilOgMedDato(adresser);
checkOverlappendeDatoer(adresser);
setPendingFromDato(adresser);
var startIndex = adresser.size() - 1;
setGyldigFromDato(adresser, startIndex);
setGyldigTomDato(adresser);
}
}

private void setPendingTilOgMedDato(List<T> adresser) {

for (var i = 0; i < adresser.size(); i++) {
private static void setGyldigTomDato(List<? extends AdresseDTO> adresser) {

if (i + 1 < adresser.size() &&
(isNull(adresser.get(i + 1).getGyldigTilOgMed()) &&
nonNull(adresser.get(i).getGyldigFraOgMed()) ||
adresser.get(i + 1).getGyldigTilOgMed()
.isAfter(adresser.get(i).getGyldigFraOgMed()))) {

if (adresser.get(i + 1).getGyldigFraOgMed().toLocalDate().isEqual(
adresser.get(i).getGyldigFraOgMed().toLocalDate())) {

var time = LocalDateTime.now();
adresser.get(i).setGyldigFraOgMed(adresser.get(i).getGyldigFraOgMed().toLocalDate()
.atTime(time.getHour(), time.getMinute(), time.getSecond()));
}

adresser.get(i + 1).setGyldigTilOgMed(getGyldigTilDato(adresser.get(i + 1), adresser.get(i)));
for (int i = adresser.size() - 1; i > 0; i--) {
if (isNull(adresser.get(i).getGyldigTilOgMed())) {
adresser.get(i).setGyldigTilOgMed(adresser.get(i - 1).getGyldigFraOgMed().minusDays(1));
}
}
}

private LocalDateTime getGyldigTilDato(AdresseDTO adresse1, AdresseDTO adresse2) {

if (adresse1.getGyldigFraOgMed().toLocalDate()
.isEqual(adresse2.getGyldigFraOgMed().toLocalDate()) ||
adresse1.getGyldigFraOgMed().toLocalDate()
.isEqual(adresse2.getGyldigFraOgMed().toLocalDate().minusDays(1))) {

var time = adresse2.getGyldigFraOgMed().minusSeconds(1);
return adresse2.getGyldigFraOgMed().toLocalDate()
.atTime(time.getHour(), time.getMinute(), time.getSecond());

} else if (adresse1.getGyldigFraOgMed().toLocalDate()
.isBefore(adresse2.getGyldigFraOgMed().toLocalDate())) {

return adresse2.getGyldigFraOgMed().minusDays(1).toLocalDate().atStartOfDay();
private static void setPendingFromDato(List<? extends AdresseDTO> adresser) {

} else {

throw new InvalidRequestException(VALIDATION_ADRESSE_OVELAP_ERROR);
}
}

private void checkOverlappendeDatoer(List<T> adresser) {

// https://stackoverflow.com/questions/13513932/algorithm-to-detect-overlapping-periods
for (var i = 0; i < adresser.size(); i++) {
for (var j = 0; j < adresser.size(); j++) {
if (i != j &&
(adresser.get(i).getGyldigFraOgMed()
.isEqual(adresser.get(j).getGyldigFraOgMed()) ||
getDateOrFuture(adresser.get(i).getGyldigTilOgMed())
.isEqual(getDateOrFuture(adresser.get(j).getGyldigTilOgMed())) ||
isAdresseOverlapp(adresser.get(i), adresser.get(j)))) {
throw new InvalidRequestException(VALIDATION_ADRESSE_OVELAP_ERROR);
}
for (int i = adresser.size() - 1; i > 0; i--) {
if (isNull(adresser.get(i - 1).getGyldigFraOgMed()) && nonNull(adresser.get(i).getGyldigTilOgMed())) {
adresser.get(i - 1).setGyldigFraOgMed(adresser.get(i).getGyldigTilOgMed().plusDays(1));
}
}
}

private boolean isAdresseOverlapp(T adresse1, T adresse2) {

return isOverlappTilfelle1(adresse1, adresse2) ||
isOverlappTilfelle2(adresse1, adresse2) ||
isOverlappTilfelle3(adresse1, adresse2);
}

private boolean isOverlappTilfelle1(T adresse1, T adresse2) {
private static void setGyldigFromDato(List<? extends AdresseDTO> adresser, int startIndex) {

// |<---- Intervall A ----->|
// |<---- Intervall B ----->|
return getDateOrFuture(adresse1.getGyldigFraOgMed()).isBefore(adresse2.getGyldigFraOgMed()) &&
adresse2.getGyldigFraOgMed().isBefore(getDateOrFuture(adresse1.getGyldigTilOgMed()));
if (startIndex == OUT_OF_BOUND) {
return;
}
var lowWaterMark = getIndexOfNextFromDate(adresser, startIndex);
var daysInterval = getWeightedDaysInterval(adresser, startIndex, lowWaterMark);
for (int i = startIndex - 1; i > lowWaterMark; i--) {
adresser.get(i).setGyldigFraOgMed(adresser.get(i + 1).getGyldigFraOgMed().plusDays(daysInterval));
}
setGyldigFromDato(adresser, lowWaterMark);
}

private boolean isOverlappTilfelle2(T adresse1, T adresse2) {

// |<---- Intervall A ----->|
// |<---- Intervall B ----->|
return adresse1.getGyldigFraOgMed().isBefore(getDateOrFuture(adresse2.getGyldigTilOgMed())) &&
getDateOrFuture(adresse2.getGyldigTilOgMed()).isBefore(getDateOrFuture(adresse1.getGyldigTilOgMed()));
}
private static long getWeightedDaysInterval(List<? extends
AdresseDTO> adresser, int index1, int index2) {

private boolean isOverlappTilfelle3(T adresse1, T adresse2) {
var interval = Duration.between(adresser.get(index1).getGyldigFraOgMed(),
index2 == OUT_OF_BOUND ? LocalDateTime.now() :
adresser.get(index2).getGyldigFraOgMed()).toDays();

// |<--- Intervall A --->|
// |<-------- Intervall B ------->|
return adresse2.getGyldigFraOgMed().isBefore(adresse1.getGyldigFraOgMed()) &&
getDateOrFuture(adresse2.getGyldigTilOgMed()).isAfter(getDateOrFuture(adresse1.getGyldigTilOgMed()));
return (interval - interval / (index1 - index2)) / (index1 - index2);
}

private void sortAdresser(List<T> adresser) {
private static int getIndexOfNextFromDate(List<? extends
AdresseDTO> adresser, int index) {

if (adresser.isEmpty()) {
return;
}
adresser.stream()
.filter(adresse -> isNull(adresse.getGyldigFraOgMed()))
.forEach(adresse -> adresse.setGyldigFraOgMed(LocalDateTime.now()));
adresser.sort(Comparator.comparing(AdresseDTO::getGyldigFraOgMed, Comparator.reverseOrder()));
for (var i = adresser.size(); i > 0; i--) {
adresser.get(i - 1).setId(adresser.size() - i + 1);
for (var i = index - 1; i >= 0; i--) {
if (nonNull(adresser.get(i).getGyldigFraOgMed())) {
return i;
}
}
return OUT_OF_BOUND;
}

protected boolean isIdSupported(AdresseDTO adresse, String ident) {

return isNotNpidIdent(ident) && !isTestnorgeIdent(ident) && !adresse.isPdlMaster();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static no.nav.pdl.forvalter.utils.ArtifactUtils.getKilde;
import static no.nav.pdl.forvalter.utils.ArtifactUtils.getMaster;
import static no.nav.pdl.forvalter.utils.IdenttypeUtility.getIdenttype;
import static no.nav.pdl.forvalter.utils.TestnorgeIdentUtility.isTestnorgeIdent;
import static no.nav.testnav.libs.data.pdlforvalter.v1.AdressebeskyttelseDTO.AdresseBeskyttelse.STRENGT_FORTROLIG;
Expand Down Expand Up @@ -51,15 +53,17 @@ public BostedAdresseService(GenererNavnServiceConsumer genererNavnServiceConsume

public List<BostedadresseDTO> convert(PersonDTO person, Boolean relaxed) {

for (var adresse : person.getBostedsadresse()) {
person.getBostedsadresse().stream()
.filter(adresse -> isTrue(adresse.getIsNew()) && (isNotTrue(relaxed)))
.forEach(adresse -> {
handle(adresse, person);
adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
});

if (isTrue(adresse.getIsNew()) && (isNotTrue(relaxed))) {
handle(adresse, person);
populateMiscFields(adresse, person);
oppdaterAdressedatoer(person.getBostedsadresse(), person);
setAngittFlyttedato(person.getBostedsadresse());

}
}
enforceIntegrity(person.getBostedsadresse());
return person.getBostedsadresse();
}

Expand Down Expand Up @@ -192,4 +196,10 @@ private String getLandkode(PersonDTO person) {
.map(Optional::get)
.findFirst().orElse(null);
}

private static void setAngittFlyttedato(List<BostedadresseDTO> bostedsadresse) {

bostedsadresse.forEach(adresse ->
adresse.setAngittFlyttedato(adresse.getGyldigFraOgMed()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,16 @@ private static void validatePostBoksAdresse(KontaktadresseDTO.PostboksadresseDTO

public List<KontaktadresseDTO> convert(PersonDTO person, Boolean relaxed) {

for (var adresse : person.getKontaktadresse()) {

if (isTrue(adresse.getIsNew())) {
person.getKontaktadresse().stream()
.filter(adresse -> isTrue(adresse.getIsNew()) && (isNotTrue(relaxed)))
.forEach(adresse -> {
handle(adresse, person);
adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
});

adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
oppdaterAdressedatoer(person.getBostedsadresse(), person);

if (isNotTrue(relaxed)) {
handle(adresse, person);
}
}
}
return person.getKontaktadresse();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,15 @@ public OppholdsadresseService(GenererNavnServiceConsumer genererNavnServiceConsu

public List<OppholdsadresseDTO> convert(PersonDTO person) {

for (var adresse : person.getOppholdsadresse()) {

if (isTrue(adresse.getIsNew())) {

adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
handle(adresse, person);
}
}

person.getOppholdsadresse().stream()
.filter(adresse -> isTrue(adresse.getIsNew()))
.forEach(adresse -> {
handle(adresse, person);
adresse.setKilde(getKilde(adresse));
adresse.setMaster(getMaster(adresse, person));
});

oppdaterAdressedatoer(person.getBostedsadresse(), person);
return person.getOppholdsadresse();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,21 +149,20 @@ void whenOverlappingGyldigTil_thenFixInterval() {
.ident(FNR_IDENT)
.bostedsadresse(new ArrayList<>(List.of(
BostedadresseDTO.builder()
.gyldigFraOgMed(LocalDate.of(2020, 1, 1).atStartOfDay())
.gyldigTilOgMed(LocalDate.of(2021, 2, 3).atStartOfDay())
.utenlandskAdresse(new UtenlandskAdresseDTO())
.gyldigFraOgMed(LocalDate.of(2021, 2, 2).atStartOfDay())
.matrikkeladresse(new MatrikkeladresseDTO())
.isNew(true)
.build(),
BostedadresseDTO.builder()
.gyldigFraOgMed(LocalDate.of(2020, 2, 2).atStartOfDay())
.matrikkeladresse(new MatrikkeladresseDTO())
.gyldigFraOgMed(LocalDate.of(2020, 1, 1).atStartOfDay())
.utenlandskAdresse(new UtenlandskAdresseDTO())
.isNew(true)
.build())))
.build();

var response = bostedAdresseService.convert(request, null);

assertThat(response.get(1).getGyldigTilOgMed(), is(equalTo(LocalDateTime.of(2020, 2, 1, 0, 0))));
assertThat(response.get(1).getGyldigTilOgMed(), is(equalTo(LocalDateTime.of(2021, 2, 1, 0, 0))));
}

@Test
Expand Down
Loading