Skip to content

Commit 143470a

Browse files
authored
Merge pull request #234 from bcgov/feature/schoolFunding
Added school funding codes
2 parents aca4436 + 8cd5cd2 commit 143470a

28 files changed

+1588
-26
lines changed

api/src/main/java/ca/bc/gov/educ/api/institute/constants/v1/URL.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ca.bc.gov.educ.api.institute.constants.v1;
22

33
public final class URL {
4-
public static final String SCHOOL_BY_ID = "/{schoolId}";
54
public static final String CATEGORY_CODES = "/category-codes";
65
public static final String GRADE_CODES = "/grade-codes";
76
public static final String FACILITY_TYPE_CODES = "/facility-codes";
@@ -12,12 +11,10 @@ public final class URL {
1211
public static final String AUTHORITY_GROUP_CODES = "/authority-group-codes";
1312
public static final String AUTHORITY_TYPE_CODES = "/authority-type-codes";
1413
public static final String DISTRICT_CONTACT_TYPE_CODES = "/district-contact-type-codes";
15-
1614
public static final String SCHOOL_CONTACT_TYPE_CODES = "/school-contact-type-codes";
17-
1815
public static final String AUTHORITY_CONTACT_TYPE_CODES = "/authority-contact-type-codes";
1916
public static final String PROVINCE_CODES = "/province-codes";
20-
17+
public static final String FUNDING_GROUP_CODES = "/funding-group-codes";
2118
public static final String COUNTRY_CODES = "/country-codes";
2219
public static final String DISTRICT_REGION_CODES = "/district-region-codes";
2320
public static final String DISTRICT_STATUS_CODES = "/district-status-codes";
@@ -29,4 +26,5 @@ private URL(){
2926
public static final String BASE_URL_DISTRICT="/api/v1/institute/district";
3027
public static final String BASE_URL_SCHOOL="/api/v1/institute/school";
3128
public static final String BASE_URL_AUTHORITY="/api/v1/institute/authority";
29+
public static final String BASE_URL_SCHOOL_FUNDING="/api/v1/institute/schoolFundingGroup";
3230
}

api/src/main/java/ca/bc/gov/educ/api/institute/controller/v1/CodeTableAPIController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public List<AddressTypeCode> getAddressTypeCodes() {
3030
return getService().getAddressTypeCodesList().stream().map(mapper::toStructure).collect(Collectors.toList());
3131
}
3232

33+
@Override
34+
public List<SchoolFundingGroupCode> getIndependentSchoolFundingGroupCodes() {
35+
return getService().getAllSchoolFundingGroupCodes().stream().map(mapper::toStructure).toList();
36+
}
37+
3338
@Override
3439
public List<ProvinceCode> getProvinceCodes() {
3540
return getService().getProvinceCodesList().stream().map(mapper::toStructure).collect(Collectors.toList());
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package ca.bc.gov.educ.api.institute.controller.v1;
2+
3+
import ca.bc.gov.educ.api.institute.endpoint.v1.IndependentSchoolFundingGroupEndpoint;
4+
import ca.bc.gov.educ.api.institute.exception.EntityNotFoundException;
5+
import ca.bc.gov.educ.api.institute.exception.InvalidPayloadException;
6+
import ca.bc.gov.educ.api.institute.exception.errors.ApiError;
7+
import ca.bc.gov.educ.api.institute.mapper.v1.IndependentSchoolFundingGroupMapper;
8+
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupEntity;
9+
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupHistoryEntity;
10+
import ca.bc.gov.educ.api.institute.service.v1.IndependentSchoolFundingGroupService;
11+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroup;
12+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
13+
import ca.bc.gov.educ.api.institute.util.RequestUtil;
14+
import ca.bc.gov.educ.api.institute.util.ValidationUtil;
15+
import ca.bc.gov.educ.api.institute.validator.IndependentSchoolFundingGroupPayloadValidator;
16+
import com.fasterxml.jackson.core.JsonProcessingException;
17+
import lombok.extern.slf4j.Slf4j;
18+
import lombok.val;
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.http.ResponseEntity;
21+
import org.springframework.transaction.annotation.Transactional;
22+
import org.springframework.validation.FieldError;
23+
import org.springframework.web.bind.annotation.RestController;
24+
25+
import java.time.LocalDateTime;
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
import java.util.Optional;
29+
import java.util.UUID;
30+
import java.util.function.Supplier;
31+
32+
import static org.springframework.http.HttpStatus.BAD_REQUEST;
33+
34+
@RestController
35+
@Slf4j
36+
public class IndependentSchoolFundingGroupController implements IndependentSchoolFundingGroupEndpoint {
37+
38+
private static final IndependentSchoolFundingGroupMapper independentSchoolFundingGroupMapper = IndependentSchoolFundingGroupMapper.mapper;
39+
private final IndependentSchoolFundingGroupPayloadValidator independentSchoolFundingGroupPayloadValidator;
40+
private final IndependentSchoolFundingGroupService independentSchoolFundingGroupService;
41+
42+
@Autowired
43+
public IndependentSchoolFundingGroupController(IndependentSchoolFundingGroupPayloadValidator independentSchoolFundingGroupPayloadValidator, IndependentSchoolFundingGroupService independentSchoolFundingGroupService) {
44+
this.independentSchoolFundingGroupPayloadValidator = independentSchoolFundingGroupPayloadValidator;
45+
this.independentSchoolFundingGroupService = independentSchoolFundingGroupService;
46+
}
47+
48+
private void validatePayload(Supplier<List<FieldError>> validator) {
49+
val validationResult = validator.get();
50+
if (!validationResult.isEmpty()) {
51+
ApiError error = ApiError.builder().timestamp(LocalDateTime.now()).message("Payload contains invalid data.").status(BAD_REQUEST).build();
52+
error.addValidationErrors(validationResult);
53+
throw new InvalidPayloadException(error);
54+
}
55+
}
56+
57+
@Override
58+
public IndependentSchoolFundingGroup getIndependentSchoolFundingGroup(UUID schoolFundingGroupID) {
59+
Optional<IndependentSchoolFundingGroupEntity> independentSchoolFundingGroup = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroup(schoolFundingGroupID);
60+
61+
if (independentSchoolFundingGroup.isPresent()) {
62+
return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroup.get());
63+
} else {
64+
throw new EntityNotFoundException();
65+
}
66+
}
67+
68+
@Override
69+
public List<IndependentSchoolFundingGroup> getIndependentSchoolFundingGroups(UUID schoolID) {
70+
List<IndependentSchoolFundingGroupEntity> independentSchoolFundingGroups = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroups(schoolID);
71+
72+
List<IndependentSchoolFundingGroup> independentSchoolFundingGroupList = new ArrayList<>();
73+
for(IndependentSchoolFundingGroupEntity entity: independentSchoolFundingGroups){
74+
independentSchoolFundingGroupList.add(independentSchoolFundingGroupMapper.toStructure(entity));
75+
}
76+
77+
return independentSchoolFundingGroupList;
78+
}
79+
80+
@Override
81+
public List<IndependentSchoolFundingGroupHistory> getIndependentSchoolFundingGroupHistory(UUID schoolID) {
82+
List<IndependentSchoolFundingGroupHistoryEntity> independentSchoolFundingGroups = this.independentSchoolFundingGroupService.getIndependentSchoolFundingGroupHistory(schoolID);
83+
84+
List<IndependentSchoolFundingGroupHistory> independentSchoolFundingGroupList = new ArrayList<>();
85+
for(IndependentSchoolFundingGroupHistoryEntity entity: independentSchoolFundingGroups){
86+
independentSchoolFundingGroupList.add(independentSchoolFundingGroupMapper.toStructure(entity));
87+
}
88+
89+
return independentSchoolFundingGroupList;
90+
}
91+
92+
@Override
93+
public IndependentSchoolFundingGroup createIndependentSchoolFundingGroup(IndependentSchoolFundingGroup fundingGroup) throws JsonProcessingException {
94+
validatePayload(() -> this.independentSchoolFundingGroupPayloadValidator.validateCreatePayload(fundingGroup));
95+
RequestUtil.setAuditColumnsForCreate(fundingGroup);
96+
97+
return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroupService.createIndependentSchoolFundingGroup(fundingGroup));
98+
}
99+
100+
@Override
101+
public IndependentSchoolFundingGroup updateIndependentSchoolFundingGroup(UUID schoolFundingGroupID, IndependentSchoolFundingGroup independentSchoolFundingGroup) {
102+
ValidationUtil.validatePayload(() -> this.independentSchoolFundingGroupPayloadValidator.validatePayload(independentSchoolFundingGroup, false));
103+
RequestUtil.setAuditColumnsForUpdate(independentSchoolFundingGroup);
104+
return independentSchoolFundingGroupMapper.toStructure(independentSchoolFundingGroupService.updateIndependentSchoolFundingGroup(independentSchoolFundingGroup));
105+
}
106+
107+
@Override
108+
@Transactional
109+
public ResponseEntity<Void> deleteIndependentSchoolFundingGroup(UUID schoolFundingGroupID) {
110+
this.independentSchoolFundingGroupService.deleteIndependentSchoolFundingGroup(schoolFundingGroupID);
111+
return ResponseEntity.noContent().build();
112+
}
113+
}

api/src/main/java/ca/bc/gov/educ/api/institute/endpoint/v1/CodeTableAPIEndpoint.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ public interface CodeTableAPIEndpoint {
3838
@Schema(name = "ProvinceCode", implementation = ProvinceCode.class)
3939
List<ProvinceCode> getProvinceCodes();
4040

41+
@PreAuthorize("hasAuthority('SCOPE_READ_COLLECTION_CODES')")
42+
@GetMapping(URL.FUNDING_GROUP_CODES)
43+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
44+
@Transactional(readOnly = true)
45+
@Tag(name = "Collection Codes", description = "Endpoints to get collection codes.")
46+
@Schema(name = "SchoolFundingGroupCodes", implementation = SchoolFundingGroupCode.class)
47+
List<SchoolFundingGroupCode> getIndependentSchoolFundingGroupCodes();
48+
4149
@PreAuthorize("hasAuthority('SCOPE_READ_INSTITUTE_CODES')")
4250
@GetMapping(URL.COUNTRY_CODES)
4351
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package ca.bc.gov.educ.api.institute.endpoint.v1;
2+
3+
import ca.bc.gov.educ.api.institute.constants.v1.URL;
4+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroup;
5+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
6+
import com.fasterxml.jackson.core.JsonProcessingException;
7+
import io.swagger.v3.oas.annotations.media.Schema;
8+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
9+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
10+
import io.swagger.v3.oas.annotations.tags.Tag;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.security.access.prepost.PreAuthorize;
13+
import org.springframework.transaction.annotation.Transactional;
14+
import org.springframework.validation.annotation.Validated;
15+
import org.springframework.web.bind.annotation.*;
16+
17+
import java.util.List;
18+
import java.util.UUID;
19+
20+
import static org.springframework.http.HttpStatus.CREATED;
21+
import static org.springframework.http.HttpStatus.NO_CONTENT;
22+
23+
@RequestMapping(URL.BASE_URL_SCHOOL_FUNDING)
24+
public interface IndependentSchoolFundingGroupEndpoint {
25+
26+
@GetMapping("/{schoolFundingGroupID}")
27+
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
28+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
29+
@Transactional(readOnly = true)
30+
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
31+
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
32+
IndependentSchoolFundingGroup getIndependentSchoolFundingGroup(@PathVariable("schoolFundingGroupID") UUID schoolFundingGroupID);
33+
34+
@GetMapping("/search/{schoolID}")
35+
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
36+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
37+
@Transactional(readOnly = true)
38+
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
39+
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
40+
List<IndependentSchoolFundingGroup> getIndependentSchoolFundingGroups(@PathVariable("schoolID") UUID schoolID);
41+
42+
@GetMapping("/search/{schoolID}/history")
43+
@PreAuthorize("hasAuthority('SCOPE_READ_SCHOOL_FUNDING_GROUP')")
44+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
45+
@Transactional(readOnly = true)
46+
@Tag(name = "IndependentSchoolFundingGroupHistory Entity", description = "Endpoints for independent school group funding history entities.")
47+
@Schema(name = "IndependentSchoolFundingGroupHistory", implementation = IndependentSchoolFundingGroupHistory.class)
48+
List<IndependentSchoolFundingGroupHistory> getIndependentSchoolFundingGroupHistory(@PathVariable("schoolID") UUID schoolID);
49+
50+
@PostMapping()
51+
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL_FUNDING_GROUP')")
52+
@ApiResponses(value = {@ApiResponse(responseCode = "201", description = "CREATED"), @ApiResponse(responseCode = "400", description = "BAD REQUEST")})
53+
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
54+
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
55+
@ResponseStatus(CREATED)
56+
IndependentSchoolFundingGroup createIndependentSchoolFundingGroup(@Validated @RequestBody IndependentSchoolFundingGroup fundingGroup) throws JsonProcessingException;
57+
58+
@PutMapping("/{schoolFundingGroupID}")
59+
@PreAuthorize("hasAuthority('SCOPE_WRITE_SCHOOL_FUNDING_GROUP')")
60+
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
61+
@Transactional
62+
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
63+
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
64+
IndependentSchoolFundingGroup updateIndependentSchoolFundingGroup(@PathVariable("schoolFundingGroupID") UUID schoolFundingGroupID, @Validated @RequestBody IndependentSchoolFundingGroup independentSchoolFundingGroup);
65+
66+
@DeleteMapping("/{schoolFundingGroupID}")
67+
@PreAuthorize("hasAuthority('SCOPE_DELETE_SCHOOL_FUNDING_GROUP')")
68+
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "NO CONTENT"), @ApiResponse(responseCode = "404", description = "NOT FOUND")})
69+
@Tag(name = "IndependentSchoolFundingGroup Entity", description = "Endpoints for independent school group funding entity.")
70+
@Schema(name = "IndependentSchoolFundingGroup", implementation = IndependentSchoolFundingGroup.class)
71+
@ResponseStatus(NO_CONTENT)
72+
ResponseEntity<Void> deleteIndependentSchoolFundingGroup(@PathVariable UUID schoolFundingGroupID);
73+
}

