feat(persons): accept PersonUpdateDTO for POST /api/persons (all 6 fields)
createPerson now takes PersonUpdateDTO, persisting birthYear, deathYear, notes in addition to firstName, lastName, alias. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import org.raddatz.familienarchiv.dto.PersonUpdateDTO;
|
||||
import org.raddatz.familienarchiv.model.Document;
|
||||
import org.raddatz.familienarchiv.model.Person;
|
||||
@@ -58,13 +59,14 @@ public class PersonController {
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(Permission.WRITE_ALL)
|
||||
public ResponseEntity<Person> createPerson(@RequestBody Map<String, String> body) {
|
||||
String firstName = body.get("firstName");
|
||||
String lastName = body.get("lastName");
|
||||
if (firstName == null || firstName.isBlank() || lastName == null || lastName.isBlank()) {
|
||||
public ResponseEntity<Person> createPerson(@Valid @RequestBody PersonUpdateDTO dto) {
|
||||
if (dto.getFirstName() == null || dto.getFirstName().isBlank()
|
||||
|| dto.getLastName() == null || dto.getLastName().isBlank()) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Vor- und Nachname sind Pflichtfelder");
|
||||
}
|
||||
return ResponseEntity.ok(personService.createPerson(firstName.trim(), lastName.trim(), body.get("alias")));
|
||||
dto.setFirstName(dto.getFirstName().trim());
|
||||
dto.setLastName(dto.getLastName().trim());
|
||||
return ResponseEntity.ok(personService.createPerson(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
|
||||
@@ -72,6 +72,20 @@ public class PersonService {
|
||||
return personRepository.save(person);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Person createPerson(PersonUpdateDTO dto) {
|
||||
validateYears(dto.getBirthYear(), dto.getDeathYear());
|
||||
Person person = Person.builder()
|
||||
.firstName(dto.getFirstName())
|
||||
.lastName(dto.getLastName())
|
||||
.alias(dto.getAlias() == null || dto.getAlias().isBlank() ? null : dto.getAlias().trim())
|
||||
.notes(dto.getNotes() == null || dto.getNotes().isBlank() ? null : dto.getNotes().trim())
|
||||
.birthYear(dto.getBirthYear())
|
||||
.deathYear(dto.getDeathYear())
|
||||
.build();
|
||||
return personRepository.save(person);
|
||||
}
|
||||
|
||||
private void validateYears(Integer birthYear, Integer deathYear) {
|
||||
if (birthYear != null && birthYear <= 0) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Geburtsjahr muss eine positive Zahl sein");
|
||||
|
||||
@@ -201,7 +201,7 @@ class PersonControllerTest {
|
||||
@WithMockUser(authorities = "WRITE_ALL")
|
||||
void createPerson_returns200_whenValid() throws Exception {
|
||||
Person saved = Person.builder().id(UUID.randomUUID()).firstName("Hans").lastName("Müller").build();
|
||||
when(personService.createPerson(eq("Hans"), eq("Müller"), any())).thenReturn(saved);
|
||||
when(personService.createPerson(any(org.raddatz.familienarchiv.dto.PersonUpdateDTO.class))).thenReturn(saved);
|
||||
|
||||
mockMvc.perform(post("/api/persons")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
@@ -305,6 +305,27 @@ class PersonControllerTest {
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
// ─── Phase 2.2: POST /api/persons with full PersonUpdateDTO ───────────────
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "WRITE_ALL")
|
||||
void createPerson_returns200_withAllSixFields() throws Exception {
|
||||
UUID id = UUID.randomUUID();
|
||||
Person saved = Person.builder().id(id).firstName("Maria").lastName("Raddatz")
|
||||
.alias("Oma Maria").birthYear(1901).deathYear(1975).notes("Some notes").build();
|
||||
when(personService.createPerson(any(org.raddatz.familienarchiv.dto.PersonUpdateDTO.class))).thenReturn(saved);
|
||||
|
||||
mockMvc.perform(post("/api/persons")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"firstName\":\"Maria\",\"lastName\":\"Raddatz\"," +
|
||||
"\"alias\":\"Oma Maria\",\"birthYear\":1901,\"deathYear\":1975," +
|
||||
"\"notes\":\"Some notes\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.firstName").value("Maria"))
|
||||
.andExpect(jsonPath("$.alias").value("Oma Maria"))
|
||||
.andExpect(jsonPath("$.birthYear").value(1901));
|
||||
}
|
||||
|
||||
// ─── Phase 1.2: @Size constraints ─────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
|
||||
@@ -110,6 +110,37 @@ class PersonServiceTest {
|
||||
assertThat(result.getAlias()).isEqualTo("Hans Müller");
|
||||
}
|
||||
|
||||
// ─── Phase 2.1: createPerson(PersonUpdateDTO) ─────────────────────────────
|
||||
|
||||
@Test
|
||||
void createPerson_dto_persistsAllSixFields() {
|
||||
when(personRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
|
||||
PersonUpdateDTO dto = new PersonUpdateDTO();
|
||||
dto.setFirstName("Maria"); dto.setLastName("Raddatz"); dto.setAlias("Oma Maria");
|
||||
dto.setBirthYear(1901); dto.setDeathYear(1975); dto.setNotes("Some notes");
|
||||
|
||||
Person result = personService.createPerson(dto);
|
||||
|
||||
assertThat(result.getFirstName()).isEqualTo("Maria");
|
||||
assertThat(result.getLastName()).isEqualTo("Raddatz");
|
||||
assertThat(result.getAlias()).isEqualTo("Oma Maria");
|
||||
assertThat(result.getBirthYear()).isEqualTo(1901);
|
||||
assertThat(result.getDeathYear()).isEqualTo(1975);
|
||||
assertThat(result.getNotes()).isEqualTo("Some notes");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createPerson_dto_yearValidationFires_whenBirthYearNegative() {
|
||||
PersonUpdateDTO dto = new PersonUpdateDTO();
|
||||
dto.setFirstName("Anna"); dto.setLastName("Test"); dto.setBirthYear(-1);
|
||||
|
||||
assertThatThrownBy(() -> personService.createPerson(dto))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.extracting(e -> ((ResponseStatusException) e).getStatusCode().value())
|
||||
.isEqualTo(400);
|
||||
}
|
||||
|
||||
// ─── updatePerson (alias) ─────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user