Skip to content

Commit 4339969

Browse files
feat(oracle-api): #1959 Added testing activity search api (#2085)
1 parent 845bbe8 commit 4339969

File tree

9 files changed

+933
-0
lines changed

9 files changed

+933
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ca.bc.gov.oracleapi;
2+
3+
import lombok.AccessLevel;
4+
import lombok.NoArgsConstructor;
5+
6+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
7+
public class ConsepOracleQueryConstants {
8+
public static final String ACTIVITY_SEARCH = """
9+
SELECT seedlot_display
10+
, request_item
11+
, vegetation_st
12+
, stndrd_activity_id
13+
, test_rank
14+
, current_test_ind
15+
, test_category_cd
16+
, germination_pct
17+
, pv
18+
, moisture_pct
19+
, purity_pct
20+
, seeds_per_gram
21+
, other_test_result
22+
, test_complete_ind
23+
, accept_result_ind
24+
, significnt_sts_ind
25+
, seed_withdrawal_date
26+
, revised_end_dt
27+
, actual_begin_dt_tm
28+
, actual_end_dt_tm
29+
, ria_comment
30+
, request_skey
31+
, req_id
32+
, item_id
33+
, seedlot_sample
34+
, ria_skey
35+
FROM consep.cns17
36+
WHERE (:testType IS NULL OR activity_type_cd = :testType)
37+
AND (:lotNumbers IS NULL OR seedlot_number IN (:lotNumbers))
38+
AND (:activityId IS NULL OR stndrd_activity_id = :activityId)
39+
AND (:germinatorTrayId IS NULL OR germinator_tray_id = :germinatorTrayId)
40+
AND (:seedWithdrawalStartDate IS NULL OR seed_withdrawal_date >= :seedWithdrawalStartDate)
41+
AND (:seedWithdrawalEndDate IS NULL OR seed_withdrawal_date <= :seedWithdrawalEndDate)
42+
AND (:includeHistoricalTests IS NULL OR :includeHistoricalTests = 1 OR request_skey != 0)
43+
AND (:germTestsOnly IS NULL OR :germTestsOnly = 0 OR germ_test_ind = -1)
44+
AND (:requestId IS NULL OR req_id = SUBSTR(:requestId, 1, 11))
45+
AND (:requestId IS NULL OR LENGTH(:requestId) < 12 OR item_id = SUBSTR(:requestId, 12, 1))
46+
AND (:requestType IS NULL OR request_type_st = :requestType)
47+
AND (:requestYear IS NULL OR request_yr = :requestYear)
48+
AND (:orchardId IS NULL OR orchard_id = :orchardId)
49+
AND (:testCategoryCd IS NULL OR test_category_cd = :testCategoryCd)
50+
AND (:testRank IS NULL OR test_rank = :testRank)
51+
AND (:species IS NULL OR vegetation_st = :species)
52+
AND (:actualBeginDateFrom IS NULL OR actual_begin_dt_tm >= :actualBeginDateFrom)
53+
AND (:actualBeginDateTo IS NULL OR actual_begin_dt_tm <= :actualBeginDateTo)
54+
AND (:actualEndDateFrom IS NULL OR actual_end_dt_tm >= :actualEndDateFrom)
55+
AND (:actualEndDateTo IS NULL OR actual_end_dt_tm <= :actualEndDateTo)
56+
AND (:revisedStartDateFrom IS NULL OR revised_end_dt >= :revisedStartDateFrom)
57+
AND (:revisedStartDateTo IS NULL OR revised_end_dt <= :revisedStartDateTo)
58+
AND (:revisedEndDateFrom IS NULL OR revised_end_dt >= :revisedEndDateFrom)
59+
AND (:revisedEndDateTo IS NULL OR revised_end_dt <= :revisedEndDateTo)
60+
AND (:germTrayAssignment IS NULL OR assigned_tray_ind = :germTrayAssignment)
61+
AND (:completeStatus IS NULL OR test_complete_ind = :completeStatus)
62+
AND (:acceptanceStatus IS NULL OR accept_result_ind = :acceptanceStatus)
63+
ORDER BY seedlot_sample, actual_begin_dt_tm
64+
OFFSET :offset ROWS FETCH NEXT :size ROWS ONLY
65+
""";
66+
}
67+
68+
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package ca.bc.gov.oracleapi.dto.consep;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import org.springframework.format.annotation.DateTimeFormat;
5+
6+
import java.time.LocalDate;
7+
import java.util.List;
8+
9+
import jakarta.validation.constraints.Max;
10+
import jakarta.validation.constraints.Min;
11+
import jakarta.validation.constraints.Size;
12+
import jakarta.validation.constraints.Pattern;
13+
14+
15+
/**
16+
* This record serves the purpose of mapping fields the FE should send to the BE, to search a test activity.
17+
*/
18+
@Schema(description = "Search parameters for testing activity search API")
19+
public record ActivitySearchRequestDto(
20+
@Schema(description = "Seedlot and Family Lot numbers", example = "[\"12345\", \"67890\"]")
21+
@Size(max = 5, message = "You can provide up to 5 lot numbers")
22+
List<@Size(max = 5, message = "Each lot number must be at most 5 characters") String> lotNumbers,
23+
24+
@Schema(description = "Test activity type code, used to filter activity_type_cd")
25+
@Size(max = 3)
26+
String testType,
27+
28+
@Schema(description = "Activity ID, used to filter stndrd_activity_id")
29+
@Size(max = 3)
30+
String activityId,
31+
32+
@Schema(description = "Germinator Tray ID, used to filter germinator_tray_id")
33+
@Max(value = 99999, message = "Germinator Tray ID must be at most 5 digits")
34+
@Min(value = 0)
35+
Integer germinatorTrayId,
36+
37+
@Schema(description = "Withdrawal start date", example = "2025-07-01")
38+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
39+
LocalDate seedWithdrawalStartDate,
40+
41+
@Schema(description = "Withdrawal End date", example = "2025-07-01")
42+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
43+
LocalDate seedWithdrawalEndDate,
44+
45+
@Schema(description = "Include historical tests, used to filter request_skey")
46+
Boolean includeHistoricalTests,
47+
48+
@Schema(description = "Germ tests only, used to filter germ_test_ind")
49+
Boolean germTestsOnly,
50+
51+
@Schema(description = "Request ID, used to filter req_id (first 11 char) and item_id (the 12th char)")
52+
@Size(max = 12)
53+
String requestId,
54+
55+
@Schema(description = "Request type, used to filter request_type_st")
56+
@Size(max = 3)
57+
String requestType,
58+
59+
@Schema(description = "Request year between 1900 and 9999, used to filter request_yr")
60+
@Min(value = 1900)
61+
@Max(value = 9999)
62+
Integer requestYear,
63+
64+
@Schema(description = "Orchard ID, used to filter orchard_id")
65+
@Size(max = 3)
66+
String orchardId,
67+
68+
@Schema(description = "Category, used to filter test_category_cd")
69+
@Size(max = 3)
70+
String testCategoryCd,
71+
72+
@Schema(description = "Rank, used to filter test_rank")
73+
@Size(max = 1)
74+
String testRank,
75+
76+
@Schema(description = "Species, used to filter vegetation_st")
77+
@Size(max = 8)
78+
String species,
79+
80+
@Schema(description = "Actual begin date from", example = "2025-01-01")
81+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
82+
LocalDate actualBeginDateFrom,
83+
84+
@Schema(description = "Actual begin date to", example = "2025-01-31")
85+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
86+
LocalDate actualBeginDateTo,
87+
88+
@Schema(description = "Actual end date from", example = "2025-02-01")
89+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
90+
LocalDate actualEndDateFrom,
91+
92+
@Schema(description = "Actual end date to", example = "2025-02-28")
93+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
94+
LocalDate actualEndDateTo,
95+
96+
@Schema(description = "Revised begin date from", example = "2025-03-01")
97+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
98+
LocalDate revisedStartDateFrom,
99+
100+
@Schema(description = "Revised begin date to", example = "2025-03-31")
101+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
102+
LocalDate revisedStartDateTo,
103+
104+
@Schema(description = "Revised end date from", example = "2025-04-01")
105+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
106+
LocalDate revisedEndDateFrom,
107+
108+
@Schema(description = "Revised end date to", example = "2025-04-30")
109+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
110+
LocalDate revisedEndDateTo,
111+
112+
@Schema(description = "Germ tray assignment status: -1 = Assigned, 0 = Unassigned, used to filter assigned_tray_ind")
113+
@Min(-1)
114+
@Max(0)
115+
Integer germTrayAssignment,
116+
117+
@Schema(description = "Test completion status: -1 = Complete, 0 = Incomplete, used to filter test_complete_ind")
118+
@Min(-1)
119+
@Max(0)
120+
Integer completeStatus,
121+
122+
@Schema(description = "Acceptance status: -1 = Accepted, 0 = Unaccepted, used to filter accept_result_ind")
123+
@Min(-1)
124+
@Max(0)
125+
Integer acceptanceStatus,
126+
127+
@Schema(description = "Genetic class code: A = A Class, B = B Class", allowableValues = {"A", "B"})
128+
@Pattern(regexp = "[AB]", message = "geneticClassCode must be 'A' or 'B'")
129+
String seedlotClass
130+
) {
131+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package ca.bc.gov.oracleapi.dto.consep;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
5+
import java.time.LocalDate;
6+
import java.time.LocalDateTime;
7+
8+
9+
/**
10+
* This class represents a {@link ca.bc.gov.oracleapi.entity.consep.ActivitySearchResultEntity} object.
11+
*/
12+
@Schema(description = "Search response for testing activity search API")
13+
public record ActivitySearchResponseDto(
14+
String seedlotDisplay,
15+
String requestItem,
16+
String species,
17+
String activityId,
18+
String testRank,
19+
Integer currentTestInd,
20+
String testCategoryCd,
21+
Integer germinationPct,
22+
String pv,
23+
Integer moisturePct,
24+
Integer purityPct,
25+
Integer seedsPerGram,
26+
Integer otherTestResult,
27+
Boolean testCompleteInd,
28+
Integer acceptResultInd,
29+
Integer significntStsInd,
30+
LocalDate seedWithdrawalDate,
31+
LocalDate revisedEndDt,
32+
LocalDateTime actualBeginDtTm,
33+
LocalDateTime actualEndDtTm,
34+
String riaComment,
35+
Integer requestSkey,
36+
String reqId,
37+
String itemId,
38+
String seedlotSample,
39+
Integer riaSkey
40+
) {
41+
}
42+
43+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package ca.bc.gov.oracleapi.endpoint.consep;
2+
3+
import ca.bc.gov.oracleapi.dto.consep.ActivitySearchRequestDto;
4+
import ca.bc.gov.oracleapi.dto.consep.ActivitySearchResponseDto;
5+
import ca.bc.gov.oracleapi.security.RoleAccessConfig;
6+
import ca.bc.gov.oracleapi.service.consep.ActivitySearchService;
7+
import io.swagger.v3.oas.annotations.media.Content;
8+
import io.swagger.v3.oas.annotations.media.Schema;
9+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springdoc.core.annotations.ParameterObject;
14+
import org.springframework.data.domain.Pageable;
15+
import org.springframework.web.bind.annotation.PostMapping;
16+
import org.springframework.web.bind.annotation.RequestBody;
17+
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.springframework.web.bind.annotation.RestController;
19+
import org.springframework.data.web.PageableDefault;
20+
import org.springframework.validation.annotation.Validated;
21+
import jakarta.validation.Valid;
22+
23+
24+
import java.util.List;
25+
26+
@RestController
27+
@RequestMapping("/api/testing-activities")
28+
@RequiredArgsConstructor
29+
@Validated
30+
@Tag(name = "TestingActivitySearch", description = "Resource to search testing activities.")
31+
public class ActivitySearchEndpoint {
32+
private final ActivitySearchService activitySearchService;
33+
34+
@PostMapping("/search")
35+
@ApiResponses(value = {
36+
@ApiResponse(
37+
responseCode = "200",
38+
description = """
39+
Successfully found the testing activity data.
40+
"""),
41+
@ApiResponse(
42+
responseCode = "401",
43+
description = "Access token is missing or invalid",
44+
content =
45+
@Content(
46+
schema = @Schema(implementation = Void.class))),
47+
@ApiResponse(
48+
responseCode = "404",
49+
content =
50+
@Content(
51+
schema = @Schema(hidden = true)))
52+
})
53+
@RoleAccessConfig({"SPAR_TSC_ADMIN", "SPAR_MINISTRY_ORCHARD", "SPAR_NONMINISTRY_ORCHARD"})
54+
public List<ActivitySearchResponseDto> searchActivities(
55+
@Valid @RequestBody ActivitySearchRequestDto filter,
56+
@ParameterObject @PageableDefault(size = 20) Pageable paginationParameters
57+
) {
58+
return activitySearchService.searchActivities(filter, paginationParameters);
59+
}
60+
}

0 commit comments

Comments
 (0)