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

GRAD2-3064 - Refactor institute endpoints in EDUC-GRAD-TRAX-API #378

Merged
merged 7 commits into from
Nov 27, 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
Expand Up @@ -122,29 +122,57 @@ public ResponseEntity<List<SchoolDetail>> getSchoolsBySchoolCategory(@RequestPar
return response.GET(schoolService.getSchoolDetailsBySchoolCategoryCode(schoolCategoryCode));
}

@GetMapping(EducGradTraxApiConstants.GRAD_SCHOOL_DETAIL_URL_MAPPING_V2 + EducGradTraxApiConstants.GET_SCHOOL_BY_CODE_MAPPING)
@GetMapping(EducGradTraxApiConstants.GRAD_SCHOOL_DETAIL_URL_MAPPING_V2 + EducGradTraxApiConstants.GET_SCHOOL_BY_SCHOOL_ID)
@PreAuthorize(PermissionsConstants.READ_SCHOOL_DATA)
@Operation(summary = "Find School Details by ID from cache", description = "Get School Details by ID from cache", tags = { "School" })
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "204", description = "NO CONTENT")})
public ResponseEntity<SchoolDetail> getSchoolDetailsById(@PathVariable UUID schoolId) {
log.debug("getSchoolDetailsById V2 : ");
SchoolDetail schoolDetailResponse = schoolService.getSchoolDetailBySchoolId(schoolId);
if(schoolDetailResponse != null) {
return response.GET(schoolDetailResponse);
}else {
return response.NOT_FOUND();
}
}

