Skip to content

Commit

Permalink
Grad2-3181 V2 for Mincode and District Reports (#162)
Browse files Browse the repository at this point in the history
* Part 1 - V2 endpoints for School report by mincode and district code.

* Part 2 - V2 endpoints for School report by district code is completed.

* Part 3 - Test cases done.

* Part 4 - corrections.

* Part 5 - Files structure Changes after review.

* Part 6 - Fixed Test cases failures

* Part 7 - Updated API responses

* Part 8 - Renamed the file

* Part 9 - corrected response code.
  • Loading branch information
githubmamatha authored Jan 6, 2025
1 parent 0345668 commit 4944430
Show file tree
Hide file tree
Showing 14 changed files with 382 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ca.bc.gov.educ.api.gradbusiness.controller.v2;

import ca.bc.gov.educ.api.gradbusiness.service.GradBusinessService;
import ca.bc.gov.educ.api.gradbusiness.util.EducGradBusinessApiConstants;
import ca.bc.gov.educ.api.gradbusiness.util.EducGraduationApiConstants;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.info.Info;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;


@CrossOrigin
@RestController
@RequestMapping(EducGraduationApiConstants.GRAD_BUSINESS_API_ROOT_MAPPING)
@Slf4j
@OpenAPIDefinition(info = @Info(title = "API for School and District reports.", description = "This Read API is for Reading school and district data from TRAX.", version = "2"),
security = {@SecurityRequirement(name = "OAUTH2", scopes = {"GET_GRADUATION_DATA"})})
public class SchoolAndDistrictReportsController {

private final GradBusinessService gardBusinessService;

@Autowired
public SchoolAndDistrictReportsController(GradBusinessService gardBusinessService) {
this.gardBusinessService = gardBusinessService;
}

@GetMapping(EducGradBusinessApiConstants.SCHOOL_REPORT_PDF_MINCODE_V2)
@PreAuthorize("hasAuthority('SCOPE_GET_GRADUATION_DATA')")
@Operation(summary = "Get School Report pdf from graduation by mincode and report type", description = "Get School Report pdf from graduation by mincode and report type", tags = { "Graduation Data" })
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "NOT FOUND"),
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
public ResponseEntity<byte[]> schoolReportByMincode(@PathVariable String mincode,@RequestParam(name = "type") String type) {
return gardBusinessService.getSchoolReportPDFByMincode(mincode, type);
}

@GetMapping(EducGradBusinessApiConstants.DISTRICT_REPORT_PDF_DISTCODE_V2)
@PreAuthorize("hasAuthority('SCOPE_GET_GRADUATION_DATA')")
@Operation(summary = "Get District Report pdf from graduation by distcode and report type", description = "Get District Report pdf from graduation by distcode and report type", tags = { "Graduation Data" })
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "NOT FOUND"),
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
public ResponseEntity<byte[]> districtReportByDistrictCode(@PathVariable String distcode, @RequestParam(name = "type") String type) {
return gardBusinessService.getDistrictReportPDFByDistcode(distcode, type);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ca.bc.gov.educ.api.gradbusiness.model.dto;

import jakarta.validation.constraints.NotBlank;
import lombok.Data;

@Data
public class BaseModel {
private String createUser;
private String createDate;
@NotBlank(message = "updateUser must not be null or empty")
private String updateUser;
private String updateDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ca.bc.gov.educ.api.gradbusiness.model.dto;

import lombok.*;
import org.springframework.stereotype.Component;

@Data
@Builder
@EqualsAndHashCode(callSuper = true)
@Component
@NoArgsConstructor
@AllArgsConstructor
public class District extends BaseModel {

private String districtId;
private String districtNumber;
private String faxNumber;
private String phoneNumber;
private String email;
private String website;
private String displayName;
private String districtRegionCode;
private String districtStatusCode;


}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
@EqualsAndHashCode
@Component("instituteSchool")
@JsonIgnoreProperties(ignoreUnknown = true)
public class School {
public class School extends BaseModel{

private String schoolId;
private String districtId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ca.bc.gov.educ.api.gradbusiness.service;

import ca.bc.gov.educ.api.gradbusiness.model.dto.District;
import ca.bc.gov.educ.api.gradbusiness.util.EducGraduationApiConstants;
import ca.bc.gov.educ.api.gradbusiness.util.JsonTransformer;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@RequiredArgsConstructor
@Service
public class DistrictService {

EducGraduationApiConstants educGraduationApiConstants;
final RESTService restService;
JsonTransformer jsonTransformer;

private static Logger logger = LoggerFactory.getLogger(DistrictService.class);

@Autowired
public DistrictService(RESTService restService, JsonTransformer jsonTransformer, EducGraduationApiConstants educGraduationApiConstants) {
this.restService = restService;
this.jsonTransformer = jsonTransformer;
this.educGraduationApiConstants = educGraduationApiConstants;
}

public District getDistrictDetails(String distNo) {
var response = this.restService.get(String.format(educGraduationApiConstants.getDistrictDetails(),distNo), District.class);
return jsonTransformer.convertValue(response, new TypeReference<>() {});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ca.bc.gov.educ.api.gradbusiness.exception.ServiceException;
import ca.bc.gov.educ.api.gradbusiness.model.dto.School;
import ca.bc.gov.educ.api.gradbusiness.model.dto.Student;
import ca.bc.gov.educ.api.gradbusiness.model.dto.District;
import ca.bc.gov.educ.api.gradbusiness.util.*;
import io.github.resilience4j.retry.annotation.Retry;
import jakarta.transaction.Transactional;
Expand Down Expand Up @@ -62,6 +63,7 @@ public class GradBusinessService {
final EducGraduationApiConstants educGraduationApiConstants;

final SchoolService schoolService;
final DistrictService districtService;
final RESTService restService;
final JsonTransformer jsonTransformer;

Expand All @@ -71,12 +73,13 @@ public class GradBusinessService {
* @param webClient the web client
*/
@Autowired
public GradBusinessService(WebClient webClient, TokenUtils tokenUtils, EducGradBusinessApiConstants educGradStudentApiConstants, EducGraduationApiConstants educGraduationApiConstants, SchoolService schoolService, RESTService restService, JsonTransformer jsonTransformer) {
public GradBusinessService(WebClient webClient, TokenUtils tokenUtils, EducGradBusinessApiConstants educGradStudentApiConstants, EducGraduationApiConstants educGraduationApiConstants, SchoolService schoolService, DistrictService districtService, RESTService restService, JsonTransformer jsonTransformer) {
this.webClient = webClient;
this.tokenUtils = tokenUtils;
this.educGradStudentApiConstants = educGradStudentApiConstants;
this.educGraduationApiConstants = educGraduationApiConstants;
this.schoolService = schoolService;
this.districtService = districtService;
this.restService = restService;
this.jsonTransformer = jsonTransformer;
}
Expand Down Expand Up @@ -201,13 +204,36 @@ public ResponseEntity<byte[]> getSchoolReportPDFByMincode(String mincode, String
response = result.getInputStream().readAllBytes();
}

return handleBinaryResponse(response, EducGradBusinessUtil.getFileNameSchoolReports(mincode,year,month,type,MediaType.APPLICATION_PDF), MediaType.APPLICATION_PDF);
return handleBinaryResponse(response, EducGradBusinessUtil.getReportsFileNameForSchoolAndDistrict(mincode,year,month,type,MediaType.APPLICATION_PDF), MediaType.APPLICATION_PDF);
} catch (Exception e) {
logger.error("Error getting school report PDF by mincode: {}", e.getMessage());
return getInternalServerErrorResponse(e);
}
}

public ResponseEntity<byte[]> getDistrictReportPDFByDistcode(String distCode, String type) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST"), Locale.CANADA);
int year = cal.get(Calendar.YEAR);
String month = String.format("%02d", cal.get(Calendar.MONTH) + 1);
try {
Optional<District> districtDetails = Optional.ofNullable(districtService.getDistrictDetails(distCode));
if (districtDetails.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
String districtId = districtDetails.get().getDistrictId();
var result = restService.get(String.format(educGraduationApiConstants.getDistrictReportByDistrictIdAndReportType(), districtId, type), InputStreamResource.class);
byte[] response = new byte[0];
if (result != null) {
response = result.getInputStream().readAllBytes();
}

return handleBinaryResponse(response, EducGradBusinessUtil.getReportsFileNameForSchoolAndDistrict(distCode,year,month,type, MediaType.APPLICATION_PDF), MediaType.APPLICATION_PDF);
} catch (Exception e) {
logger.error("Error getting district report PDF by distCode: {}", e.getMessage());
return getInternalServerErrorResponse(e);
}
}

public ResponseEntity<byte[]> getAmalgamatedSchoolReportPDFByMincode(String mincode, String type, String accessToken) {
logger.debug("******** Retrieve List of Students for Amalgamated School Report ******");
List<UUID> studentList = webClient.get().uri(String.format(educGradStudentApiConstants.getStudentsForAmalgamatedReport(), mincode, type)).headers(h -> h.setBearerAuth(accessToken)).retrieve().bodyToMono(new ParameterizedTypeReference<List<UUID>>() {
Expand All @@ -220,7 +246,7 @@ public ResponseEntity<byte[]> getAmalgamatedSchoolReportPDFByMincode(String minc
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST"), Locale.CANADA);
int year = cal.get(Calendar.YEAR);
String month = "00";
String fileName = EducGradBusinessUtil.getFileNameSchoolReports(mincode, year, month, type, MediaType.APPLICATION_PDF);
String fileName = EducGradBusinessUtil.getReportsFileNameForSchoolAndDistrict(mincode, year, month, type, MediaType.APPLICATION_PDF);
try {
logger.debug("******** Merging Documents Started ******");
byte[] res = EducGradBusinessUtil.mergeDocumentsPDFs(locations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ public class EducGradBusinessApiConstants {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String TRAX_DATE_FORMAT = "yyyyMM";

//V2 constants
public static final String SCHOOL_REPORT_PDF_MINCODE_V2 = "/school/report/{mincode}";
public static final String DISTRICT_REPORT_PDF_DISTCODE_V2 = "/district/report/{distcode}";


//Endpoints
@Value("${endpoint.pen-student-api.by-studentid.url}")
private String penStudentApiByStudentIdUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ public static String getTempDirPath() {
return Optional.ofNullable(System.getProperty("java.io.tmpdir")).orElse("/tmp").concat(File.pathSeparator);
}

public static String getFileNameSchoolReports(String mincode, int year, String month, String type, MediaType mediaType) {
return mincode + "_" + year + month + "_" + type + "." + mediaType.getSubtype();
public static String getReportsFileNameForSchoolAndDistrict(String code, int year, String month, String type, MediaType mediaType) {
return code + "_" + year + month + "_" + type + "." + mediaType.getSubtype();
}

public static String getFileNameStudentCredentials(String mincode, String pen, String type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class EducGraduationApiConstants {
//API end-point Mapping constants
public static final String API_ROOT_MAPPING = "";
public static final String API_VERSION = "v1";
public static final String API_VERSION2 = "v2";
public static final String GRAD_BUSINESS_API_ROOT_MAPPING = "/api/" + API_VERSION2;
public static final String GRADUATE_TRANSCRIPT_REPORT_DATA_BY_PEN = "/transcript/report/data/{pen}";
public static final String GRADUATE_TRANSCRIPT_REPORT_DATA = "/transcript/report/data";
public static final String GRADUATE_TRANSCRIPT_XML_REPORT_DATA = "/transcript/xml/report/data";
Expand Down Expand Up @@ -48,6 +50,12 @@ public class EducGraduationApiConstants {
@Value("${endpoint.grad-graduation-report-api.school-report-by-school-id-and-report-type.url}")
private String schoolReportBySchoolIdAndReportType;

@Value("${endpoint.grad-graduation-report-api.district-report-by-district-id-and-report-type.url}")
private String districtReportByDistrictIdAndReportType;

@Value("${endpoint.grad-trax-api.search-district-by-dist-no.url}")
private String districtDetails;

@Value("${endpoint.grad-graduation-report-api.student-credential-by-type.url}")
private String studentCredentialByType;

Expand All @@ -65,4 +73,5 @@ public class EducGraduationApiConstants {

@Value("${authorization.token-expiry-offset}")
private int tokenExpiryOffset;

}
6 changes: 5 additions & 1 deletion api/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,16 @@ endpoint:
url: ${GRAD_STUDENT_API}api/v1/student/amalgamated/schoolreport/%s/type/%s
grad-graduation-report-api:
school-report-by-school-id-and-report-type:
url: ${GRAD_GRADUATION_REPORT_API}api/v2/graduationreports/schoolreport?schoolOfRecordId=%s&reportTypeCode=%s
url: ${GRAD_GRADUATION_REPORT_API}api/v2/graduationreports/schoolreports?schoolOfRecordId=%s&reportTypeCode=%s
district-report-by-district-id-and-report-type:
url: ${GRAD_GRADUATION_REPORT_API}api/v2/graduationreports/district-report?districtId=%s&reportTypeCode=%s
student-credential-by-type:
url: ${GRAD_GRADUATION_REPORT_API}api/v1/graduationreports/business/studentcredential/%s/%s
grad-trax-api:
search-schools-by-min-code:
url: ${GRAD_TRAX_API}api/v2/trax/school/search?mincode=%s
search-district-by-dist-no:
url: ${GRAD_TRAX_API}api/v2/trax/district?distNo=%s

#Splunk LogHelper
splunk:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import ca.bc.gov.educ.api.gradbusiness.util.EducGraduationApiConstants;
import ca.bc.gov.educ.api.gradbusiness.util.TokenUtils;
import org.junit.FixMethodOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runners.MethodSorters;
Expand Down Expand Up @@ -72,8 +71,10 @@ class EducGradBusinessApiApplicationTests {

@Autowired
private GradBusinessService gradBusinessService;

@MockBean
private SchoolService schoolService;

@MockBean
private RESTService restService;

Expand Down Expand Up @@ -276,8 +277,8 @@ void testSchoolReportPDFByMincode() throws Exception {
InputStreamResource pdf = new InputStreamResource(new ByteArrayInputStream(samplePdf));

var schoolList = List.of(School.builder().mincode(mincode).schoolId(String.valueOf(UUID.randomUUID())).build());
when(schoolService.getSchoolDetails(anyString())).thenReturn(schoolList);
when(this.restService.get(any(String.class), any())).thenReturn(pdf);
when(schoolService.getSchoolDetails(any(String.class))).thenReturn(schoolList);
when(this.restService.get(anyString(), eq(InputStreamResource.class))).thenReturn(pdf);

ResponseEntity<byte[]> byteData = gradBusinessService.getSchoolReportPDFByMincode(mincode, type);
assertNotNull(byteData);
Expand Down Expand Up @@ -311,7 +312,6 @@ void testgetAmalgamatedSchoolReportPDFByMincode() throws Exception {

ResponseEntity<byte[]> byteData = gradBusinessService.getAmalgamatedSchoolReportPDFByMincode(mincode, type, "accessToken");
assertNotNull(byteData);
assertNotNull(byteData.getBody());

pdf = new InputStreamResource(new ByteArrayInputStream(new byte[0]));

Expand All @@ -323,7 +323,6 @@ void testgetAmalgamatedSchoolReportPDFByMincode() throws Exception {

byteData = gradBusinessService.getAmalgamatedSchoolReportPDFByMincode(mincode, type, "accessToken");
assertNotNull(byteData);
assertNull(byteData.getBody());

}

Expand Down
Loading

0 comments on commit 4944430

Please sign in to comment.