Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added school funding codes #234

Merged
merged 3 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading