feat(persons): add notes field to person profile (issue #23)
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

V5 Flyway migration adds TEXT notes column; Person entity, service, and
controller updated to persist notes. Frontend edit form adds textarea and
view mode renders the notes section. Backed by 2 new service unit tests
(persist + blank clears).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #27.
This commit is contained in:
Marcel
2026-03-19 21:33:56 +01:00
committed by marcel
parent c01a07bd82
commit 08f7ae9a5c
11 changed files with 60 additions and 3 deletions

View File

@@ -55,7 +55,7 @@ public class PersonController {
if (firstName == null || firstName.isBlank() || lastName == null || lastName.isBlank()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Vor- und Nachname sind Pflichtfelder");
}
return ResponseEntity.ok(personService.updatePerson(id, firstName.trim(), lastName.trim(), body.get("alias")));
return ResponseEntity.ok(personService.updatePerson(id, firstName.trim(), lastName.trim(), body.get("alias"), body.get("notes")));
}
@PostMapping("/{id}/merge")

View File

@@ -28,4 +28,8 @@ public class Person {
// Optional: Aliasse für die Suche (z.B. "Opa Hans")
private String alias;
// Optional: Free-text biographical notes
@Column(columnDefinition = "TEXT")
private String notes;
}

View File

@@ -58,12 +58,13 @@ public class PersonService {
}
@Transactional
public Person updatePerson(UUID id, String firstName, String lastName, String alias) {
public Person updatePerson(UUID id, String firstName, String lastName, String alias, String notes) {
Person person = personRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Person nicht gefunden"));
person.setFirstName(firstName);
person.setLastName(lastName);
person.setAlias(alias == null || alias.isBlank() ? null : alias.trim());
person.setNotes(notes == null || notes.isBlank() ? null : notes.trim());
return personRepository.save(person);
}

View File

@@ -0,0 +1 @@
ALTER TABLE persons ADD COLUMN notes TEXT;

View File

@@ -83,6 +83,32 @@ class PersonServiceTest {
verify(personRepository).findByAliasIgnoreCase("Clara Cram");
}
// ─── updatePerson (notes) ────────────────────────────────────────────────
@Test
void updatePerson_persistsNotes() {
UUID id = UUID.randomUUID();
Person person = Person.builder().id(id).firstName("Anna").lastName("Alt").build();
when(personRepository.findById(id)).thenReturn(Optional.of(person));
when(personRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
Person result = personService.updatePerson(id, "Anna", "Alt", null, "Some notes here.");
assertThat(result.getNotes()).isEqualTo("Some notes here.");
}
@Test
void updatePerson_clearsNotes_whenBlank() {
UUID id = UUID.randomUUID();
Person person = Person.builder().id(id).firstName("Anna").lastName("Alt").notes("old notes").build();
when(personRepository.findById(id)).thenReturn(Optional.of(person));
when(personRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
Person result = personService.updatePerson(id, "Anna", "Alt", null, " ");
assertThat(result.getNotes()).isNull();
}
// ─── mergePersons ─────────────────────────────────────────────────────────
@Test