Skip to content

Commit

Permalink
Working school endpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
arcshiftsolutions committed Jun 8, 2022
1 parent 396eb1a commit 890d51c
Show file tree
Hide file tree
Showing 17 changed files with 737 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package ca.bc.gov.educ.api.institute.controller.v1;

import ca.bc.gov.educ.api.institute.endpoint.v1.SchoolAPIEndpoint;
import ca.bc.gov.educ.api.institute.exception.EntityNotFoundException;
import ca.bc.gov.educ.api.institute.exception.InvalidPayloadException;
import ca.bc.gov.educ.api.institute.exception.errors.ApiError;
import ca.bc.gov.educ.api.institute.mapper.v1.SchoolMapper;
import ca.bc.gov.educ.api.institute.service.v1.SchoolHistoryService;
import ca.bc.gov.educ.api.institute.service.v1.SchoolService;
import ca.bc.gov.educ.api.institute.struct.v1.School;
import ca.bc.gov.educ.api.institute.struct.v1.SchoolHistory;
import ca.bc.gov.educ.api.institute.util.RequestUtil;
import ca.bc.gov.educ.api.institute.validator.SchoolPayloadValidator;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.springframework.http.HttpStatus.BAD_REQUEST;

@RestController
@Slf4j
public class SchoolAPIController implements SchoolAPIEndpoint {

private static final SchoolMapper mapper = SchoolMapper.mapper;
@Getter(AccessLevel.PRIVATE)
private final SchoolService schoolService;
@Getter(AccessLevel.PRIVATE)
private final SchoolHistoryService schoolHistoryService;

@Getter(AccessLevel.PRIVATE)
private final SchoolPayloadValidator payloadValidator;

@Autowired
public SchoolAPIController(final SchoolService schoolService, final SchoolHistoryService schoolHistoryService, final SchoolPayloadValidator payloadValidator) {
this.schoolService = schoolService;
this.schoolHistoryService = schoolHistoryService;
this.payloadValidator = payloadValidator;
}

@Override
public School getSchool(String schoolId) {
UUID schoolUUID;
try{
schoolUUID = UUID.fromString(schoolId);
}catch(Exception e){
final ApiError error = ApiError.builder().timestamp(LocalDateTime.now()).message("Invalid school ID").status(BAD_REQUEST).build();
throw new InvalidPayloadException(error);
}

var school = getSchoolService().getSchool(schoolUUID);

if(school.isPresent()){
return mapper.toStructure(school.get());
}else{
throw new EntityNotFoundException();
}
}

@Override
public List<SchoolHistory> getSchoolHistory(String schoolId) {
UUID schoolUUID;
try{
schoolUUID = UUID.fromString(schoolId);
}catch(Exception e){
final ApiError error = ApiError.builder().timestamp(LocalDateTime.now()).message("Invalid school history ID").status(BAD_REQUEST).build();
throw new InvalidPayloadException(error);
}

return getSchoolHistoryService().getAllSchoolHistoryList(schoolUUID).stream().map(mapper::toStructure).collect(Collectors.toList());
}

@Override
public School createSchool(School school) {
validatePayload(() -> getPayloadValidator().validateCreatePayload(school));
RequestUtil.setAuditColumnsForCreate(school);
return mapper.toStructure(schoolService.createSchool(school));
}

@Override
public School updateSchool(UUID id, School school) {
validatePayload(() -> getPayloadValidator().validateUpdatePayload(school));
RequestUtil.setAuditColumnsForUpdate(school);
return mapper.toStructure(schoolService.updateSchool(school, id));
}

@Override
@Transactional
public ResponseEntity<Void> deleteSchool(UUID id) {
getSchoolService().deleteSchool(id);
return ResponseEntity.noContent().build();
}

private void validatePayload(Supplier<List<FieldError>> validator) {
val validationResult = validator.get();
if (!validationResult.isEmpty()) {
ApiError error = ApiError.builder().timestamp(LocalDateTime.now()).message("Payload contains invalid data.").status(BAD_REQUEST).build();
error.addValidationErrors(validationResult);
throw new InvalidPayloadException(error);
}
}

@Override
public List<School> getAllSchools() {
return getSchoolService().getAllSchoolsList().stream().map(mapper::toStructure).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package ca.bc.gov.educ.api.institute.endpoint.v1;

import ca.bc.gov.educ.api.institute.constants.v1.URL;
import ca.bc.gov.educ.api.institute.struct.v1.School;
import ca.bc.gov.educ.api.institute.struct.v1.SchoolHistory;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

import static org.springframework.http.HttpStatus.CREATED;

@RequestMapping(URL.BASE_URL_SCHOOL)
@OpenAPIDefinition(info = @Info(title = "API to School CRUD.", description = "This API is related to school data.", version = "1"),
security = {@SecurityRequirement(name = "OAUTH2", scopes = {"READ_SCHOOL", "WRITE_SCHOOL", "DELETE_SCHOOL"})})
public interface SchoolAPIEndpoint {

@GetMapping("/{schoolId}")
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional(readOnly = true)
@Tag(name = "Endpoint to get school entity.", description = "Endpoint to get school entity by ID.")
@Schema(name = "School", implementation = School.class)
School getSchool(@PathVariable("schoolId") String schoolId);

@GetMapping("/{schoolId}/history")
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional(readOnly = true)
@Tag(name = "Endpoint to get school history entity list by school ID.", description = "Endpoint to get school history entity list by school ID.")
@Schema(name = "SchoolHistory", implementation = SchoolHistory.class)
List<SchoolHistory> getSchoolHistory(@PathVariable("schoolId") String schoolId);

@PostMapping
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "CREATED"), @ApiResponse(responseCode = "400", description = "BAD REQUEST")})
@Tag(name = "Endpoint to create school entity.", description = "Endpoint to create school entity.")
@Schema(name = "School", implementation = School.class)
@ResponseStatus(CREATED)
School createSchool(@Validated @RequestBody School school) throws JsonProcessingException;

