diff --git a/.gitignore b/.gitignore index 3bcc45ec1..996bb61cf 100644 --- a/.gitignore +++ b/.gitignore @@ -210,4 +210,4 @@ schemaspy/output # local testing *.bat -oracle-api/config \ No newline at end of file +oracle-api/config diff --git a/frontend/src/api-service/ApiConfig.ts b/frontend/src/api-service/ApiConfig.ts index df8da4096..9b301768d 100644 --- a/frontend/src/api-service/ApiConfig.ts +++ b/frontend/src/api-service/ApiConfig.ts @@ -55,7 +55,9 @@ const ApiConfig = { areaOfUseSpzList: `${oracleServerHost}/api/area-of-use/spz-list/vegetation-code`, - parentTreeByVegCode: `${oracleServerHost}/api/parent-trees/vegetation-codes/{vegCode}` + parentTreeByVegCode: `${oracleServerHost}/api/parent-trees/vegetation-codes/{vegCode}`, + + seedlotFromOracleDbBySeedlotNumber: `${oracleServerHost}/api/seedlot/{seedlotNumber}` }; export default ApiConfig; diff --git a/frontend/src/api-service/seedlotAPI.ts b/frontend/src/api-service/seedlotAPI.ts index 24217771d..3a4c9ae49 100644 --- a/frontend/src/api-service/seedlotAPI.ts +++ b/frontend/src/api-service/seedlotAPI.ts @@ -72,3 +72,8 @@ export const getAClassSeedlotFullForm = (seedlotNumber: string) => { const url = `${ApiConfig.seedlots}/${seedlotNumber}/a-class-full-form`; return api.get(url).then((res) => res.data as SeedlotAClassFullResponseType); }; + +export const getSeedlotFromOracleDbBySeedlotNumber = (seedlotNumber: string) => { + const url = ApiConfig.seedlotFromOracleDbBySeedlotNumber.replace('{seedlotNumber}', seedlotNumber); + return api.get(url); +}; diff --git a/frontend/src/components/ClientAndCodeInput/definitions.ts b/frontend/src/components/ClientAndCodeInput/definitions.ts index 4e6063f6c..9a1518e35 100644 --- a/frontend/src/components/ClientAndCodeInput/definitions.ts +++ b/frontend/src/components/ClientAndCodeInput/definitions.ts @@ -18,6 +18,7 @@ type ClientAndCodeInputProps = { readOnly?: boolean, maxInputColSize?: number, checkBoxInput?: BooleanInputType + shouldSelectDefaultValue?: boolean } export default ClientAndCodeInputProps; diff --git a/frontend/src/components/ClientAndCodeInput/index.tsx b/frontend/src/components/ClientAndCodeInput/index.tsx index c054ba2ef..67eedc36c 100644 --- a/frontend/src/components/ClientAndCodeInput/index.tsx +++ b/frontend/src/components/ClientAndCodeInput/index.tsx @@ -26,7 +26,7 @@ import './styles.scss'; const ClientAndCodeInput = ({ checkboxId, clientInput, locationCodeInput, textConfig, defaultClientNumber, defaultLocCode, setClientAndCode, readOnly, showCheckbox, maxInputColSize, - checkBoxInput + checkBoxInput, shouldSelectDefaultValue = false }: ClientAndCodeInputProps) => { const getIsDefaultVal = () => ( checkBoxInput === undefined @@ -38,9 +38,16 @@ const ClientAndCodeInput = ({ const clientInputRef = useRef(null); const locCodeInputRef = useRef(null); const [isDefault, setIsDefault] = useState( - () => getIsDefaultVal() + !shouldSelectDefaultValue ? false : () => getIsDefaultVal() ); + const [isChecked, setIsChecked] = useState(() => { + if (!shouldSelectDefaultValue) { + return false; + } + return checkBoxInput ? checkBoxInput.value : isDefault; + }); + const [showClientValidationStatus, setShowClientValidationStatus] = useState(true); const [showLocCodeValidationStatus, setShowLocCodeValidationStatus] = useState(false); @@ -60,7 +67,9 @@ const ClientAndCodeInput = ({ useEffect(() => { const areValsDefault = getIsDefaultVal(); - setIsDefault(areValsDefault); + if (shouldSelectDefaultValue) { + setIsDefault(areValsDefault); + } // Do not show validation status if isDefault is true if (areValsDefault) { @@ -223,10 +232,8 @@ const ClientAndCodeInput = ({ } : undefined ); - - if (!checkBoxInput) { - setIsDefault(checked); - } + setIsDefault(checked); + setIsChecked(checked); }; const [openAgnTooltip, setOpenAgnTooltip] = useState(false); @@ -343,7 +350,7 @@ const ClientAndCodeInput = ({ name={textConfig.useDefaultCheckbox.name} labelText={textConfig.useDefaultCheckbox.labelText} readOnly={readOnly} - checked={checkBoxInput ? checkBoxInput.value : isDefault} + checked={isChecked} onChange={(e: React.ChangeEvent) => { handleDefaultCheckBox(e.target.checked); }} @@ -363,7 +370,7 @@ const ClientAndCodeInput = ({ id={clientInput.id} autoCapitalize="on" labelText={textConfig.agencyInput.titleText} - defaultValue={forestClientQuery.data?.acronym} + defaultValue={shouldSelectDefaultValue ? forestClientQuery.data?.acronym : ''} helperText={ (readOnly || (showCheckbox && isDefault)) ? null @@ -406,7 +413,7 @@ const ClientAndCodeInput = ({ id={locationCodeInput.id} ref={locCodeInputRef} name={textConfig.locationCode.name} - defaultValue={locationCodeInput.value} + defaultValue={shouldSelectDefaultValue ? locationCodeInput.value : ''} type="number" maxCount={LOCATION_CODE_LIMIT} enableCounter diff --git a/frontend/src/components/LotApplicantAndInfoForm/index.tsx b/frontend/src/components/LotApplicantAndInfoForm/index.tsx index 6d81177da..03fb63185 100644 --- a/frontend/src/components/LotApplicantAndInfoForm/index.tsx +++ b/frontend/src/components/LotApplicantAndInfoForm/index.tsx @@ -118,6 +118,7 @@ const LotApplicantAndInfoForm = ({ } readOnly={isEdit} maxInputColSize={6} + shouldSelectDefaultValue /> diff --git a/frontend/src/components/SeedlotRegistrationSteps/CollectionStep/constants.ts b/frontend/src/components/SeedlotRegistrationSteps/CollectionStep/constants.ts index a3fa2d971..9eddccfae 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/CollectionStep/constants.ts +++ b/frontend/src/components/SeedlotRegistrationSteps/CollectionStep/constants.ts @@ -49,12 +49,12 @@ export const fieldsConfig = { }, volumePerContainers: { name: 'volumePerContainers', - labelText: 'Volume per Containers (HI)', + labelText: 'Volume per containers (hl)', invalidText: 'Invalid entry. Number must be between 0 and 10,000 and up to 3 decimal places.' }, volumeOfCones: { name: 'volumeOfCones', - labelText: 'Volume of Cones (HI)', + labelText: 'Volume of cones (hl)', invalidText: 'Number has more than 3 decimals.', helperText: 'This value must be the "Volume per container" X "Number of containers".', warnText: 'The total volume of cones does not equal, please note that this value must be the "Volume per container" x "Number of containers"' diff --git a/frontend/src/components/SeedlotRegistrationSteps/OwnershipStep/index.tsx b/frontend/src/components/SeedlotRegistrationSteps/OwnershipStep/index.tsx index bef78b0ec..9361c5fe0 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/OwnershipStep/index.tsx +++ b/frontend/src/components/SeedlotRegistrationSteps/OwnershipStep/index.tsx @@ -18,6 +18,7 @@ import { EmptyMultiOptObj } from '../../../shared-constants/shared-constants'; import { THREE_HALF_HOURS, THREE_HOURS } from '../../../config/TimeUnits'; import { getMultiOptList } from '../../../utils/MultiOptionsUtils'; import getFundingSources from '../../../api-service/fundingSourcesAPI'; +import { getSeedlotFromOracleDbBySeedlotNumber } from '../../../api-service/seedlotAPI'; import TitleAccordion from '../../TitleAccordion'; import ScrollToTop from '../../ScrollToTop'; import SingleOwnerInfo from './SingleOwnerInfo'; @@ -53,7 +54,8 @@ const OwnershipStep = ({ isReview }: OwnershipStepProps) => { setStepData, defaultClientNumber: defaultAgency, defaultCode, - isFormSubmitted + isFormSubmitted, + seedlotNumber } = useContext(ClassAContext); const [accordionControls, setAccordionControls] = useState({}); @@ -107,6 +109,12 @@ const OwnershipStep = ({ isReview }: OwnershipStepProps) => { cacheTime: THREE_HALF_HOURS }); + const getSeedlotBySeedlotNumberQuery = useQuery( + ['get-seedlot-by-seedlotNumber', seedlotNumber], + () => getSeedlotFromOracleDbBySeedlotNumber(seedlotNumber ?? ''), + { enabled: !!seedlotNumber } + ); + // Set default method of payment for the first owner. useEffect(() => { if (methodsOfPaymentQuery.status === 'success') { @@ -143,6 +151,8 @@ const OwnershipStep = ({ isReview }: OwnershipStepProps) => { const getFcQuery = (clientNumber: string): ForestClientType | undefined => qc.getQueryData(['forest-clients', clientNumber]); + const originalSeedQty = getSeedlotBySeedlotNumberQuery.data?.data?.originalSeedQty ?? 0; + return (
@@ -209,7 +219,7 @@ const OwnershipStep = ({ isReview }: OwnershipStepProps) => { checkPortionSum={ (updtEntry: SingleOwnerForm, id: number) => checkPortionSum(updtEntry, id) } - readOnly={isFormSubmitted} + readOnly={isFormSubmitted || originalSeedQty > 0} isReview={isReview} /> diff --git a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/constants.tsx b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/constants.tsx index 9ab03349a..be6230004 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/constants.tsx +++ b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/constants.tsx @@ -219,12 +219,13 @@ export const geneticWorthDict: GeneticWorthDictType = { PW: ['dsb'], DR: ['gvo'], EP: ['gvo'], - FDI: ['gvo'], + FDI: ['gvo', 'wwd'], HW: ['gvo'], LW: ['gvo'], PY: ['gvo'], SS: ['gvo', 'iws'], SX: ['gvo', 'iws'], + YC: ['gvo'], UNKNOWN: ['gvo'] }; diff --git a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/definitions.ts b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/definitions.ts index 5c8ed38d9..56cf13077 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/definitions.ts +++ b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/definitions.ts @@ -82,7 +82,21 @@ export type NotifCtrlType = { } } -type SpeciesWithGenWorth = 'CW'| 'PLI' |'FDC' | 'PW' | 'DR' | 'EP' | 'FDI' | 'HW' | 'LW' | 'PY' | 'SS' | 'SX' | 'UNKNOWN'; +type SpeciesWithGenWorth = + 'CW' + |'PLI' + |'FDC' + |'PW' + |'DR' + |'EP' + |'FDI' + |'HW' + |'LW' + |'PY' + |'SS' + |'SX' + |'YC' + |'UNKNOWN'; export type GeneticWorthDictType = { [key in SpeciesWithGenWorth]: string[] diff --git a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/index.tsx b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/index.tsx index e4bfa779c..186e23f79 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/index.tsx +++ b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/index.tsx @@ -270,8 +270,7 @@ const ParentTreeStep = ({ isReviewDisplay, isReviewRead }: ParentTreeStepProps) setHeaderConfig, weightedGwInfoItems, setWeightedGwInfoItems, - setApplicableGenWorths, - isReviewDisplay ?? false + setApplicableGenWorths ), [seedlotSpecies]); const uploadCompostion = useMutation({ diff --git a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/utils.ts b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/utils.ts index 80679e1c8..b4036906f 100644 --- a/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/utils.ts +++ b/frontend/src/components/SeedlotRegistrationSteps/ParentTreeStep/utils.ts @@ -545,8 +545,7 @@ export const configHeaderOpt = ( setHeaderConfig: Function, weightedGwInfoItems: Record, setWeightedGwInfoItems: Function, - setApplicableGenWorths: Function, - isReview: boolean + setApplicableGenWorths: Function ) => { const speciesKey = Object.keys(geneticWorthDict).includes(seedlotSpecies.code) ? seedlotSpecies.code.toUpperCase() @@ -562,10 +561,8 @@ export const configHeaderOpt = ( // Enable option in the column customization clonedHeaders[optionIndex].isAnOption = true; - // When on review mode, display all columns - if (isReview) { - clonedHeaders[optionIndex].enabled = true; - } + // Display all columns by default + clonedHeaders[optionIndex].enabled = true; // Enable weighted option in mix tab const weightedIndex = headerConfig.findIndex((header) => header.id === `w_${opt}`); @@ -923,15 +920,11 @@ export const isMissingSecondaryOrchard = (orchardStepData: OrchardForm): boolean * Check if orchards selections are valid. */ export const areOrchardsValid = (orchardStepData: OrchardForm): boolean => { - let isValid = true; const { orchards } = orchardStepData; if (!orchards.primaryOrchard.value.code) { - isValid = false; - } - if (isMissingSecondaryOrchard(orchardStepData)) { - isValid = false; + return false; } - return isValid; + return true; }; diff --git a/frontend/src/components/SeedlotTable/constants.ts b/frontend/src/components/SeedlotTable/constants.ts index 6a7afd360..03a0e1e8d 100644 --- a/frontend/src/components/SeedlotTable/constants.ts +++ b/frontend/src/components/SeedlotTable/constants.ts @@ -63,7 +63,7 @@ export const TableText = { }; export const PageSizesConfig = [ - 10, 20, 30, 40, 50 + 50, 100, 150, 200, 250 ]; export const ExclusiveAdminRows: Array = [ diff --git a/frontend/src/types/SeedlotType.ts b/frontend/src/types/SeedlotType.ts index 544245034..b3581ccf8 100644 --- a/frontend/src/types/SeedlotType.ts +++ b/frontend/src/types/SeedlotType.ts @@ -207,9 +207,9 @@ export type CollectionFormSubmitType = { collectionLocnCode: string, collectionStartDate: string, collectionEndDate: string, - noOfContainers: number, - volPerContainer: number, - clctnVolume: number, + noOfContainers: string, + volPerContainer: string, + clctnVolume: string, seedlotComment: string, coneCollectionMethodCodes: Array } diff --git a/frontend/src/views/Seedlot/ContextContainerClassA/constants.tsx b/frontend/src/views/Seedlot/ContextContainerClassA/constants.tsx index 7eb64a11c..f9a33bc13 100644 --- a/frontend/src/views/Seedlot/ContextContainerClassA/constants.tsx +++ b/frontend/src/views/Seedlot/ContextContainerClassA/constants.tsx @@ -120,9 +120,9 @@ export const emptyCollectionStep: CollectionFormSubmitType = { collectionLocnCode: '', collectionStartDate: '', collectionEndDate: '', - noOfContainers: 1, - volPerContainer: 1, - clctnVolume: 1, + noOfContainers: '', + volPerContainer: '', + clctnVolume: '', seedlotComment: '', coneCollectionMethodCodes: [] }; diff --git a/frontend/src/views/Seedlot/ContextContainerClassA/utils.ts b/frontend/src/views/Seedlot/ContextContainerClassA/utils.ts index 5a480774a..590b51f1f 100644 --- a/frontend/src/views/Seedlot/ContextContainerClassA/utils.ts +++ b/frontend/src/views/Seedlot/ContextContainerClassA/utils.ts @@ -852,9 +852,9 @@ export const convertCollection = (collectionData: CollectionForm): CollectionFor // Assume the date values are present as validation has occurred before payload is generated collectionStartDate: localDateToUtcFormat(collectionData.startDate.value)!, collectionEndDate: localDateToUtcFormat(collectionData.endDate.value)!, - noOfContainers: +collectionData.numberOfContainers.value, - volPerContainer: +collectionData.volumePerContainers.value, - clctnVolume: +collectionData.volumeOfCones.value, + noOfContainers: `${+collectionData.numberOfContainers.value}`, + volPerContainer: `${+collectionData.volumePerContainers.value}`, + clctnVolume: `${+collectionData.volumeOfCones.value}`, seedlotComment: collectionData.comments.value, coneCollectionMethodCodes: collectionData .selectedCollectionCodes.value.map((code) => parseInt(code, 10)) diff --git a/frontend/src/views/Seedlot/MySeedlots/index.tsx b/frontend/src/views/Seedlot/MySeedlots/index.tsx index f38f87631..43baaf8bb 100644 --- a/frontend/src/views/Seedlot/MySeedlots/index.tsx +++ b/frontend/src/views/Seedlot/MySeedlots/index.tsx @@ -66,7 +66,7 @@ const MySeedlots = () => { isSortable showSearch showPagination - defaultPageSize={20} + defaultPageSize={50} /> diff --git a/frontend/src/views/Seedlot/ReviewSeedlots/index.tsx b/frontend/src/views/Seedlot/ReviewSeedlots/index.tsx index 440039d18..4c6d973e9 100644 --- a/frontend/src/views/Seedlot/ReviewSeedlots/index.tsx +++ b/frontend/src/views/Seedlot/ReviewSeedlots/index.tsx @@ -57,7 +57,7 @@ const ReviewSeedlots = () => { isSortable showSearch showPagination - defaultPageSize={20} + defaultPageSize={50} />
diff --git a/frontend/src/views/Seedlot/SeedlotReview/SeedlotReviewContent.tsx b/frontend/src/views/Seedlot/SeedlotReview/SeedlotReviewContent.tsx index a7f45fb1f..f47855484 100644 --- a/frontend/src/views/Seedlot/SeedlotReview/SeedlotReviewContent.tsx +++ b/frontend/src/views/Seedlot/SeedlotReview/SeedlotReviewContent.tsx @@ -13,7 +13,7 @@ import { } from '@carbon/icons-react'; import { Beforeunload } from 'react-beforeunload'; -import { getSeedlotById, putAClassSeedlotProgress } from '../../../api-service/seedlotAPI'; +import { getSeedlotById, putAClassSeedlotProgress, getSeedlotFromOracleDbBySeedlotNumber } from '../../../api-service/seedlotAPI'; import { THREE_HALF_HOURS, THREE_HOURS } from '../../../config/TimeUnits'; import getVegCodes from '../../../api-service/vegetationCodeAPI'; import Breadcrumbs from '../../../components/Breadcrumbs'; @@ -105,6 +105,12 @@ const SeedlotReviewContent = () => { refetchOnMount: true }); + const getSeedlotBySeedlotNumberQuery = useQuery({ + queryKey: ['seedlot-by-seedlotNumber', seedlotNumber], + queryFn: () => getSeedlotFromOracleDbBySeedlotNumber(seedlotNumber ?? ''), + enabled: seedlotQuery.isFetched + }); + useEffect(() => { const { status } = seedlotQuery; @@ -550,6 +556,8 @@ const SeedlotReviewContent = () => { className="edit-save-btn" renderIcon={isReadMode ? Edit : Save} onClick={handleEditSaveBtn} + disabled={getSeedlotBySeedlotNumberQuery.isSuccess + && getSeedlotBySeedlotNumberQuery.data.data.originalSeedQty > 0} > {isReadMode ? 'Edit seedlot' : 'Save edit'} diff --git a/oracle-api/config/application-local.yml b/oracle-api/config/application-local.yml new file mode 100644 index 000000000..8a5b3d520 --- /dev/null +++ b/oracle-api/config/application-local.yml @@ -0,0 +1,5 @@ +spring: + datasource: + url: jdbc:oracle:thin:@tcp://localhost:1521/dbdock_01 + username: THE + password: default diff --git a/oracle-api/src/main/java/ca/bc/gov/oracleapi/endpoint/SeedlotEndpoint.java b/oracle-api/src/main/java/ca/bc/gov/oracleapi/endpoint/SeedlotEndpoint.java new file mode 100644 index 000000000..4932dd289 --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/oracleapi/endpoint/SeedlotEndpoint.java @@ -0,0 +1,73 @@ +package ca.bc.gov.oracleapi.endpoint; + +import ca.bc.gov.oracleapi.config.SparLog; +import ca.bc.gov.oracleapi.entity.Seedlot; +import ca.bc.gov.oracleapi.repository.SeedlotRepository; +import ca.bc.gov.oracleapi.security.RoleAccessConfig; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +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.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** This class exposes seedlot resources API. */ +@RestController +@RequestMapping("/api/seedlot") +@Tag(name = "seedlot", description = "Resource to retrieve seedlot") +public class SeedlotEndpoint { + + private SeedlotRepository seedlotRepository; + + SeedlotEndpoint(SeedlotRepository seedlotRepository) { + this.seedlotRepository = seedlotRepository; + } + + /** + * Retrieve a seedlot by seedlot number. + * + * @return A record of {@link Seedlot}. + */ + @GetMapping( + path = "/{seedlotNumber}", + produces = "application/json") + @Operation( + summary = "Retrieve a seedlot by seedlot number", + description = "Retrieve a seedlot by seedlot number ") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "Returns a record of seedlot", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Seedlot.class))), + @ApiResponse( + responseCode = "401", + description = "Access token is missing or invalid", + content = @Content(schema = @Schema(implementation = Void.class))) + }) + @RoleAccessConfig({"SPAR_TSC_ADMIN", "SPAR_MINISTRY_ORCHARD", "SPAR_NONMINISTRY_ORCHARD"}) + public Seedlot getSeedlotBySeedlotNumber( + @PathVariable + @Parameter( + name = "seedlotNumber", + in = ParameterIn.PATH, + description = "Identifier of the seedlot.") + String seedlotNumber + ) { + SparLog.info("Fetch a seedlot by seedlot number"); + SparLog.info(seedlotNumber); + Seedlot seedlot = seedlotRepository.findSeedlotBySeedlotNumber(seedlotNumber); + SparLog.info("{} valid seedlot found.", seedlot); + + return seedlot; + } +} diff --git a/oracle-api/src/main/java/ca/bc/gov/oracleapi/entity/Seedlot.java b/oracle-api/src/main/java/ca/bc/gov/oracleapi/entity/Seedlot.java new file mode 100644 index 000000000..1b534ba7b --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/oracleapi/entity/Seedlot.java @@ -0,0 +1,29 @@ +package ca.bc.gov.oracleapi.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** This class presents a funding source to an agency seedlot owner. */ +@Getter +@Setter +@Entity +@Table(name = "SEEDLOT") +@Schema(description = "Represents a partial seedlot object in the database") +public class Seedlot { + + @Id + @Column(name = "SEEDLOT_NUMBER") + @Schema(description = "The number of a seedlot", example = "16258") + private Long seedlotNumber; + + @Column(name = "ORIGINAL_SEED_QTY") + @Schema( + description = "The original quantity of seeds in the seedlot", + example = "1") + private Long originalSeedQty; +} diff --git a/oracle-api/src/main/java/ca/bc/gov/oracleapi/repository/SeedlotRepository.java b/oracle-api/src/main/java/ca/bc/gov/oracleapi/repository/SeedlotRepository.java new file mode 100644 index 000000000..ae354807c --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/oracleapi/repository/SeedlotRepository.java @@ -0,0 +1,13 @@ +package ca.bc.gov.oracleapi.repository; + +import ca.bc.gov.oracleapi.entity.Seedlot; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +/** This interface enables the funding source entity to be retrieved from the database. */ +public interface SeedlotRepository extends JpaRepository { + + @Query("SELECT s FROM Seedlot s WHERE s.seedlotNumber = :seedlotNumber") + Seedlot findSeedlotBySeedlotNumber(@Param("seedlotNumber") String seedlotNumber); +}