Skip to content

Commit

Permalink
Merge pull request #1026 from bcgov/feature/collection-pagination
Browse files Browse the repository at this point in the history
EDX-2771, EDX-2535, EDX-2534 - adds pagination for sdc collections
  • Loading branch information
SodhiA1 authored Aug 2, 2024
2 parents c0e488e + bf53955 commit 5661c2d
Show file tree
Hide file tree
Showing 21 changed files with 596 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import ca.bc.gov.educ.studentdatacollection.api.model.v1.CollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.orchestrator.CloseCollectionOrchestrator;
import ca.bc.gov.educ.studentdatacollection.api.properties.ApplicationProperties;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.CollectionSearchService;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.CollectionService;

import ca.bc.gov.educ.studentdatacollection.api.service.v1.SagaService;
Expand All @@ -25,6 +26,9 @@
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -36,6 +40,7 @@
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

import static org.springframework.http.HttpStatus.BAD_REQUEST;
Expand All @@ -51,14 +56,16 @@ public class CollectionController implements CollectionEndpoint {
private final SdcDuplicatesService sdcDuplicatesService;
private final CloseCollectionOrchestrator closeCollectionOrchestrator;
private final SagaService sagaService;
private final CollectionSearchService collectionSearchService;

@Autowired
public CollectionController(final CollectionService collectionService, final CollectionPayloadValidator collectionPayloadValidator, final SdcDuplicatesService sdcDuplicatesService, CloseCollectionOrchestrator closeCollectionOrchestrator, SagaService sagaService) {
public CollectionController(final CollectionService collectionService, final CollectionPayloadValidator collectionPayloadValidator, final SdcDuplicatesService sdcDuplicatesService, CloseCollectionOrchestrator closeCollectionOrchestrator, SagaService sagaService, CollectionSearchService collectionSearchService) {
this.collectionService = collectionService;
this.sdcDuplicatesService = sdcDuplicatesService;
this.collectionPayloadValidator = collectionPayloadValidator;
this.closeCollectionOrchestrator = closeCollectionOrchestrator;
this.sagaService = sagaService;
this.sagaService = sagaService;
this.collectionSearchService = collectionSearchService;
}

@Override
Expand Down Expand Up @@ -158,4 +165,19 @@ public ResponseEntity<Void> resolveRemainingDuplicates(UUID collectionID){
return ResponseEntity.ok().build();
}

@Override
public CompletableFuture<Page<Collection>> findAll(Integer pageNumber, Integer pageSize, String sortCriteriaJson, String searchCriteriaListJson) {
final List<Sort.Order> sorts = new ArrayList<>();
Specification<CollectionEntity> collectionSpecs = collectionSearchService
.setSpecificationAndSortCriteria(
sortCriteriaJson,
searchCriteriaListJson,
JsonUtil.mapper,
sorts
);
return this.collectionSearchService
.findAll(collectionSpecs, pageNumber, pageSize, sorts)
.thenApplyAsync(collectionEntities -> collectionEntities.map(collectionMapper::toStructure));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,43 @@
import ca.bc.gov.educ.studentdatacollection.api.mappers.v1.SdcSchoolCollectionMapper;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcDistrictCollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcDistrictCollectionSearchService;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcDistrictCollectionService;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcDuplicatesService;
import ca.bc.gov.educ.studentdatacollection.api.struct.v1.*;
import ca.bc.gov.educ.studentdatacollection.api.util.JsonUtil;
import ca.bc.gov.educ.studentdatacollection.api.util.RequestUtil;
import ca.bc.gov.educ.studentdatacollection.api.util.ValidationUtil;
import ca.bc.gov.educ.studentdatacollection.api.validator.SdcDistrictCollectionSubmissionSignatureValidator;
import ca.bc.gov.educ.studentdatacollection.api.validator.SdcDistrictCollectionValidator;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@RestController
public class SdcDistrictCollectionController implements SdcDistrictCollectionEndpoint {

private static final SdcDistrictCollectionMapper mapper = SdcDistrictCollectionMapper.mapper;
private final SdcDuplicatesService sdcDuplicatesService;
private final SdcDistrictCollectionService sdcDistrictCollectionService;
private final SdcDistrictCollectionSearchService sdcDistrictCollectionSearchService;
private static final SdcDuplicateMapper duplicateMapper = SdcDuplicateMapper.mapper;
private static final SdcSchoolCollectionMapper sdcSchoolCollectionMapper = SdcSchoolCollectionMapper.mapper;
private final SdcDistrictCollectionValidator sdcDistrictCollectionValidator;
private final SdcDistrictCollectionSubmissionSignatureValidator sdcDistrictCollectionSubmissionSignatureValidator;
public SdcDistrictCollectionController(SdcDuplicatesService sdcDuplicatesService, SdcDistrictCollectionService sdcDistrictCollectionService, SdcDistrictCollectionValidator sdcDistrictCollectionValidator, SdcDistrictCollectionSubmissionSignatureValidator sdcDistrictCollectionSubmissionSignatureValidator) {
public SdcDistrictCollectionController(SdcDuplicatesService sdcDuplicatesService, SdcDistrictCollectionService sdcDistrictCollectionService, SdcDistrictCollectionValidator sdcDistrictCollectionValidator, SdcDistrictCollectionSubmissionSignatureValidator sdcDistrictCollectionSubmissionSignatureValidator, SdcDistrictCollectionSearchService sdcDistrictCollectionSearchService) {
this.sdcDuplicatesService = sdcDuplicatesService;
this.sdcDistrictCollectionService = sdcDistrictCollectionService;
this.sdcDistrictCollectionValidator = sdcDistrictCollectionValidator;
this.sdcDistrictCollectionSubmissionSignatureValidator = sdcDistrictCollectionSubmissionSignatureValidator;
this.sdcDistrictCollectionSearchService = sdcDistrictCollectionSearchService;
}

@Override
Expand Down Expand Up @@ -115,4 +123,19 @@ public ResponseEntity<Void> signDistrictCollectionForSubmission(UUID sdcDistrict
sdcDistrictCollectionService.signDistrictCollectionForSubmission(sdcDistrictCollectionID, mapper.toModelWithSubmissionSignatures(sdcDistrictCollection));
return ResponseEntity.ok().build();
}

@Override
public CompletableFuture<Page<SdcDistrictCollection>> findAll(Integer pageNumber, Integer pageSize, String sortCriteriaJson, String searchCriteriaListJson) {
final List<Sort.Order> sorts = new ArrayList<>();
Specification<SdcDistrictCollectionEntity> districtSpecs = sdcDistrictCollectionSearchService
.setSpecificationAndSortCriteria(
sortCriteriaJson,
searchCriteriaListJson,
JsonUtil.mapper,
sorts
);
return this.sdcDistrictCollectionSearchService
.findAll(districtSpecs, pageNumber, pageSize, sorts)
.thenApplyAsync(sdcDistrictCollectionEntities -> sdcDistrictCollectionEntities.map(mapper::toStructure));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@
import ca.bc.gov.educ.studentdatacollection.api.mappers.v1.SdcSchoolCollectionStudentMapper;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcDuplicatesService;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcSchoolCollectionSearchService;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.SdcSchoolCollectionService;
import ca.bc.gov.educ.studentdatacollection.api.struct.v1.*;
import ca.bc.gov.educ.studentdatacollection.api.util.JsonUtil;
import ca.bc.gov.educ.studentdatacollection.api.util.RequestUtil;
import ca.bc.gov.educ.studentdatacollection.api.util.ValidationUtil;
import ca.bc.gov.educ.studentdatacollection.api.validator.SdcSchoolCollectionValidator;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@RestController
public class SdcSchoolCollectionController implements SdcSchoolCollectionEndpoint {
Expand All @@ -29,11 +35,13 @@ public class SdcSchoolCollectionController implements SdcSchoolCollectionEndpoin
private final SdcDuplicatesService sdcDuplicatesService;
private final SdcSchoolCollectionService sdcSchoolCollectionService;
private final SdcSchoolCollectionValidator sdcSchoolCollectionValidator;
private final SdcSchoolCollectionSearchService sdcSchoolCollectionSearchService;

public SdcSchoolCollectionController(SdcSchoolCollectionService sdcSchoolCollectionService, SdcSchoolCollectionValidator sdcSchoolCollectionValidator, SdcDuplicatesService sdcDuplicatesService) {
public SdcSchoolCollectionController(SdcSchoolCollectionService sdcSchoolCollectionService, SdcSchoolCollectionValidator sdcSchoolCollectionValidator, SdcDuplicatesService sdcDuplicatesService, SdcSchoolCollectionSearchService sdcSchoolCollectionSearchService) {
this.sdcSchoolCollectionService = sdcSchoolCollectionService;
this.sdcSchoolCollectionValidator = sdcSchoolCollectionValidator;
this.sdcDuplicatesService = sdcDuplicatesService;
this.sdcSchoolCollectionSearchService = sdcSchoolCollectionSearchService;
}

@Override
Expand Down Expand Up @@ -122,4 +130,19 @@ public List<SdcDuplicate> getSchoolCollectionProvincialDuplicates(UUID sdcSchool
public List<ValidationIssueTypeCode> getStudentValidationIssueCodes(UUID sdcSchoolCollectionID) {
return this.sdcSchoolCollectionService.getStudentValidationIssueCodes(sdcSchoolCollectionID);
}

@Override
public CompletableFuture<Page<SdcSchoolCollection>> findAll(Integer pageNumber, Integer pageSize, String sortCriteriaJson, String searchCriteriaListJson) {
final List<Sort.Order> sorts = new ArrayList<>();
Specification<SdcSchoolCollectionEntity> schoolSpecs = sdcSchoolCollectionSearchService
.setSpecificationAndSortCriteria(
sortCriteriaJson,
searchCriteriaListJson,
JsonUtil.mapper,
sorts
);
return this.sdcSchoolCollectionSearchService
.findAll(schoolSpecs, pageNumber, pageSize, sorts)
.thenApplyAsync(sdcSchoolCollectionEntities -> sdcSchoolCollectionEntities.map(mapper::toStructure));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -16,6 +17,7 @@

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

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

Expand Down Expand Up @@ -107,4 +109,13 @@ public interface CollectionEndpoint {
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "BAD REQUEST")})
@Tag(name = "Collection Entity", description = "Endpoints for collection entity.")
ResponseEntity<Void> resolveRemainingDuplicates(@PathVariable("collectionID") UUID collectionID);

@GetMapping(URL.PAGINATED)
@PreAuthorize("hasAuthority('SCOPE_READ_SDC_COLLECTION')")
@Transactional(readOnly = true)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
CompletableFuture<Page<Collection>> findAll(@RequestParam(name = "pageNumber", defaultValue = "0") Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "sort", defaultValue = "") String sortCriteriaJson,
@RequestParam(name = "searchCriteriaList", required = false) String searchCriteriaListJson);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,6 +15,7 @@

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.NO_CONTENT;
Expand Down Expand Up @@ -105,4 +107,13 @@ public interface SdcDistrictCollectionEndpoint {
@Transactional
@Schema(name = "SdcDistrictCollectionSubmissionSignature", implementation = SdcDistrictCollectionSubmissionSignature.class)
ResponseEntity<Void> signDistrictCollectionForSubmission(@PathVariable("sdcDistrictCollectionID") UUID sdcDistrictCollectionID, @RequestBody SdcDistrictCollection sdcDistrictCollection);

@GetMapping(URL.PAGINATED)
@PreAuthorize("hasAuthority('SCOPE_READ_SDC_DISTRICT_COLLECTION')")
@Transactional(readOnly = true)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
CompletableFuture<Page<SdcDistrictCollection>> findAll(@RequestParam(name = "pageNumber", defaultValue = "0") Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "sort", defaultValue = "") String sortCriteriaJson,
@RequestParam(name = "searchCriteriaList", required = false) String searchCriteriaListJson);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,6 +15,7 @@

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.NO_CONTENT;
Expand Down Expand Up @@ -114,4 +116,13 @@ List<SdcSchoolCollection> getAllSchoolCollections(@RequestParam(name = "schoolID
@Transactional(readOnly = true)
@Tag(name = "Sdc School Collection", description = "Endpoints to get all student validation issue codes for a school collection.")
List<ValidationIssueTypeCode> getStudentValidationIssueCodes(@PathVariable("sdcSchoolCollectionID") UUID sdcSchoolCollectionID);

@GetMapping(URL.PAGINATED)
@PreAuthorize("hasAuthority('SCOPE_READ_SDC_COLLECTION')")
@Transactional(readOnly = true)
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR.")})
CompletableFuture<Page<SdcSchoolCollection>> findAll(@RequestParam(name = "pageNumber", defaultValue = "0") Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "sort", defaultValue = "") String sortCriteriaJson,
@RequestParam(name = "searchCriteriaList", required = false) String searchCriteriaListJson);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ca.bc.gov.educ.studentdatacollection.api.filter;

import ca.bc.gov.educ.studentdatacollection.api.model.v1.CollectionEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.util.UUID;

@Service
@Slf4j
public class CollectionFilterSpecs extends BaseFilterSpecs<CollectionEntity> {

public CollectionFilterSpecs(FilterSpecifications<CollectionEntity, ChronoLocalDate> dateFilterSpecifications, FilterSpecifications<CollectionEntity, ChronoLocalDateTime<?>> dateTimeFilterSpecifications, FilterSpecifications<CollectionEntity, Integer> integerFilterSpecifications, FilterSpecifications<CollectionEntity, String> stringFilterSpecifications, FilterSpecifications<CollectionEntity, Long> longFilterSpecifications, FilterSpecifications<CollectionEntity, UUID> uuidFilterSpecifications, FilterSpecifications<CollectionEntity, Boolean> booleanFilterSpecifications, Converters converters) {
super(dateFilterSpecifications, dateTimeFilterSpecifications, integerFilterSpecifications, stringFilterSpecifications, longFilterSpecifications, uuidFilterSpecifications, booleanFilterSpecifications, converters);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,18 @@ public void initSpecifications() {
return criteriaBuilder.or(criteriaBuilder.not(root.get(filterCriteria.getFieldName()).in(filterCriteria.getConvertedValues())), criteriaBuilder.isNull(root.get(filterCriteria.getFieldName())));
}
});

map.put(FilterOperation.BETWEEN,
filterCriteria -> (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.between(
root.get(filterCriteria.getFieldName()), filterCriteria.getMinValue(),
filterCriteria.getMaxValue()));
filterCriteria -> (root, criteriaQuery, criteriaBuilder) -> {
if (filterCriteria.getFieldName().contains(".")) {
String[] splits = filterCriteria.getFieldName().split("\\.");
return criteriaBuilder.between(root.join(splits[0]).get(splits[1]), filterCriteria.getMinValue(),
filterCriteria.getMaxValue());
} else {
return criteriaBuilder.between(
root.get(filterCriteria.getFieldName()), filterCriteria.getMinValue(),
filterCriteria.getMaxValue());
}
});

map.put(FilterOperation.CONTAINS, filterCriteria -> (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder
.like(root.get(filterCriteria.getFieldName()), "%" + filterCriteria.getConvertedSingleValue() + "%"));
Expand Down
Loading

0 comments on commit 5661c2d

Please sign in to comment.