Skip to content

Commit

Permalink
VKT(Backend&Frontend): Change backend to match frontend requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
pkoivisto committed Oct 29, 2024
1 parent 107e721 commit a8565a7
Show file tree
Hide file tree
Showing 15 changed files with 260 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fi.oph.vkt.api.dto;

import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record MunicipalityDTO(@NonNull @NotNull String code) {}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package fi.oph.vkt.api.dto.examiner;

import fi.oph.vkt.api.dto.MunicipalityDTO;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
import lombok.Builder;
import lombok.NonNull;

Expand All @@ -9,8 +12,11 @@ public record ExaminerDetailsDTO(
@NonNull Integer version,
@NonNull String oid,
@NonNull String email,
@NonNull String phoneNumber,
@NonNull String lastName,
@NonNull String firstName,
@NonNull Boolean examLanguageFinnish,
@NonNull Boolean examLanguageSwedish
@NonNull Boolean examLanguageSwedish,
@NonNull Boolean isPublic,
@NonNull @NotEmpty List<MunicipalityDTO> municipalities
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fi.oph.vkt.api.dto.examiner;

import fi.oph.vkt.api.dto.MunicipalityDTO;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record ExaminerDetailsUpsertDTO(
@NonNull String email,
@NonNull String phoneNumber,
@NonNull Boolean examLanguageFinnish,
@NonNull Boolean examLanguageSwedish,
@NonNull Boolean isPublic,
@NonNull @NotEmpty List<MunicipalityDTO> municipalities
) {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package fi.oph.vkt.api.examiner;

import fi.oph.vkt.api.dto.examiner.ExaminerDetailsCreateDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsInitDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsUpsertDTO;
import fi.oph.vkt.service.ExaminerDetailsService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
Expand All @@ -25,12 +25,12 @@ public ExaminerDetailsDTO getExaminerDetails(@PathVariable("oid") String oid) {
}

@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(tags = TAG_EXAMINER, summary = "Create examiner")
public ExaminerDetailsDTO createExaminer(
@Operation(tags = TAG_EXAMINER, summary = "Create or update examiner")
public ExaminerDetailsDTO upsertExaminer(
@PathVariable("oid") String oid,
@RequestBody ExaminerDetailsCreateDTO examinerDetailsCreateDTO
@RequestBody ExaminerDetailsUpsertDTO examinerDetailsUpsertDTO
) {
return examinerDetailsService.createExaminer(oid, examinerDetailsCreateDTO);
return examinerDetailsService.upsertExaminer(oid, examinerDetailsUpsertDTO);
}

@GetMapping(path = "/init")
Expand Down
25 changes: 15 additions & 10 deletions backend/vkt/src/main/java/fi/oph/vkt/model/Examiner.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package fi.oph.vkt.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -32,6 +26,10 @@ public class Examiner extends BaseEntity {
@Column(name = "email", nullable = false)
private String email;

@Size(max = 255)
@Column(name = "phone_number", nullable = false)
private String phoneNumber;

@Column(name = "last_name", nullable = false)
private String lastName;

Expand All @@ -50,7 +48,14 @@ public class Examiner extends BaseEntity {
@OneToMany(mappedBy = "examiner")
private List<ExamEvent> examEvents = new ArrayList<>();

// TODO Consider using a separate join table instead?
@OneToMany(mappedBy = "examiner")
private List<ExaminerMunicipality> municipalities = new ArrayList<>();
@Column(name = "is_public", nullable = false)
private boolean isPublic;

@ManyToMany
@JoinTable(
name = "examiner_municipality",
joinColumns = @JoinColumn(name = "examiner_id", referencedColumnName = "examiner_id"),
inverseJoinColumns = @JoinColumn(name = "municipality_id")
)
private List<Municipality> municipalities = new ArrayList<>();
}

This file was deleted.

31 changes: 31 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/model/Municipality.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fi.oph.vkt.model;

import jakarta.persistence.*;
import java.util.List;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
@Table(name = "municipality")
public class Municipality extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "municipality_id", nullable = false)
private long id;

// Code should match the koodiArvo of an entry in koodisto
@Column(name = "code", nullable = false, unique = true)
private String code;

@Column(name = "name_fi", nullable = false)
private String nameFI;

@Column(name = "name_sv", nullable = false)
private String nameSV;

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "municipalities")
private List<Examiner> examiners;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fi.oph.vkt.repository;

import fi.oph.vkt.model.Municipality;
import java.util.Optional;
import org.springframework.stereotype.Repository;

@Repository
public interface MunicipalityRepository extends BaseRepository<Municipality> {
Optional<Municipality> findByCode(String code);
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package fi.oph.vkt.service;

import fi.oph.vkt.api.dto.examiner.ExaminerDetailsCreateDTO;
import fi.oph.vkt.api.dto.MunicipalityDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsInitDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsUpsertDTO;
import fi.oph.vkt.audit.AuditService;
import fi.oph.vkt.model.Examiner;
import fi.oph.vkt.model.Municipality;
import fi.oph.vkt.repository.ExaminerRepository;
import fi.oph.vkt.service.onr.OnrService;
import fi.oph.vkt.service.onr.PersonalData;
import fi.oph.vkt.util.exception.APIException;
import fi.oph.vkt.util.exception.APIExceptionType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -21,6 +25,7 @@
public class ExaminerDetailsService {

private final ExaminerRepository examinerRepository;
private final MunicipalityService municipalityService;
private final OnrService onrService;
private final AuditService auditService;

Expand All @@ -29,6 +34,10 @@ private PersonalData getOnrPersonalData(final String oid) {
return oidToData.get(oid);
}

private static MunicipalityDTO toMunicipalityDTO(final Municipality municipality) {
return MunicipalityDTO.builder().code(municipality.getCode()).build();
}

private static ExaminerDetailsDTO toExaminerDetailsDTO(final Examiner examiner) {
return ExaminerDetailsDTO
.builder()
Expand All @@ -38,6 +47,9 @@ private static ExaminerDetailsDTO toExaminerDetailsDTO(final Examiner examiner)
.lastName(examiner.getLastName())
.firstName(examiner.getFirstName())
.email(examiner.getEmail())
.phoneNumber(examiner.getPhoneNumber())
.municipalities(examiner.getMunicipalities().stream().map(ExaminerDetailsService::toMunicipalityDTO).toList())
.isPublic(examiner.isPublic())
.examLanguageFinnish(examiner.isExamLanguageFinnish())
.examLanguageSwedish(examiner.isExamLanguageSwedish())
.build();
Expand All @@ -62,8 +74,9 @@ public ExaminerDetailsInitDTO getInitialExaminerPersonalData(final String oid) {
}

@Transactional
public ExaminerDetailsDTO createExaminer(final String oid, ExaminerDetailsCreateDTO examinerDetailsCreateDTO) {
public ExaminerDetailsDTO upsertExaminer(final String oid, ExaminerDetailsUpsertDTO examinerDetailsUpsertDTO) {
// TODO Audit log entry
// TODO Throws when trying to update existing examiner - figure out if we want separate methods for updating vs. creating??
if (examinerRepository.findByOid(oid).isPresent()) {
throw new APIException(APIExceptionType.EXAMINER_ALREADY_INITIALIZED);
}
Expand All @@ -76,9 +89,17 @@ public ExaminerDetailsDTO createExaminer(final String oid, ExaminerDetailsCreate
examiner.setLastName(personalData.getLastName());
examiner.setFirstName(personalData.getFirstName());
examiner.setNickname(personalData.getNickname());
examiner.setEmail(examinerDetailsCreateDTO.email());
examiner.setExamLanguageFinnish(examinerDetailsCreateDTO.examLanguageFinnish());
examiner.setExamLanguageSwedish(examinerDetailsCreateDTO.examLanguageSwedish());
examiner.setEmail(examinerDetailsUpsertDTO.email());
examiner.setPhoneNumber(examinerDetailsUpsertDTO.phoneNumber());
examiner.setMunicipalities(
examinerDetailsUpsertDTO
.municipalities()
.stream()
.map(municipality -> municipalityService.getOrCreateByCode(municipality.code()))
.toList()
);
examiner.setExamLanguageFinnish(examinerDetailsUpsertDTO.examLanguageFinnish());
examiner.setExamLanguageSwedish(examinerDetailsUpsertDTO.examLanguageSwedish());
examinerRepository.saveAndFlush(examiner);

return toExaminerDetailsDTO(examiner);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package fi.oph.vkt.service;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import fi.oph.vkt.model.Municipality;
import fi.oph.vkt.repository.MunicipalityRepository;
import jakarta.annotation.PostConstruct;
import jakarta.transaction.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MunicipalityService {

private final MunicipalityRepository municipalityRepository;
private Map<String, String> codeToFi;
private Map<String, String> codeToSv;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final String KOODISTO_MUNICIPALITIES_JSON = "koodisto/koodisto_kunnat.json";

@PostConstruct
public void init() {
codeToFi = new HashMap<>();
codeToSv = new HashMap<>();

try (final InputStream is = new ClassPathResource(KOODISTO_MUNICIPALITIES_JSON).getInputStream()) {
final List<KoodistoEntry> koodisto = deserializeJson(is);
koodisto.forEach(koodistoEntry -> {
codeToFi.put(koodistoEntry.koodiArvo(), koodistoEntry.fi());
codeToSv.put(koodistoEntry.koodiArvo(), koodistoEntry.sv());
});
} catch (final IOException e) {
throw new RuntimeException(e);
}
}

@Transactional
public Municipality getOrCreateByCode(final String code) {
Optional<Municipality> existingMunicipality = municipalityRepository.findByCode(code);
if (existingMunicipality.isPresent()) {
return existingMunicipality.get();
} else {
Municipality municipality = new Municipality();
municipality.setCode(code);
municipality.setNameFI(codeToFi.get(code));
municipality.setNameSV(codeToSv.get(code));
municipalityRepository.saveAndFlush(municipality);
return municipality;
}
}

private List<KoodistoEntry> deserializeJson(final InputStream is) throws IOException {
return OBJECT_MAPPER.readValue(is, new TypeReference<>() {});
}

@JsonIgnoreProperties(ignoreUnknown = true)
private record KoodistoEntry(@NonNull String koodiArvo, @NonNull String fi, @NonNull String sv) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import fi.oph.vkt.api.dto.PublicMunicipalityDTO;
import fi.oph.vkt.model.ExamEvent;
import fi.oph.vkt.model.Examiner;
import fi.oph.vkt.model.ExaminerMunicipality;
import fi.oph.vkt.model.Municipality;
import fi.oph.vkt.model.type.ExamLanguage;
import fi.oph.vkt.repository.ExaminerRepository;
import java.util.ArrayList;
Expand All @@ -21,8 +21,8 @@ public class PublicExaminerService {

private final ExaminerRepository examinerRepository;

private static PublicMunicipalityDTO toPublicMunicipalityDTO(ExaminerMunicipality municipality) {
return PublicMunicipalityDTO.builder().fi(municipality.getNameFi()).sv(municipality.getNameSv()).build();
private static PublicMunicipalityDTO toPublicMunicipalityDTO(Municipality municipality) {
return PublicMunicipalityDTO.builder().fi(municipality.getNameFI()).sv(municipality.getNameSV()).build();
}

private static PublicExaminerExamDateDTO toPublicExaminerExamDateDTO(ExamEvent examEvent) {
Expand Down
Loading

0 comments on commit a8565a7

Please sign in to comment.