api/src/main/java/ca/bc/gov/educ/api/institute/mapper/v1/CodeTableMapper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import ca.bc.gov.educ.api.institute.model.v1.*;
66
import ca.bc.gov.educ.api.institute.struct.v1.*;
77
import org.mapstruct.Mapper;
8-
import org.mapstruct.Mapping;
98
import org.mapstruct.factory.Mappers;
109

1110
/**
@@ -92,4 +91,6 @@ public interface CodeTableMapper {
9291
SchoolReportingRequirementCodeEntity toModel(SchoolReportingRequirementCode structure);
9392

9493
SchoolReportingRequirementCode toStructure(SchoolReportingRequirementCodeEntity entity);
94+
95+
SchoolFundingGroupCode toStructure(SchoolFundingGroupCodeEntity entity);
9596
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package ca.bc.gov.educ.api.institute.mapper.v1;
2+
3+
import ca.bc.gov.educ.api.institute.mapper.LocalDateTimeMapper;
4+
import ca.bc.gov.educ.api.institute.mapper.UUIDMapper;
5+
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupEntity;
6+
import ca.bc.gov.educ.api.institute.model.v1.IndependentSchoolFundingGroupHistoryEntity;
7+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroup;
8+
import ca.bc.gov.educ.api.institute.struct.v1.IndependentSchoolFundingGroupHistory;
9+
import org.mapstruct.Mapper;
10+
import org.mapstruct.factory.Mappers;
11+
12+
@Mapper(uses = {UUIDMapper.class, LocalDateTimeMapper.class})
13+
@SuppressWarnings("squid:S1214")
14+
public interface IndependentSchoolFundingGroupMapper {
15+
16+
IndependentSchoolFundingGroupMapper mapper = Mappers.getMapper(IndependentSchoolFundingGroupMapper.class);
17+
18+
IndependentSchoolFundingGroupEntity toModel(IndependentSchoolFundingGroup structure);
19+
20+
IndependentSchoolFundingGroup toStructure(IndependentSchoolFundingGroupEntity entity);
21+
IndependentSchoolFundingGroupHistoryEntity toModel(IndependentSchoolFundingGroupHistory structure);
22+
23+
IndependentSchoolFundingGroupHistory toStructure(IndependentSchoolFundingGroupHistoryEntity entity);
24+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package ca.bc.gov.educ.api.institute.model.v1;
2+
3+
import ca.bc.gov.educ.api.institute.util.UpperCase;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import jakarta.persistence.*;
6+
import jakarta.validation.constraints.PastOrPresent;
7+
import lombok.AllArgsConstructor;
8+
import lombok.Builder;
9+
import lombok.Data;
10+
import lombok.NoArgsConstructor;
11+
import org.hibernate.annotations.DynamicUpdate;
12+
import org.hibernate.annotations.GenericGenerator;
13+
import org.hibernate.annotations.Parameter;
14+
15+
import java.time.LocalDateTime;
16+
import java.util.UUID;
17+
18+
@Data
19+
@NoArgsConstructor
20+
@AllArgsConstructor
21+
@DynamicUpdate
22+
@Entity
23+
@Builder
24+
@Table(name = "INDEPENDENT_SCHOOL_FUNDING_GROUP")
25+
@JsonIgnoreProperties(ignoreUnknown = true)
26+
public class IndependentSchoolFundingGroupEntity {
27+
28+
@Id
29+
@GeneratedValue(generator = "UUID")
30+
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator", parameters = {
31+
@Parameter(name = "uuid_gen_strategy_class", value = "org.hibernate.id.uuid.CustomVersionOneStrategy")})
32+
@Column(name = "SCHOOL_FUNDING_GROUP_ID", unique = true, updatable = false, columnDefinition = "BINARY(16)")
33+
private UUID schoolFundingGroupID;
34+
35+
@Basic
36+
@Column(name = "SCHOOL_ID", columnDefinition = "BINARY(16)")
37+
private UUID schoolID;
38+
39+
@Column(name = "SCHOOL_GRADE_CODE", nullable = false, length = 10)
40+
@UpperCase
41+
private String schoolGradeCode;
42+
43+
@Column(name = "SCHOOL_FUNDING_GROUP_CODE", nullable = false, length = 10)
44+
@UpperCase
45+
private String schoolFundingGroupCode;
46+
47+
@Column(name = "CREATE_USER", updatable = false , length = 32)
48+
private String createUser;
49+
50+
@PastOrPresent
51+
@Column(name = "CREATE_DATE", updatable = false)
52+
private LocalDateTime createDate;
53+
54+
@Column(name = "UPDATE_USER", length = 32)
55+
private String updateUser;
56+
57+
@PastOrPresent
58+
@Column(name = "UPDATE_DATE")
59+
private LocalDateTime updateDate;
60+
61+
}

0 commit comments

Comments
 (0)