feat(relationship): add generation to PersonNodeDTO + update all sites (#689)
PersonNodeDTO is a positional record. The optional Integer generation field is inserted between deathYear and familyMember so all four construction sites stay readable without a builder. - RelationshipService.getFamilyNetwork → populates with person.getGeneration() (the Stammbaum's strict-rank source on the frontend). - RelationshipInferenceService.findAllFor → populates the same way; inference UI does not consume it but the field travels along for consistency. - RelationshipControllerTest fixtures pass null. Refs #689 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -96,7 +96,8 @@ public class RelationshipInferenceService {
|
|||||||
if (p == null) continue;
|
if (p == null) continue;
|
||||||
List<RelationToken> path = shortestPaths.get(id);
|
List<RelationToken> path = shortestPaths.get(id);
|
||||||
PersonNodeDTO node = new PersonNodeDTO(
|
PersonNodeDTO node = new PersonNodeDTO(
|
||||||
p.getId(), p.getDisplayName(), p.getBirthYear(), p.getDeathYear(), p.isFamilyMember());
|
p.getId(), p.getDisplayName(), p.getBirthYear(), p.getDeathYear(),
|
||||||
|
p.getGeneration(), p.isFamilyMember());
|
||||||
out.add(new InferredRelationshipWithPersonDTO(node, labelFor(path), path.size()));
|
out.add(new InferredRelationshipWithPersonDTO(node, labelFor(path), path.size()));
|
||||||
}
|
}
|
||||||
out.sort(Comparator.comparingInt(InferredRelationshipWithPersonDTO::hops)
|
out.sort(Comparator.comparingInt(InferredRelationshipWithPersonDTO::hops)
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ public class RelationshipService {
|
|||||||
for (Person p : familyMembers) {
|
for (Person p : familyMembers) {
|
||||||
familyIds.add(p.getId());
|
familyIds.add(p.getId());
|
||||||
nodes.add(new PersonNodeDTO(
|
nodes.add(new PersonNodeDTO(
|
||||||
p.getId(), p.getDisplayName(), p.getBirthYear(), p.getDeathYear(), true));
|
p.getId(), p.getDisplayName(), p.getBirthYear(), p.getDeathYear(),
|
||||||
|
p.getGeneration(), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PersonRelationship> familyEdges = relationshipRepository.findAllByRelationTypeIn(
|
List<PersonRelationship> familyEdges = relationshipRepository.findAllByRelationTypeIn(
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ public record PersonNodeDTO(
|
|||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) String displayName,
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) String displayName,
|
||||||
Integer birthYear,
|
Integer birthYear,
|
||||||
Integer deathYear,
|
Integer deathYear,
|
||||||
|
Integer generation,
|
||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) boolean familyMember
|
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) boolean familyMember
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class RelationshipControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
|
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
|
||||||
void getNetwork_returns200_with_NetworkDTO_for_authenticated_user() throws Exception {
|
void getNetwork_returns200_with_NetworkDTO_for_authenticated_user() throws Exception {
|
||||||
PersonNodeDTO node = new PersonNodeDTO(PERSON_ID, "Alice Müller", 1900, 1980, true);
|
PersonNodeDTO node = new PersonNodeDTO(PERSON_ID, "Alice Müller", 1900, 1980, null, true);
|
||||||
RelationshipDTO edge = new RelationshipDTO(
|
RelationshipDTO edge = new RelationshipDTO(
|
||||||
UUID.randomUUID(), PERSON_ID, OTHER_ID,
|
UUID.randomUUID(), PERSON_ID, OTHER_ID,
|
||||||
"Alice Müller", 1900, 1980,
|
"Alice Müller", 1900, 1980,
|
||||||
@@ -111,7 +111,7 @@ class RelationshipControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
|
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
|
||||||
void getInferredRelationships_returns200_with_list_for_authenticated_user() throws Exception {
|
void getInferredRelationships_returns200_with_list_for_authenticated_user() throws Exception {
|
||||||
PersonNodeDTO relative = new PersonNodeDTO(OTHER_ID, "Bob Müller", 1930, null, true);
|
PersonNodeDTO relative = new PersonNodeDTO(OTHER_ID, "Bob Müller", 1930, null, null, true);
|
||||||
InferredRelationshipWithPersonDTO inferred =
|
InferredRelationshipWithPersonDTO inferred =
|
||||||
new InferredRelationshipWithPersonDTO(relative, "Großvater", 2);
|
new InferredRelationshipWithPersonDTO(relative, "Großvater", 2);
|
||||||
when(relationshipService.getInferredRelationships(PERSON_ID))
|
when(relationshipService.getInferredRelationships(PERSON_ID))
|
||||||
|
|||||||
@@ -237,6 +237,22 @@ class RelationshipServiceTest {
|
|||||||
assertThat(result.edges().get(0).relatedPersonId()).isEqualTo(bob.getId());
|
assertThat(result.edges().get(0).relatedPersonId()).isEqualTo(bob.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getFamilyNetwork_populates_generation_on_PersonNodeDTO() {
|
||||||
|
Person walter = Person.builder().id(UUID.randomUUID()).lastName("Raddatz")
|
||||||
|
.familyMember(true).generation(2).build();
|
||||||
|
Person clara = Person.builder().id(UUID.randomUUID()).lastName("Raddatz")
|
||||||
|
.familyMember(true).generation(3).build();
|
||||||
|
when(personService.findAllFamilyMembers()).thenReturn(List.of(walter, clara));
|
||||||
|
when(relationshipRepository.findAllByRelationTypeIn(any())).thenReturn(List.of());
|
||||||
|
|
||||||
|
NetworkDTO result = service.getFamilyNetwork();
|
||||||
|
|
||||||
|
assertThat(result.nodes()).hasSize(2);
|
||||||
|
assertThat(result.nodes().stream().map(n -> n.generation()).toList())
|
||||||
|
.containsExactlyInAnyOrder(2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
// --- helpers ---
|
// --- helpers ---
|
||||||
|
|
||||||
private static Person person(String name) {
|
private static Person person(String name) {
|
||||||
|
|||||||
Reference in New Issue
Block a user