Skip to content

Commit

Permalink
Merge pull request #234 from bcgov/feature/schoolFunding
Browse files Browse the repository at this point in the history
Added school funding codes
  • Loading branch information
mightycox authored May 1, 2024
2 parents aca4436 + 8cd5cd2 commit 143470a
Show file tree
Hide file tree
Showing 28 changed files with 1,588 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ca.bc.gov.educ.api.institute.constants.v1;

public final class URL {
public static final String SCHOOL_BY_ID = "/{schoolId}";
public static final String CATEGORY_CODES = "/category-codes";
public static final String GRADE_CODES = "/grade-codes";
public static final String FACILITY_TYPE_CODES = "/facility-codes";
Expand All @@ -12,12 +11,10 @@ public final class URL {
public static final String AUTHORITY_GROUP_CODES = "/authority-group-codes";
public static final String AUTHORITY_TYPE_CODES = "/authority-type-codes";
public static final String DISTRICT_CONTACT_TYPE_CODES = "/district-contact-type-codes";

public static final String SCHOOL_CONTACT_TYPE_CODES = "/school-contact-type-codes";

public static final String AUTHORITY_CONTACT_TYPE_CODES = "/authority-contact-type-codes";
public static final String PROVINCE_CODES = "/province-codes";

public static final String FUNDING_GROUP_CODES = "/funding-group-codes";
public static final String COUNTRY_CODES = "/country-codes";
public static final String DISTRICT_REGION_CODES = "/district-region-codes";
public static final String DISTRICT_STATUS_CODES = "/district-status-codes";
Expand All @@ -29,4 +26,5 @@ private URL(){
public static final String BASE_URL_DISTRICT="/api/v1/institute/district";
public static final String BASE_URL_SCHOOL="/api/v1/institute/school";
public static final String BASE_URL_AUTHORITY="/api/v1/institute/authority";
public static final String BASE_URL_SCHOOL_FUNDING="/api/v1/institute/schoolFundingGroup";
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public List<AddressTypeCode> getAddressTypeCodes() {
return getService().getAddressTypeCodesList().stream().map(mapper::toStructure).collect(Collectors.toList());
}

@Override
public List<SchoolFundingGroupCode> getIndependentSchoolFundingGroupCodes() {
return getService().getAllSchoolFundingGroupCodes().stream().map(mapper::toStructure).toList();
}

@Override
public List<ProvinceCode> getProvinceCodes() {
return getService().getProvinceCodesList().stream().map(mapper::toStructure).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ca.bc.gov.educ.api.institute.controller.v1;

import ca.bc.gov.educ.api.institute.endpoint.v1.IndependentSchoolFundingGroupEndpoint;
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.IndependentSchoolFundingGroupMapper;
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupEntity;
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupHistoryEntity;
import ca.bc.gov.educ.api.institute.service.v1.IndependentSchoolFundingGroupService;
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroup;
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
import ca.bc.gov.educ.api.institute.util.RequestUtil;
import ca.bc.gov.educ.api.institute.util.ValidationUtil;
import ca.bc.gov.educ.api.institute.validator.IndependentSchoolFundingGroupPayloadValidator;
import com.fasterxml.jackson.core.JsonProcessingException;
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.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Supplier;

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

@RestController
@Slf4j
public class IndependentSchoolFundingGroupController implements IndependentSchoolFundingGroupEndpoint {

private static final IndependentSchoolFundingGroupMapper independentSchoolFundingGroupMapper = IndependentSchoolFundingGroupMapper.mapper;
private final IndependentSchoolFundingGroupPayloadValidator independentSchoolFundingGroupPayloadValidator;
private final IndependentSchoolFundingGroupService independentSchoolFundingGroupService;

@Autowired
public IndependentSchoolFundingGroupController(IndependentSchoolFundingGroupPayloadValidator independentSchoolFundingGroupPayloadValidator, IndependentSchoolFundingGroupService independentSchoolFundingGroupService) {
this.independentSchoolFundingGroupPayloadValidator = independentSchoolFundingGroupPayloadValidator;
this.independentSchoolFundingGroupService = independentSchoolFundingGroupService;
}

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 IndependentSchoolFundingGroup getIndependentSchoolFundingGroup(UUID schoolFundingGroupID) {
Optional<IndependentSchoolFundingGroupEntity> independentSchoolFundingGroup = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroup(schoolFundingGroupID);

if (independentSchoolFundingGroup.isPresent()) {
return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroup.get());
} else {
throw new EntityNotFoundException();
}
}

@Override
public List<IndependentSchoolFundingGroup> getIndependentSchoolFundingGroups(UUID schoolID) {
List<IndependentSchoolFundingGroupEntity> independentSchoolFundingGroups = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroups(schoolID);

List<IndependentSchoolFundingGroup> independentSchoolFundingGroupList = new ArrayList<>();
for(IndependentSchoolFundingGroupEntity entity: independentSchoolFundingGroups){
independentSchoolFundingGroupList.add(independentSchoolFundingGroupMapper.toStructure(entity));
}

return independentSchoolFundingGroupList;
}

@Override
public List<IndependentSchoolFundingGroupHistory> getIndependentSchoolFundingGroupHistory(UUID schoolID) {
List<IndependentSchoolFundingGroupHistoryEntity> independentSchoolFundingGroups = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroupHistory(schoolID);

List<IndependentSchoolFundingGroupHistory> independentSchoolFundingGroupList = new ArrayList<>();
for(IndependentSchoolFundingGroupHistoryEntity entity: independentSchoolFundingGroups){
independentSchoolFundingGroupList.add(independentSchoolFundingGroupMapper.toStructure(entity));
}

return independentSchoolFundingGroupList;
}

@Override
public IndependentSchoolFundingGroup createIndependentSchoolFundingGroup(IndependentSchoolFundingGroup fundingGroup) throws JsonProcessingException {
validatePayload(() -> this.independentSchoolFundingGroupPayloadValidator.validateCreatePayload(fundingGroup));
RequestUtil.setAuditColumnsForCreate(fundingGroup);

return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroupService.createIndependentSchoolFundingGroup(fundingGroup));
}

@Override
public IndependentSchoolFundingGroup updateIndependentSchoolFundingGroup(UUID schoolFundingGroupID, IndependentSchoolFundingGroup independentSchoolFundingGroup) {
ValidationUtil.validatePayload(() -> this.independentSchoolFundingGroupPayloadValidator.validatePayload(independentSchoolFundingGroup, false));
RequestUtil.setAuditColumnsForUpdate(independentSchoolFundingGroup);
return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroupService.updateIndependentSchoolFundingGroup(independentSchoolFundingGroup));
}

@Override
@Transactional
public ResponseEntity<Void> deleteIndependentSchoolFundingGroup(UUID schoolFundingGroupID) {
this.independentSchoolFundingGroupService.deleteIndependentSchoolFundingGroup(schoolFundingGroupID);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ public interface CodeTableAPIEndpoint {
@Schema(name = "ProvinceCode", implementation = ProvinceCode.class)
List<ProvinceCode> getProvinceCodes();

@PreAuthorize("hasAuthority('SCOPE_READ_COLLECTION_CODES')")
@GetMapping(URL.FUNDING_GROUP_CODES)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
@Transactional(readOnly = true)
@Tag(name = "Collection Codes", description = "Endpoints to get collection codes.")
@Schema(name = "SchoolFundingGroupCodes", implementation = SchoolFundingGroupCode.class)
List<SchoolFundingGroupCode> getIndependentSchoolFundingGroupCodes();

@PreAuthorize("hasAuthority('SCOPE_READ_INSTITUTE_CODES')")
@GetMapping(URL.COUNTRY_CODES)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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.IndependentSchoolFundingGroup;
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
import com.fasterxml.jackson.core.JsonProcessingException;
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.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;
import static org.springframework.http.HttpStatus.NO_CONTENT;

@RequestMapping(URL.BASE_URL_SCHOOL_FUNDING)
public interface IndependentSchoolFundingGroupEndpoint {

@GetMapping("/{schoolFundingGroupID}")
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional(readOnly = true)
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
IndependentSchoolFundingGroup getIndependentSchoolFundingGroup(@PathVariable("schoolFundingGroupID") UUID schoolFundingGroupID);

@GetMapping("/search/{schoolID}")
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional(readOnly = true)
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
List<IndependentSchoolFundingGroup> getIndependentSchoolFundingGroups(@PathVariable("schoolID") UUID schoolID);

@GetMapping("/search/{schoolID}/history")
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional(readOnly = true)
@Tag(name = "IndependentSchoolFundingGroupHistory Entity", description = "Endpoints for independent school group funding history entities.")
@Schema(name = "IndependentSchoolFundingGroupHistory", implementation = IndependentSchoolFundingGroupHistory.class)
List<IndependentSchoolFundingGroupHistory> getIndependentSchoolFundingGroupHistory(@PathVariable("schoolID") UUID schoolID);

@PostMapping()
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "CREATED"), @ApiResponse(responseCode = "400", description = "BAD REQUEST")})
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
@ResponseStatus(CREATED)
IndependentSchoolFundingGroup createIndependentSchoolFundingGroup(@Validated @RequestBody IndependentSchoolFundingGroup fundingGroup) throws JsonProcessingException;

@PutMapping("/{schoolFundingGroupID}")
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Transactional
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
IndependentSchoolFundingGroup updateIndependentSchoolFundingGroup(@PathVariable("schoolFundingGroupID") UUID schoolFundingGroupID, @Validated @RequestBody IndependentSchoolFundingGroup independentSchoolFundingGroup);

@DeleteMapping("/{schoolFundingGroupID}")
@PreAuthorize("hasAuthority('SCOPE_DELETE_SCHOOL_FUNDING_GROUP')")
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "NO CONTENT"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
@ResponseStatus(NO_CONTENT)
ResponseEntity<Void> deleteIndependentSchoolFundingGroup(@PathVariable UUID schoolFundingGroupID);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import ca.bc.gov.educ.api.institute.model.v1.*;
import ca.bc.gov.educ.api.institute.struct.v1.*;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

/**
Expand Down Expand Up @@ -92,4 +91,6 @@ public interface CodeTableMapper {
SchoolReportingRequirementCodeEntity toModel(SchoolReportingRequirementCode structure);

SchoolReportingRequirementCode toStructure(SchoolReportingRequirementCodeEntity entity);

SchoolFundingGroupCode toStructure(SchoolFundingGroupCodeEntity entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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.UUIDMapper;
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupEntity;
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupHistoryEntity;
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroup;
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

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

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

IndependentSchoolFundingGroupEntity toModel(IndependentSchoolFundingGroup structure);

IndependentSchoolFundingGroup toStructure(IndependentSchoolFundingGroupEntity entity);
IndependentSchoolFundingGroupHistoryEntity toModel(IndependentSchoolFundingGroupHistory structure);

IndependentSchoolFundingGroupHistory toStructure(IndependentSchoolFundingGroupHistoryEntity entity);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package ca.bc.gov.educ.api.institute.model.v1;

import ca.bc.gov.educ.api.institute.util.UpperCase;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import jakarta.validation.constraints.PastOrPresent;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

import java.time.LocalDateTime;
import java.util.UUID;

@Data
@NoArgsConstructor
@AllArgsConstructor
@DynamicUpdate
@Entity
@Builder
@Table(name = "INDEPENDENT_SCHOOL_FUNDING_GROUP")
@JsonIgnoreProperties(ignoreUnknown = true)
public class IndependentSchoolFundingGroupEntity {

@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator", parameters = {
@Parameter(name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy")})
@Column(name = "SCHOOL_FUNDING_GROUP_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)")
private UUID schoolFundingGroupID;

@Basic
@Column(name = "SCHOOL_ID", columnDefinition = "BINARY(16)")
private UUID schoolID;

@Column(name = "SCHOOL_GRADE_CODE", nullable = false, length = 10)
@UpperCase
private String schoolGradeCode;

@Column(name = "SCHOOL_FUNDING_GROUP_CODE", nullable = false, length = 10)
@UpperCase
private String schoolFundingGroupCode;

@Column(name = "CREATE_USER", updatable = false , length = 32)
private String createUser;

@PastOrPresent
@Column(name = "CREATE_DATE", updatable = false)
private LocalDateTime createDate;

@Column(name = "UPDATE_USER", length = 32)
private String updateUser;

@PastOrPresent
@Column(name = "UPDATE_DATE")
private LocalDateTime updateDate;

}
Loading

0 comments on commit 143470a

Please sign in to comment.