@PutMapping("/{id}")
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Tag(name = "Endpoint to update school entity.", description = "Endpoint to update school entity.")
@Schema(name = "School", implementation = School.class)
School updateSchool(@PathVariable UUID id, @Validated @RequestBody School school) throws JsonProcessingException;

@DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('SCOPE_DELETE_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "NO CONTENT"), @ApiResponse(responseCode = "404", description = "NOT FOUND."), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
@Tag(name = "Endpoint to delete school entity.", description = "Endpoint to delete school entity.")
ResponseEntity<Void> deleteSchool(@PathVariable UUID id);

@GetMapping
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
@Transactional(readOnly = true)
@Tag(name = "Endpoint to get all school entities.", description = "Endpoint to get all school entities.")
@Schema(name = "School", implementation = School.class)
List<School> getAllSchools();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ca.bc.gov.educ.api.institute.mapper.v1;

import ca.bc.gov.educ.api.institute.mapper.LocalDateTimeMapper;
import ca.bc.gov.educ.api.institute.mapper.StringMapper;
import ca.bc.gov.educ.api.institute.mapper.UUIDMapper;
import ca.bc.gov.educ.api.institute.model.v1.SchoolEntity;
import ca.bc.gov.educ.api.institute.model.v1.SchoolHistoryEntity;
import ca.bc.gov.educ.api.institute.struct.v1.School;
import ca.bc.gov.educ.api.institute.struct.v1.SchoolHistory;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper(uses = {UUIDMapper.class, LocalDateTimeMapper.class, StringMapper.class})
@SuppressWarnings("squid:S1214")
public interface SchoolMapper {

SchoolMapper mapper = Mappers.getMapper(SchoolMapper.class);

@Mapping(target = "updateUser", ignore = true)
@Mapping(target = "updateDate", ignore = true)
@Mapping(target = "createUser", ignore = true)
@Mapping(target = "createDate", ignore = true)
SchoolEntity toModel(School structure);

School toStructure(SchoolEntity entity);

@Mapping(target = "updateUser", ignore = true)
@Mapping(target = "updateDate", ignore = true)
@Mapping(target = "createUser", ignore = true)
@Mapping(target = "createDate", ignore = true)
SchoolHistoryEntity toModel(SchoolHistory structure);

SchoolHistory toStructure(SchoolHistoryEntity entity);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ public class AddressHistoryEntity {
@Column(name = "address_history_id", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID addressHistoryId;
@Basic
@Column(name = "address_id")
@Column(name = "address_id", columnDefinition = "BINARY(16)")
private UUID addressId;
@Basic
@Column(name = "school_id")
@Column(name = "school_id", columnDefinition = "BINARY(16)")
private UUID schoolId;
@Basic
@Column(name = "district_id")
@Column(name = "district_id", columnDefinition = "BINARY(16)")
private UUID districtId;
@Basic
@Column(name = "independent_authority_id")
@Column(name = "independent_authority_id", columnDefinition = "BINARY(16)")
private UUID independentAuthorityId;
@Basic
@Column(name = "address_line_1")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package ca.bc.gov.educ.api.institute.model.v1;

import ca.bc.gov.educ.api.institute.util.UpperCase;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
Expand All @@ -23,7 +26,7 @@ public class DistrictHistoryEntity {
@Column(name = "district_history_id", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID districtHistoryId;
@Basic
@Column(name = "district_id")
@Column(name = "district_id", columnDefinition = "BINARY(16)")
private UUID districtId;
@Basic
@Column(name = "district_number")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ca.bc.gov.educ.api.institute.model.v1;

import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
Expand All @@ -22,7 +25,7 @@ public class IndependentAuthorityHistoryEntity {
@Column(name = "independent_authority_history_id", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID independentAuthorityHistoryId;
@Basic
@Column(name = "independent_authority_id")
@Column(name = "independent_authority_id", columnDefinition = "BINARY(16)")
private UUID independentAuthorityId;
@Basic
@Column(name = "authority_number")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public class SchoolEntity {
@Column(name = "school_id", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID schoolId;
@Basic
@Column(name = "district_id")
@Column(name = "district_id", columnDefinition = "BINARY(16)")
private UUID districtId;
@Basic
@Column(name = "independent_authority_id")
@Column(name = "independent_authority_id", columnDefinition = "BINARY(16)")
private UUID independentAuthorityId;
@Basic
@Column(name = "school_number")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ca.bc.gov.educ.api.institute.model.v1;

import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
Expand All @@ -22,13 +25,13 @@ public class SchoolHistoryEntity {
@Column(name = "school_history_id", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID schoolHistoryId;
@Basic
@Column(name = "school_id")
@Column(name = "school_id", columnDefinition = "BINARY(16)")
private UUID schoolId;
@Basic
@Column(name = "district_id")
@Column(name = "district_id", columnDefinition = "BINARY(16)")
private UUID districtId;
@Basic
@Column(name = "independent_authority_id")
@Column(name = "independent_authority_id", columnDefinition = "BINARY(16)")
private UUID independentAuthorityId;
@Basic
@Column(name = "school_number")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import ca.bc.gov.educ.api.institute.model.v1.DistrictHistoryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface DistrictHistoryRepository extends JpaRepository<DistrictHistoryEntity, UUID> {
public interface DistrictHistoryRepository extends JpaRepository<DistrictHistoryEntity, UUID>, JpaSpecificationExecutor<DistrictHistoryEntity> {

List<DistrictHistoryEntity> findAllByDistrictId(UUID districtId);
List<DistrictHistoryEntity> findByDistrictId(UUID districtId);
void deleteByDistrictId(UUID districtId);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package ca.bc.gov.educ.api.institute.repository.v1;

import ca.bc.gov.educ.api.institute.model.v1.DistrictHistoryEntity;
import ca.bc.gov.educ.api.institute.model.v1.SchoolHistoryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface SchoolHistoryRepository extends JpaRepository<SchoolHistoryEntity, UUID> {
public interface SchoolHistoryRepository extends JpaRepository<SchoolHistoryEntity, UUID>, JpaSpecificationExecutor<DistrictHistoryEntity> {

}
List<SchoolHistoryEntity> findBySchoolId(UUID districtId);

void deleteBySchoolId(UUID schoolId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ public void createDistrictHistory(DistrictEntity curDistrictEntity, String updat
}

public List<DistrictHistoryEntity> getAllDistrictHistoryList(UUID districtId) {
return districtHistoryRepository.findAllByDistrictId(districtId);
return districtHistoryRepository.findByDistrictId(districtId);
}
}
Loading

0 comments on commit 890d51c

Please sign in to comment.