@GetMapping(EducGradTraxApiConstants.GRAD_SCHOOL_DETAIL_URL_MAPPING_V2 + EducGradTraxApiConstants.GET_SCHOOL_DETAIL_SEARCH_MAPPING)
@PreAuthorize(PermissionsConstants.READ_SCHOOL_DATA)
@Operation(summary = "Find School Details by Mincode from cache", description = "Get School Details by Mincode from cache", tags = { "School" })
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "204", description = "NO CONTENT")})
public ResponseEntity<SchoolDetail> getSchoolDetailsByMincode(@PathVariable String minCode) {
log.debug("getSchoolDetails V2 : ");
public ResponseEntity<SchoolDetail> getSchoolDetailsByParams(@RequestParam(required = false) String minCode) {
log.debug("getSchoolDetailsByParams V2 : ");
SchoolDetail schoolDetailResponse = schoolService.getSchoolDetailByMincodeFromRedisCache(minCode);
if(schoolDetailResponse != null) {
return response.GET(schoolDetailResponse);
}else {
return response.NOT_FOUND();
}
}

/**
* School wildcard Search with given params
* @param districtId
* @param mincode
* @param displayName
* @param distNo
* @return
*/
@GetMapping(EducGradTraxApiConstants.GRAD_SCHOOL_URL_MAPPING_V2 + EducGradTraxApiConstants.GET_SCHOOL_SEARCH_MAPPING)
@PreAuthorize(PermissionsConstants.READ_SCHOOL_DATA)
@Operation(summary = "Search for a school", description = "Search for a School", tags = { "School" })
@Operation(summary = "Search for a school v2", description = "Search for a School v2", tags = { "School" })
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "400", description = "BAD REQUEST")})
public ResponseEntity<List<School>> getSchoolsByParams(
@RequestParam(value = "districtId", required = false) UUID districtId,
@RequestParam(value = "mincode", required = false) String mincode) {
return response.GET(schoolService.getSchoolsByParams(districtId, mincode));
@RequestParam(value = "districtId", required = false) String districtId,
@RequestParam(value = "mincode", required = false) String mincode,
@RequestParam(value = "displayName", required = false) String displayName,
@RequestParam(value = "distNo", required = false) String distNo)
{
log.debug("getSchoolsByParams V2 : ");
return response.GET(schoolService.getSchoolsByParams(districtId, mincode, displayName, distNo));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ca.bc.gov.educ.api.trax.model.dto.institute.School;
import ca.bc.gov.educ.api.trax.service.institute.SchoolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -11,7 +12,7 @@ public abstract class SchoolEventBaseService<T> extends EventBaseService<T> {

protected SchoolService schoolService;

protected SchoolEventBaseService(SchoolService schoolService) {
protected SchoolEventBaseService(@Qualifier("instituteSchoolService") SchoolService schoolService) {
this.schoolService = schoolService;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ca.bc.gov.educ.api.trax.service.institute.SchoolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.Arrays;
Expand All @@ -17,7 +18,7 @@
public class SchoolMovedService extends SchoolEventBaseService<MoveSchoolData> {

@Autowired
public SchoolMovedService(SchoolService schoolService) {
public SchoolMovedService(@Qualifier("instituteSchoolService") SchoolService schoolService) {
super(schoolService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.List;

@Slf4j
@Service("InstituteCodeService")
@Service("instituteCodeService")
public class CodeService {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public class CommonService {
private SchoolService schoolService;

@Autowired
public CommonService(@Qualifier("InstituteCodeService") CodeService codeService,
@Qualifier("InstituteDistrictService") DistrictService districtService,
@Qualifier("InstituteSchoolService") SchoolService schoolService) {
public CommonService(@Qualifier("instituteCodeService") CodeService codeService,
@Qualifier("instituteDistrictService") DistrictService districtService,
@Qualifier("instituteSchoolService") SchoolService schoolService) {
this.codeService = codeService;
this.districtService = districtService;
this.schoolService = schoolService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.List;

@Slf4j
@Service("InstituteDistrictService")
@Service("instituteDistrictService")
public class DistrictService {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ca.bc.gov.educ.api.trax.service.institute;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Builder
public class SchoolSearchCriteria {
private String districtId;
private String mincode;
private String displayName;
private String distNo;

public String toString() {
return String.format("DistrictId: %s, Mincode: %s, DisplayName: %s, DisNo: %s", districtId, mincode, displayName, distNo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@
import ca.bc.gov.educ.api.trax.repository.redis.SchoolRedisRepository;
import ca.bc.gov.educ.api.trax.service.RESTService;
import ca.bc.gov.educ.api.trax.util.EducGradTraxApiConstants;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service("InstituteSchoolService")
@Service("instituteSchoolService")
public class SchoolService {

@Autowired
Expand Down Expand Up @@ -56,7 +58,7 @@ public List<School> getSchoolsFromInstituteApi() {
} catch (Exception e) {
log.error(String.format("Error getting data from Institute api: %s", e.getMessage()));
}
return null;
return Collections.emptyList();
}

public void loadSchoolsIntoRedisCache(List<ca.bc.gov.educ.api.trax.model.dto.institute.School> schools) {
Expand Down Expand Up @@ -182,16 +184,53 @@ public Optional<School> getSchoolBySchoolId(UUID schoolId) {
return schoolRedisRepository.findById(String.valueOf(schoolId)).map(schoolTransformer::transformToDTO);
}

public List<School> getSchoolsByParams(UUID districtId, String mincode) {
if(districtId == null && mincode == null) {
return schoolTransformer.transformToDTO(schoolRedisRepository.findAll());
} else if (mincode == null) {
return schoolTransformer.transformToDTO(schoolRedisRepository.findAllByDistrictId(String.valueOf(districtId)));
} else if(districtId == null) {
Optional<SchoolEntity> schoolOptional = schoolRedisRepository.findByMincode(mincode);
return schoolOptional.map(schoolEntity -> List.of(schoolTransformer.transformToDTO(schoolEntity))).orElse(Collections.emptyList());
} else {
return schoolTransformer.transformToDTO(schoolRedisRepository.findAllByDistrictIdAndMincode(String.valueOf(districtId), mincode));
/**
* Get a list of schools that match the given params with wildcards
* @param districtId
* @param mincode
* @param displayName
* @param distNo
* @return
*/
@Transactional(readOnly = true)
public List<School> getSchoolsByParams(String districtId, String mincode, String displayName, String distNo) {

SchoolSearchCriteria criteria = SchoolSearchCriteria.builder()
.districtId(transformToWildcard(districtId))
.mincode(transformToWildcard(mincode))
.displayName(transformToWildcard(displayName))
.distNo(transformToWildcard(distNo))
.build();

log.debug(criteria.toString());
List<SchoolEntity> schools = filterByCriteria(criteria, schoolRedisRepository.findAll());
return schoolTransformer.transformToDTO(schools);
}

/**
* Filter a list of SchoolEntities by given criteria
* @param criteria
* @param schoolEntities
* @return
*/
private List<SchoolEntity> filterByCriteria(SchoolSearchCriteria criteria, Iterable<SchoolEntity> schoolEntities) {
List<SchoolEntity> schools = new ArrayList<>();
for (SchoolEntity school : schoolEntities) {
if (school.getDistrictId().matches(criteria.getDistrictId())
Dismissed Show dismissed Hide dismissed
&& school.getMincode().matches(criteria.getMincode())
Dismissed Show dismissed Hide dismissed
&& school.getDisplayName().matches(criteria.getDisplayName())
Dismissed Show dismissed Hide dismissed
&& school.getMincode().substring(0, 3).matches(criteria.getDistNo()))
Dismissed Show dismissed Hide dismissed
schools.add(school);
}
return schools;
}

/**
* Transform '*' wildcard into Regex format
* @param value
* @return
*/
private String transformToWildcard(String value) {
return Strings.isNullOrEmpty(value) ? "(.*)" : "*".concat(value).concat("*").replaceAll("\\*", "(.*)");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class EducGradTraxApiConstants {

public static final String GET_COMMON_SCHOOL_BY_CODE_MAPPING = GET_COMMON_SCHOOLS + GET_SCHOOL_BY_CODE_MAPPING;
public static final String GET_SCHOOL_SEARCH_MAPPING = "/search";
public static final String GET_SCHOOL_DETAIL_SEARCH_MAPPING = "/search";

public static final String GET_PSI_BY_CODE_MAPPING = "/{psiCode}";
public static final String GET_PSI_SEARCH_MAPPING="/search";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ public void whenGetSchoolDetailsByMincode_ReturnsSchoolDetail() {
schoolDetail.setMincode(mincode);

Mockito.when(schoolServiceV2.getSchoolDetailByMincodeFromRedisCache(mincode)).thenReturn(schoolDetail);
schoolControllerV2.getSchoolDetailsByMincode(mincode);
schoolControllerV2.getSchoolDetailsByParams(mincode);
Mockito.verify(schoolServiceV2).getSchoolDetailByMincodeFromRedisCache(mincode);
}

Expand All @@ -239,9 +239,9 @@ public void whenGetSchoolDetailsByMincode_Return_NOT_FOUND() {
schoolDetail.setMincode(mincode);

Mockito.when(schoolServiceV2.getSchoolDetailByMincodeFromRedisCache(mincode)).thenReturn(null);
schoolControllerV2.getSchoolDetailsByMincode(mincode);
schoolControllerV2.getSchoolDetailsByParams(mincode);
Mockito.verify(schoolServiceV2).getSchoolDetailByMincodeFromRedisCache(mincode);
assertEquals(responseHelper.NOT_FOUND(), schoolControllerV2.getSchoolDetailsByMincode(mincode));
assertEquals(responseHelper.NOT_FOUND(), schoolControllerV2.getSchoolDetailsByParams(mincode));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,23 @@ class SchoolControllerIntegrationTest {
@Autowired
private SchoolDetailTransformer schoolDetailTransformer;

private final String schoolId = UUID.randomUUID().toString();
private final String districtId = UUID.randomUUID().toString();
private final UUID schoolId = UUID.randomUUID();
private final UUID districtId = UUID.randomUUID();

@BeforeEach
void setup() {
schoolRedisRepository.deleteAll();
schoolDetailRedisRepository.deleteAll();

School school = new School();
school.setSchoolId(schoolId);
school.setSchoolId(schoolId.toString());
school.setMincode("1234567");
school.setDistrictId(districtId);
school.setDistrictId(districtId.toString());
schoolRedisRepository.save(schoolTransformer.transformToEntity(school));

SchoolDetail schoolDetail = new SchoolDetail();
schoolDetail.setSchoolId(schoolId);
schoolDetail.setDistrictId(districtId);
schoolDetail.setSchoolId(schoolId.toString());
schoolDetail.setDistrictId(districtId.toString());
schoolDetailRedisRepository.save(schoolDetailTransformer.transformToEntity(schoolDetail));
}

Expand All @@ -79,7 +79,7 @@ void testGetSchoolDetails_givenValidPayload_shouldReturnOk() throws Exception {
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.schoolId").value(schoolId))
.andExpect(jsonPath("$.schoolId").value(schoolId.toString()))
.andExpect(jsonPath("$.mincode").value("1234567"));
}

Expand All @@ -104,13 +104,14 @@ void testGetSchoolDetails_givenInvalidScope_shouldReturnUnauthorized() throws Ex
@Test
void testGetSchoolsByParams_givenValidPayload_shouldReturnOk() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/v2/trax/school/search")
.param("districtId", districtId)
.param("districtId", districtId.toString())
.with(jwt().jwt(jwt -> jwt.claim("scope", "READ_GRAD_SCHOOL_DATA")))
.param("mincode", "1234567")
.param("displayName", "School name")
.param("distNo", "123")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json("[{\"schoolId\":\""+schoolId+"\",\"districtId\":\""+districtId+"\"}]"));
.andExpect(status().isBadRequest())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}

@Test
Expand All @@ -131,18 +132,22 @@ void testGetSchoolsByParams_givenBadDistrictId_shouldReturnBadRequest() throws E
.param("districtId", "BAD_ID123")
.with(jwt().jwt(jwt -> jwt.claim("scope", "READ_GRAD_SCHOOL_DATA")))
.param("mincode", "1234567")
.param("displayName", "School name")
.param("distNo", "123")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.message").value("Parameter 'districtId' with value 'BAD_ID123' could not be converted to type 'UUID'."));
.andExpect(content().json("[]"));
}

@Test
void testGetSchoolsByParams_givenScope_shouldReturnForbidden() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/v2/trax/school/search")
.param("districtId", districtId)
.param("districtId", districtId.toString())
.with(jwt().jwt(jwt -> jwt.claim("scope", "BAD_SCOPE")))
.param("mincode", "1234567")
.param("displayName", "School name")
.param("distNo", "123")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isForbidden());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class TraxCommonServiceTest {
SchoolService schoolService;

@MockBean
@Qualifier("InstituteSchoolService")
@Qualifier("instituteSchoolService")
ca.bc.gov.educ.api.trax.service.institute.SchoolService schoolServiceV2;

// NATS
Expand Down
Loading
Loading