From 978aa365d70e1d8bc9f76a11373164e735b8c26d Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 14:35:51 +0200 Subject: [PATCH 1/6] patient entity-class and functionality implemented --- .../application/service/PatientMapper.java | 32 ++++++++++ .../application/service/PatientService.java | 58 +++++++++++++++++++ .../projektarendehantering/common/Actor.java | 2 + .../infrastructure/config/SecurityConfig.java | 26 +++------ .../persistence/PatientEntity.java | 51 ++++++++++++++++ .../persistence/PatientRepository.java | 11 ++++ .../presentation/dto/PatientDTO.java | 47 +++++++++++++++ .../presentation/rest/PatientController.java | 39 +++++++++++++ src/test/resources/application.properties | 4 +- 9 files changed, 250 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java create mode 100644 src/main/java/org/example/projektarendehantering/application/service/PatientService.java create mode 100644 src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java create mode 100644 src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientRepository.java create mode 100644 src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java create mode 100644 src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java diff --git a/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java b/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java new file mode 100644 index 0000000..3b36e7c --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java @@ -0,0 +1,32 @@ +package org.example.projektarendehantering.application.service; + +import org.example.projektarendehantering.infrastructure.persistence.PatientEntity; +import org.example.projektarendehantering.presentation.dto.PatientDTO; +import org.springframework.stereotype.Component; + +@Component +public class PatientMapper { + + public PatientDTO toDTO(PatientEntity entity) { + if (entity == null) return null; + return new PatientDTO( + entity.getId(), + entity.getFirstName(), + entity.getLastName(), + entity.getPersonalIdentityNumber(), + entity.getCreatedAt() + ); + } + + public PatientEntity toEntity(PatientDTO dto) { + if (dto == null) return null; + PatientEntity entity = new PatientEntity(); + entity.setId(dto.getId()); + entity.setFirstName(dto.getFirstName()); + entity.setLastName(dto.getLastName()); + entity.setPersonalIdentityNumber(dto.getPersonalIdentityNumber()); + entity.setCreatedAt(dto.getCreatedAt()); + return entity; + } +} + diff --git a/src/main/java/org/example/projektarendehantering/application/service/PatientService.java b/src/main/java/org/example/projektarendehantering/application/service/PatientService.java new file mode 100644 index 0000000..4bbd21f --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/application/service/PatientService.java @@ -0,0 +1,58 @@ +package org.example.projektarendehantering.application.service; + +import org.example.projektarendehantering.infrastructure.persistence.PatientEntity; +import org.example.projektarendehantering.infrastructure.persistence.PatientRepository; +import org.example.projektarendehantering.presentation.dto.PatientDTO; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +public class PatientService { + + private final PatientRepository patientRepository; + private final PatientMapper patientMapper; + + public PatientService(PatientRepository patientRepository, PatientMapper patientMapper) { + this.patientRepository = patientRepository; + this.patientMapper = patientMapper; + } + + @Transactional + public PatientDTO createPatient(PatientDTO patientDTO) { + PatientEntity entity = patientMapper.toEntity(patientDTO); + if (entity.getId() == null) { + entity.setId(UUID.randomUUID()); + } + if (entity.getCreatedAt() == null) { + entity.setCreatedAt(Instant.now()); + } + if (entity.getPersonalIdentityNumber() != null && !entity.getPersonalIdentityNumber().isBlank()) { + patientRepository.findByPersonalIdentityNumber(entity.getPersonalIdentityNumber()) + .ifPresent(existing -> { + throw new ResponseStatusException(HttpStatus.CONFLICT, "Patient with personalIdentityNumber already exists"); + }); + } + return patientMapper.toDTO(patientRepository.save(entity)); + } + + @Transactional(readOnly = true) + public Optional getPatient(UUID id) { + return patientRepository.findById(id).map(patientMapper::toDTO); + } + + @Transactional(readOnly = true) + public List getAllPatients() { + return patientRepository.findAll().stream() + .map(patientMapper::toDTO) + .collect(Collectors.toList()); + } +} + diff --git a/src/main/java/org/example/projektarendehantering/common/Actor.java b/src/main/java/org/example/projektarendehantering/common/Actor.java index 407e4d2..1b701e2 100644 --- a/src/main/java/org/example/projektarendehantering/common/Actor.java +++ b/src/main/java/org/example/projektarendehantering/common/Actor.java @@ -3,4 +3,6 @@ import java.util.UUID; public record Actor(UUID userId, Role role) { + + } diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java b/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java index bb2f1dc..f2a40c8 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java @@ -4,10 +4,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @@ -18,28 +14,22 @@ public class SecurityConfig { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize - .requestMatchers("/login**", "/error**", "/static/**", "/app.css", "/app.js").permitAll() + .requestMatchers( + "/login**", + "/oauth2/**", + "/error**", + "/static/**", + "/app.css", + "/app.js" + ).permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .defaultSuccessUrl("/", true) ) - .formLogin(form -> form - .defaultSuccessUrl("/", true) - ) .logout(logout -> logout .logoutSuccessUrl("/") ); return http.build(); } - - @Bean - public UserDetailsService userDetailsService() { - UserDetails admin = User.builder() - .username("admin") - .password("{noop}password") // {noop} means no password encoding (fine for dev) - .roles("ADMIN") - .build(); - return new InMemoryUserDetailsManager(admin); - } } diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java new file mode 100644 index 0000000..ab4066e --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java @@ -0,0 +1,51 @@ +package org.example.projektarendehantering.infrastructure.persistence; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "patients") +public class PatientEntity { + + @Id + private UUID id; + + private String firstName; + private String lastName; + + @Column(unique = true) + private String personalIdentityNumber; + + private Instant createdAt; + + public PatientEntity() {} + + public PatientEntity(UUID id, String firstName, String lastName, String personalIdentityNumber, Instant createdAt) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.personalIdentityNumber = personalIdentityNumber; + this.createdAt = createdAt; + } + + public UUID getId() { return id; } + public void setId(UUID id) { this.id = id; } + + public String getFirstName() { return firstName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + + public String getLastName() { return lastName; } + public void setLastName(String lastName) { this.lastName = lastName; } + + public String getPersonalIdentityNumber() { return personalIdentityNumber; } + public void setPersonalIdentityNumber(String personalIdentityNumber) { this.personalIdentityNumber = personalIdentityNumber; } + + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } +} + diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientRepository.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientRepository.java new file mode 100644 index 0000000..9005464 --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientRepository.java @@ -0,0 +1,11 @@ +package org.example.projektarendehantering.infrastructure.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; +import java.util.UUID; + +public interface PatientRepository extends JpaRepository { + Optional findByPersonalIdentityNumber(String personalIdentityNumber); +} + diff --git a/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java new file mode 100644 index 0000000..ba03358 --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java @@ -0,0 +1,47 @@ +package org.example.projektarendehantering.presentation.dto; + +import jakarta.validation.constraints.NotBlank; + +import java.time.Instant; +import java.util.UUID; + +public class PatientDTO { + + private UUID id; + + @NotBlank + private String firstName; + + @NotBlank + private String lastName; + + private String personalIdentityNumber; + + private Instant createdAt; + + public PatientDTO() {} + + public PatientDTO(UUID id, String firstName, String lastName, String personalIdentityNumber, Instant createdAt) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.personalIdentityNumber = personalIdentityNumber; + this.createdAt = createdAt; + } + + public UUID getId() { return id; } + public void setId(UUID id) { this.id = id; } + + public String getFirstName() { return firstName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + + public String getLastName() { return lastName; } + public void setLastName(String lastName) { this.lastName = lastName; } + + public String getPersonalIdentityNumber() { return personalIdentityNumber; } + public void setPersonalIdentityNumber(String personalIdentityNumber) { this.personalIdentityNumber = personalIdentityNumber; } + + public Instant getCreatedAt() { return createdAt; } + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } +} + diff --git a/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java b/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java new file mode 100644 index 0000000..3fcfdaa --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java @@ -0,0 +1,39 @@ +package org.example.projektarendehantering.presentation.rest; + +import jakarta.validation.Valid; +import org.example.projektarendehantering.application.service.PatientService; +import org.example.projektarendehantering.presentation.dto.PatientDTO; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/api/patients") +public class PatientController { + + private final PatientService patientService; + + public PatientController(PatientService patientService) { + this.patientService = patientService; + } + + @PostMapping + public ResponseEntity createPatient(@RequestBody @Valid PatientDTO patientDTO) { + return ResponseEntity.ok(patientService.createPatient(patientDTO)); + } + + @GetMapping("/{id}") + public ResponseEntity getPatient(@PathVariable UUID id) { + return patientService.getPatient(id) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + @GetMapping + public ResponseEntity> getAllPatients() { + return ResponseEntity.ok(patientService.getAllPatients()); + } +} + diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 898f789..099fd85 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -16,6 +16,6 @@ spring.jpa.show-sql=true # Disable Docker Compose auto-configuration during tests to avoid connection errors in CI spring.docker.compose.enabled=false -spring.security.oauth2.client.registration.github.client-id=mock-id ? -spring.security.oauth2.client.registration.github.client-secret=mock-secret ? +spring.security.oauth2.client.registration.github.client-id=mock-id +spring.security.oauth2.client.registration.github.client-secret=mock-secret spring.security.oauth2.client.registration.github.scope=read:user,user:email \ No newline at end of file From bb96da0d136132563afe43f5ea6818b613e9c555 Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 14:42:43 +0200 Subject: [PATCH 2/6] Unfucked the file --- .env.template | 4 +-- .../infrastructure/config/SecurityConfig.java | 26 +++++++++++++------ .../persistence/PatientEntity.java | 1 + src/test/resources/application.properties | 4 +-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.env.template b/.env.template index 5563b35..18fe61f 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,4 @@ # GitHub OAuth2 Credentials (DO NOT COMMIT THE ACTUAL .env FILE) # Get these from GitHub Settings -> Developer settings -> OAuth Apps -GITHUB_CLIENT_ID= -GITHUB_CLIENT_SECRET= +GITHUB_CLIENT_ID=Ov23liH2WD75Mu6yIMRq; +GITHUB_CLIENT_SECRET=63c07ed3f40021ed9a877c06ca09be0a6ef55883 diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java b/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java index f2a40c8..bb2f1dc 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java @@ -4,6 +4,10 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @@ -14,22 +18,28 @@ public class SecurityConfig { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize - .requestMatchers( - "/login**", - "/oauth2/**", - "/error**", - "/static/**", - "/app.css", - "/app.js" - ).permitAll() + .requestMatchers("/login**", "/error**", "/static/**", "/app.css", "/app.js").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .defaultSuccessUrl("/", true) ) + .formLogin(form -> form + .defaultSuccessUrl("/", true) + ) .logout(logout -> logout .logoutSuccessUrl("/") ); return http.build(); } + + @Bean + public UserDetailsService userDetailsService() { + UserDetails admin = User.builder() + .username("admin") + .password("{noop}password") // {noop} means no password encoding (fine for dev) + .roles("ADMIN") + .build(); + return new InMemoryUserDetailsManager(admin); + } } diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java index ab4066e..8a96028 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java @@ -13,6 +13,7 @@ public class PatientEntity { @Id + @GeneratedValue(strategy = GenerationType.UUID) private UUID id; private String firstName; diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 099fd85..898f789 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -16,6 +16,6 @@ spring.jpa.show-sql=true # Disable Docker Compose auto-configuration during tests to avoid connection errors in CI spring.docker.compose.enabled=false -spring.security.oauth2.client.registration.github.client-id=mock-id -spring.security.oauth2.client.registration.github.client-secret=mock-secret +spring.security.oauth2.client.registration.github.client-id=mock-id ? +spring.security.oauth2.client.registration.github.client-secret=mock-secret ? spring.security.oauth2.client.registration.github.scope=read:user,user:email \ No newline at end of file From 54e03fb2850ac3c8fb3d981bc0e79674c38c9baa Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 14:46:37 +0200 Subject: [PATCH 3/6] pushing .env to github since 1996 --- .env.template | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .env.template diff --git a/.env.template b/.env.template deleted file mode 100644 index 18fe61f..0000000 --- a/.env.template +++ /dev/null @@ -1,4 +0,0 @@ -# GitHub OAuth2 Credentials (DO NOT COMMIT THE ACTUAL .env FILE) -# Get these from GitHub Settings -> Developer settings -> OAuth Apps -GITHUB_CLIENT_ID=Ov23liH2WD75Mu6yIMRq; -GITHUB_CLIENT_SECRET=63c07ed3f40021ed9a877c06ca09be0a6ef55883 From 1a4cd3b467bba163f62d6aaa0bd1e2ade83951dd Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 14:49:52 +0200 Subject: [PATCH 4/6] generated value fixed? --- .../infrastructure/persistence/PatientEntity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java index 8a96028..e511a7d 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java @@ -4,6 +4,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; +import jakarta.persistence.GeneratedValue; import java.time.Instant; import java.util.UUID; From bae39d6b1833f953f57619734ac3c57ff5353df1 Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 14:52:52 +0200 Subject: [PATCH 5/6] fixed imports again --- .../infrastructure/persistence/PatientEntity.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java index e511a7d..b5f129a 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/PatientEntity.java @@ -1,10 +1,6 @@ package org.example.projektarendehantering.infrastructure.persistence; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import jakarta.persistence.GeneratedValue; +import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; From b96df4561227983aa7f1e4a932b8e859c9c61d08 Mon Sep 17 00:00:00 2001 From: Linus Westling Date: Tue, 31 Mar 2026 15:03:27 +0200 Subject: [PATCH 6/6] added functionality for patients. Added relations to case. Fixed conflicts and removed personnr field --- .../application/service/CaseMapper.java | 3 +- .../application/service/CaseService.java | 21 +++++++++++- .../application/service/PatientMapper.java | 6 ++-- .../application/service/PatientService.java | 11 +++---- .../persistence/CaseEntity.java | 12 ++++++- .../persistence/CaseRepository.java | 3 ++ .../presentation/dto/CaseDTO.java | 11 ++++++- .../presentation/dto/PatientCreateDTO.java | 32 +++++++++++++++++++ .../presentation/dto/PatientDTO.java | 8 +---- .../presentation/rest/PatientController.java | 14 ++++++-- 10 files changed, 97 insertions(+), 24 deletions(-) create mode 100644 src/main/java/org/example/projektarendehantering/presentation/dto/PatientCreateDTO.java diff --git a/src/main/java/org/example/projektarendehantering/application/service/CaseMapper.java b/src/main/java/org/example/projektarendehantering/application/service/CaseMapper.java index eec79f9..80128e9 100644 --- a/src/main/java/org/example/projektarendehantering/application/service/CaseMapper.java +++ b/src/main/java/org/example/projektarendehantering/application/service/CaseMapper.java @@ -14,7 +14,8 @@ public CaseDTO toDTO(CaseEntity entity) { entity.getStatus(), entity.getTitle(), entity.getDescription(), - entity.getCreatedAt() + entity.getCreatedAt(), + entity.getPatient() != null ? entity.getPatient().getId() : null ); } diff --git a/src/main/java/org/example/projektarendehantering/application/service/CaseService.java b/src/main/java/org/example/projektarendehantering/application/service/CaseService.java index ffd69e3..503e045 100644 --- a/src/main/java/org/example/projektarendehantering/application/service/CaseService.java +++ b/src/main/java/org/example/projektarendehantering/application/service/CaseService.java @@ -2,9 +2,13 @@ import org.example.projektarendehantering.infrastructure.persistence.CaseEntity; import org.example.projektarendehantering.infrastructure.persistence.CaseRepository; +import org.example.projektarendehantering.infrastructure.persistence.PatientEntity; +import org.example.projektarendehantering.infrastructure.persistence.PatientRepository; import org.example.projektarendehantering.presentation.dto.CaseDTO; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; import java.time.Instant; import java.util.List; @@ -17,15 +21,23 @@ public class CaseService { private final CaseRepository caseRepository; private final CaseMapper caseMapper; + private final PatientRepository patientRepository; - public CaseService(CaseRepository caseRepository, CaseMapper caseMapper) { + public CaseService(CaseRepository caseRepository, CaseMapper caseMapper, PatientRepository patientRepository) { this.caseRepository = caseRepository; this.caseMapper = caseMapper; + this.patientRepository = patientRepository; } @Transactional public CaseDTO createCase(CaseDTO caseDTO) { + if (caseDTO.getPatientId() == null) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "patientId is required"); + } CaseEntity entity = caseMapper.toEntity(caseDTO); + PatientEntity patient = patientRepository.findById(caseDTO.getPatientId()) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Patient not found")); + entity.setPatient(patient); if (entity.getStatus() == null) { entity.setStatus("OPEN"); } @@ -47,4 +59,11 @@ public List getAllCases() { .map(caseMapper::toDTO) .collect(Collectors.toList()); } + + @Transactional(readOnly = true) + public List getCasesForPatient(UUID patientId) { + return caseRepository.findAllByPatient_Id(patientId).stream() + .map(caseMapper::toDTO) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java b/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java index 3b36e7c..aec111e 100644 --- a/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java +++ b/src/main/java/org/example/projektarendehantering/application/service/PatientMapper.java @@ -1,6 +1,7 @@ package org.example.projektarendehantering.application.service; import org.example.projektarendehantering.infrastructure.persistence.PatientEntity; +import org.example.projektarendehantering.presentation.dto.PatientCreateDTO; import org.example.projektarendehantering.presentation.dto.PatientDTO; import org.springframework.stereotype.Component; @@ -13,19 +14,16 @@ public PatientDTO toDTO(PatientEntity entity) { entity.getId(), entity.getFirstName(), entity.getLastName(), - entity.getPersonalIdentityNumber(), entity.getCreatedAt() ); } - public PatientEntity toEntity(PatientDTO dto) { + public PatientEntity toEntity(PatientCreateDTO dto) { if (dto == null) return null; PatientEntity entity = new PatientEntity(); - entity.setId(dto.getId()); entity.setFirstName(dto.getFirstName()); entity.setLastName(dto.getLastName()); entity.setPersonalIdentityNumber(dto.getPersonalIdentityNumber()); - entity.setCreatedAt(dto.getCreatedAt()); return entity; } } diff --git a/src/main/java/org/example/projektarendehantering/application/service/PatientService.java b/src/main/java/org/example/projektarendehantering/application/service/PatientService.java index 4bbd21f..b6c153f 100644 --- a/src/main/java/org/example/projektarendehantering/application/service/PatientService.java +++ b/src/main/java/org/example/projektarendehantering/application/service/PatientService.java @@ -2,6 +2,7 @@ import org.example.projektarendehantering.infrastructure.persistence.PatientEntity; import org.example.projektarendehantering.infrastructure.persistence.PatientRepository; +import org.example.projektarendehantering.presentation.dto.PatientCreateDTO; import org.example.projektarendehantering.presentation.dto.PatientDTO; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; @@ -26,14 +27,10 @@ public PatientService(PatientRepository patientRepository, PatientMapper patient } @Transactional - public PatientDTO createPatient(PatientDTO patientDTO) { + public PatientDTO createPatient(PatientCreateDTO patientDTO) { PatientEntity entity = patientMapper.toEntity(patientDTO); - if (entity.getId() == null) { - entity.setId(UUID.randomUUID()); - } - if (entity.getCreatedAt() == null) { - entity.setCreatedAt(Instant.now()); - } + entity.setId(UUID.randomUUID()); + entity.setCreatedAt(Instant.now()); if (entity.getPersonalIdentityNumber() != null && !entity.getPersonalIdentityNumber().isBlank()) { patientRepository.findByPersonalIdentityNumber(entity.getPersonalIdentityNumber()) .ifPresent(existing -> { diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java index 2d57c78..71656b2 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java @@ -2,6 +2,8 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.time.Instant; import java.util.UUID; @@ -18,15 +20,20 @@ public class CaseEntity { private String description; private Instant createdAt; + @ManyToOne(optional = false) + @JoinColumn(name = "patient_id", nullable = false) + private PatientEntity patient; + public CaseEntity() {} - public CaseEntity(UUID id, String status, UUID ownerId, String title, String description, Instant createdAt) { + public CaseEntity(UUID id, String status, UUID ownerId, String title, String description, Instant createdAt, PatientEntity patient) { this.id = id; this.status = status; this.ownerId = ownerId; this.title = title; this.description = description; this.createdAt = createdAt; + this.patient = patient; } public UUID getId() { return id; } @@ -46,4 +53,7 @@ public CaseEntity(UUID id, String status, UUID ownerId, String title, String des public Instant getCreatedAt() { return createdAt; } public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + + public PatientEntity getPatient() { return patient; } + public void setPatient(PatientEntity patient) { this.patient = patient; } } diff --git a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java index 0eb62c0..7d40d5d 100644 --- a/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java +++ b/src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java @@ -1,7 +1,10 @@ package org.example.projektarendehantering.infrastructure.persistence; import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; import java.util.UUID; public interface CaseRepository extends JpaRepository { + List findAllByPatient_Id(UUID patientId); } diff --git a/src/main/java/org/example/projektarendehantering/presentation/dto/CaseDTO.java b/src/main/java/org/example/projektarendehantering/presentation/dto/CaseDTO.java index 050fcb9..e0c306e 100644 --- a/src/main/java/org/example/projektarendehantering/presentation/dto/CaseDTO.java +++ b/src/main/java/org/example/projektarendehantering/presentation/dto/CaseDTO.java @@ -1,5 +1,7 @@ package org.example.projektarendehantering.presentation.dto; +import jakarta.validation.constraints.NotNull; + import java.time.Instant; import java.util.UUID; @@ -11,14 +13,18 @@ public class CaseDTO { private String description; private Instant createdAt; + @NotNull + private UUID patientId; + public CaseDTO() {} - public CaseDTO(UUID id, String status, String title, String description, Instant createdAt) { + public CaseDTO(UUID id, String status, String title, String description, Instant createdAt, UUID patientId) { this.id = id; this.status = status; this.title = title; this.description = description; this.createdAt = createdAt; + this.patientId = patientId; } public UUID getId() { return id; } @@ -35,4 +41,7 @@ public CaseDTO(UUID id, String status, String title, String description, Instant public Instant getCreatedAt() { return createdAt; } public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } + + public UUID getPatientId() { return patientId; } + public void setPatientId(UUID patientId) { this.patientId = patientId; } } diff --git a/src/main/java/org/example/projektarendehantering/presentation/dto/PatientCreateDTO.java b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientCreateDTO.java new file mode 100644 index 0000000..4038ad4 --- /dev/null +++ b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientCreateDTO.java @@ -0,0 +1,32 @@ +package org.example.projektarendehantering.presentation.dto; + +import jakarta.validation.constraints.NotBlank; + +public class PatientCreateDTO { + + @NotBlank + private String firstName; + + @NotBlank + private String lastName; + + private String personalIdentityNumber; + + public PatientCreateDTO() {} + + public PatientCreateDTO(String firstName, String lastName, String personalIdentityNumber) { + this.firstName = firstName; + this.lastName = lastName; + this.personalIdentityNumber = personalIdentityNumber; + } + + public String getFirstName() { return firstName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + + public String getLastName() { return lastName; } + public void setLastName(String lastName) { this.lastName = lastName; } + + public String getPersonalIdentityNumber() { return personalIdentityNumber; } + public void setPersonalIdentityNumber(String personalIdentityNumber) { this.personalIdentityNumber = personalIdentityNumber; } +} + diff --git a/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java index ba03358..53bfb7f 100644 --- a/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java +++ b/src/main/java/org/example/projektarendehantering/presentation/dto/PatientDTO.java @@ -15,17 +15,14 @@ public class PatientDTO { @NotBlank private String lastName; - private String personalIdentityNumber; - private Instant createdAt; public PatientDTO() {} - public PatientDTO(UUID id, String firstName, String lastName, String personalIdentityNumber, Instant createdAt) { + public PatientDTO(UUID id, String firstName, String lastName, Instant createdAt) { this.id = id; this.firstName = firstName; this.lastName = lastName; - this.personalIdentityNumber = personalIdentityNumber; this.createdAt = createdAt; } @@ -38,9 +35,6 @@ public PatientDTO(UUID id, String firstName, String lastName, String personalIde public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } - public String getPersonalIdentityNumber() { return personalIdentityNumber; } - public void setPersonalIdentityNumber(String personalIdentityNumber) { this.personalIdentityNumber = personalIdentityNumber; } - public Instant getCreatedAt() { return createdAt; } public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java b/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java index 3fcfdaa..a0b2430 100644 --- a/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java +++ b/src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java @@ -1,7 +1,10 @@ package org.example.projektarendehantering.presentation.rest; import jakarta.validation.Valid; +import org.example.projektarendehantering.application.service.CaseService; import org.example.projektarendehantering.application.service.PatientService; +import org.example.projektarendehantering.presentation.dto.PatientCreateDTO; +import org.example.projektarendehantering.presentation.dto.CaseDTO; import org.example.projektarendehantering.presentation.dto.PatientDTO; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -14,13 +17,15 @@ public class PatientController { private final PatientService patientService; + private final CaseService caseService; - public PatientController(PatientService patientService) { + public PatientController(PatientService patientService, CaseService caseService) { this.patientService = patientService; + this.caseService = caseService; } @PostMapping - public ResponseEntity createPatient(@RequestBody @Valid PatientDTO patientDTO) { + public ResponseEntity createPatient(@RequestBody @Valid PatientCreateDTO patientDTO) { return ResponseEntity.ok(patientService.createPatient(patientDTO)); } @@ -35,5 +40,10 @@ public ResponseEntity getPatient(@PathVariable UUID id) { public ResponseEntity> getAllPatients() { return ResponseEntity.ok(patientService.getAllPatients()); } + + @GetMapping("/{id}/cases") + public ResponseEntity> getCasesForPatient(@PathVariable UUID id) { + return ResponseEntity.ok(caseService.getCasesForPatient(id)); + } }