diff --git a/backend/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java b/backend/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java index a8acd2ada..8be603f6d 100644 --- a/backend/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java +++ b/backend/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java @@ -8,8 +8,10 @@ @Schema(description = "Represents an Orchard object received from oracle-api.") public record OrchardDto( @Schema( - description = """ - A unique identifier of an orchard + description = + """ + A unique identifier which is assigned to a location where cuttings or + A class seed is produced. """, example = "339") String id, @@ -38,4 +40,10 @@ public record OrchardDto( @Schema( description = "A code which represents the current stage or status of an orchard.", example = "PRD") - String stageCode) {} + String stageCode, + @Schema(description = "The bgc zone code", example = "SBS") String becZoneCode, + @Schema(description = "The description of a bgc zone code", example = "Sub-Boreal Spruce") + String becZoneDescription, + @Schema(description = "The bgc sub-zone code", example = "wk") String becSubzoneCode, + @Schema(description = "The variant.", example = "1") Character variant, + @Schema(description = "The bec version id.", example = "5") Integer becVersionId) {} diff --git a/backend/src/main/java/ca/bc/gov/backendstartapi/entity/seedlot/Seedlot.java b/backend/src/main/java/ca/bc/gov/backendstartapi/entity/seedlot/Seedlot.java index 3954a110c..777d69dda 100644 --- a/backend/src/main/java/ca/bc/gov/backendstartapi/entity/seedlot/Seedlot.java +++ b/backend/src/main/java/ca/bc/gov/backendstartapi/entity/seedlot/Seedlot.java @@ -223,6 +223,9 @@ public class Seedlot implements Serializable { @Column(name = "bgc_zone_code", length = 4) private String bgcZoneCode; + @Column(name = "bgc_zone_description", length = 120) + private String bgcZoneDescription; + @Column(name = "bgc_subzone_code", length = 3) private String bgcSubzoneCode; diff --git a/backend/src/main/java/ca/bc/gov/backendstartapi/provider/OracleApiProvider.java b/backend/src/main/java/ca/bc/gov/backendstartapi/provider/OracleApiProvider.java index 38ef566aa..57ab62f50 100644 --- a/backend/src/main/java/ca/bc/gov/backendstartapi/provider/OracleApiProvider.java +++ b/backend/src/main/java/ca/bc/gov/backendstartapi/provider/OracleApiProvider.java @@ -246,4 +246,28 @@ public Optional getAreaOfUseData(Integer spuId) { return Optional.empty(); } + + @Override + public Optional findOrchardById(String orchardId) { + String oracleApiUrl = String.format("%s/api/orchards/{orchardId}", rootUri); + + SparLog.info("Starting {} - {} request to {}", PROVIDER, "findOrchardById", oracleApiUrl); + + try { + ResponseEntity areaOfUseRes = + restTemplate.exchange( + oracleApiUrl, + HttpMethod.GET, + new HttpEntity<>(addHttpHeaders()), + new ParameterizedTypeReference() {}, + createParamsMap("orchardId", orchardId)); + SparLog.info("GET orchard by id - Success response!"); + return Optional.of(areaOfUseRes.getBody()); + } catch (HttpClientErrorException httpExc) { + SparLog.error( + "GET orchards by vegCode from oracle - Response code error: {}", httpExc.getStatusCode()); + } + + return Optional.empty(); + } } diff --git a/backend/src/main/java/ca/bc/gov/backendstartapi/provider/Provider.java b/backend/src/main/java/ca/bc/gov/backendstartapi/provider/Provider.java index 3ef0e3a59..e89349700 100644 --- a/backend/src/main/java/ca/bc/gov/backendstartapi/provider/Provider.java +++ b/backend/src/main/java/ca/bc/gov/backendstartapi/provider/Provider.java @@ -57,6 +57,10 @@ default Optional getAreaOfUseData(Integer spuId) { return Optional.empty(); } + default Optional findOrchardById(String orchardId) { + return Optional.empty(); + } + // Common methods String[] addAuthorizationHeader(); diff --git a/backend/src/main/java/ca/bc/gov/backendstartapi/service/SeedlotService.java b/backend/src/main/java/ca/bc/gov/backendstartapi/service/SeedlotService.java index 62bbb9d24..b088c0766 100644 --- a/backend/src/main/java/ca/bc/gov/backendstartapi/service/SeedlotService.java +++ b/backend/src/main/java/ca/bc/gov/backendstartapi/service/SeedlotService.java @@ -5,6 +5,7 @@ import ca.bc.gov.backendstartapi.dto.GeneticWorthTraitsDto; import ca.bc.gov.backendstartapi.dto.GeospatialRequestDto; import ca.bc.gov.backendstartapi.dto.GeospatialRespondDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.OrchardParentTreeValsDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticQualityDto; import ca.bc.gov.backendstartapi.dto.PtCalculationResDto; @@ -591,6 +592,8 @@ public SeedlotStatusResponseDto updateSeedlotWithForm( // Extraction Step 6 saveSeedlotFormStep6(seedlot, form.seedlotFormExtractionDto()); + setBecValues(seedlot, form.seedlotFormOrchardDto().primaryOrchardId()); + setParentTreeContribution( seedlot, form.seedlotFormParentTreeDtoList(), form.seedlotFormParentTreeSmpDtoList()); @@ -606,11 +609,30 @@ public SeedlotStatusResponseDto updateSeedlotWithForm( seedlotNumber, seedlot.getSeedlotStatus().getSeedlotStatusCode()); } + private void setBecValues(Seedlot seedlot, String primaryOrchardId) { + SparLog.info("Begin to set BEC values"); + + OrchardDto orchardDto = + oracleApiProvider + .findOrchardById(primaryOrchardId) + .orElseThrow(OracleApiProviderException::new); + + // Not sure why it's called Bgc in seedlot instead of Bec in orchard + seedlot.setBgcZoneCode(orchardDto.becZoneCode()); + seedlot.setBgcZoneDescription(orchardDto.becZoneDescription()); + seedlot.setBgcSubzoneCode(orchardDto.becSubzoneCode()); + seedlot.setVariant(orchardDto.variant()); + seedlot.setBecVersionId(orchardDto.becVersionId()); + + SparLog.info("BEC values set"); + } + private void setParentTreeContribution( Seedlot seedlot, List orchardPtDtoList, List smpPtDtoList) { + SparLog.info("Begin to set parent trees contribution"); List orchardPtVals = convertToPtVals(orchardPtDtoList); List smpMixIdAndProps = convertToGeoRes(smpPtDtoList); @@ -633,6 +655,7 @@ private void setParentTreeContribution( seedlot.setCollectionLongitudeDeg(collectionGeoData.getMeanLongitudeDegree()); seedlot.setCollectionLongitudeMin(collectionGeoData.getMeanLongitudeMinute()); seedlot.setCollectionLongitudeSec(collectionGeoData.getMeanLongitudeSecond()); + SparLog.info("Parent trees contribution set"); } private List convertToPtVals( @@ -695,6 +718,7 @@ private List getGeneticTraitList( * @param primaryOrchardId the primary orchard Id to find the spu for */ private void setAreaOfUse(Seedlot seedlot, String primaryOrchardId) { + SparLog.info("Begin to set Area of Use values"); ActiveOrchardSpuEntity activeSpuEntity = orchardService .findSpuIdByOrchardWithActive(primaryOrchardId, true) @@ -776,6 +800,8 @@ private void setAreaOfUse(Seedlot seedlot, String primaryOrchardId) { spzSaveList.add(sspzToSave); }); seedlotSeedPlanZoneRepository.saveAll(spzSaveList); + + SparLog.info("Area of Use values set"); } private void setSeedlotStatus(Seedlot seedlot, String newStatus) { diff --git a/backend/src/main/resources/db/migration/V38__add_bec_desc_to_seedlot.sql b/backend/src/main/resources/db/migration/V38__add_bec_desc_to_seedlot.sql new file mode 100644 index 000000000..8f6b65f4c --- /dev/null +++ b/backend/src/main/resources/db/migration/V38__add_bec_desc_to_seedlot.sql @@ -0,0 +1,366 @@ +-- Add a BEC zone description column to the seedlot table -- +ALTER TABLE + spar.seedlot +ADD + COLUMN bgc_zone_description varchar(120) default null; + +COMMENT ON COLUMN spar.seedlot.bgc_zone_description IS 'The description of the BEC zone.'; + +/* Update trigger */ + +CREATE OR REPLACE FUNCTION spar.seedlot_if_modified_func() RETURNS trigger AS $body$ +DECLARE + v_old_data TEXT; + v_new_data TEXT; + v_auditrevision int; +BEGIN + if (TG_OP = 'UPDATE') then + v_old_data := ROW(OLD.*); + v_new_data := ROW(NEW.*); + /* AUDIT REVISION number used to order the statements executed in the row */ + v_auditrevision := (SELECT MAX(COALESCE(audit_revision_version,1))+1 FROM spar.seedlot_audit WHERE seedlot_number = NEW.seedlot_number); + INSERT INTO spar.seedlot_audit (spar_audit_code,db_user,audit_revision_version,seedlot_number,seedlot_status_code,applicant_client_number,applicant_locn_code,applicant_email_address,vegetation_code,genetic_class_code,seedlot_source_code,to_be_registrd_ind,bc_source_ind,collection_client_number,collection_locn_code,collection_start_date,collection_end_date,no_of_containers,vol_per_container,clctn_volume,seedlot_comment,interm_strg_client_number,interm_strg_locn_code,interm_strg_st_date,interm_strg_end_date,interm_facility_code,female_gametic_mthd_code,male_gametic_mthd_code,controlled_cross_ind,biotech_processes_ind,pollen_contamination_ind,pollen_contamination_pct,contaminant_pollen_bv,pollen_contamination_mthd_code,total_parent_trees,smp_success_pct,effective_pop_size,smp_parents_outside,non_orchard_pollen_contam_pct,extractory_client_number,extractory_locn_code,extraction_st_date,extraction_end_date,temporary_strg_client_number,temporary_strg_locn_code,temporary_strg_start_date,temporary_strg_end_date,interm_strg_locn,declared_userid,declared_timestamp,entry_userid,entry_timestamp,seed_plan_unit_id,bgc_zone_code,bgc_subzone_code,variant,bec_version_id,elevation,latitude_degrees,latitude_minutes,latitude_seconds,longitude_degrees,longitude_minutes,longitude_seconds,collection_elevation,collection_elevation_min,collection_elevation_max,collection_latitude_deg,collection_latitude_min,collection_latitude_sec,collection_latitude_code,collection_longitude_deg,collection_longitude_min,collection_longitude_sec,collection_longitude_code,elevation_min,elevation_max,latitude_deg_min,latitude_min_min,latitude_sec_min,latitude_deg_max,latitude_min_max,latitude_sec_max,longitude_deg_min,longitude_min_min,longitude_sec_min,longitude_deg_max,longitude_min_max,longitude_sec_max,smp_mean_bv_growth,area_of_use_comment,approved_timestamp,approved_userid,mean_geom,update_userid,update_timestamp,revision_count) + VALUES( + /*spar_audit_code */ 'U', + /*db_user */ session_user::TEXT, + /*audit_revision_version */ coalesce(v_auditrevision,1), + /*seedlot_number */ NEW.seedlot_number, + /*seedlot_status_code */ NEW.seedlot_status_code, + /*applicant_client_number */ NEW.applicant_client_number, + /*applicant_locn_code */ NEW.applicant_locn_code, + /*applicant_email_address */ NEW.applicant_email_address, + /*vegetation_code */ NEW.vegetation_code, + /*genetic_class_code */ NEW.genetic_class_code, + /*seedlot_source_code */ NEW.seedlot_source_code, + /*to_be_registrd_ind */ NEW.to_be_registrd_ind, + /*bc_source_ind */ NEW.bc_source_ind, + /*collection_client_number */ NEW.collection_client_number, + /*collection_locn_code */ NEW.collection_locn_code, + /*collection_start_date */ NEW.collection_start_date, + /*collection_end_date */ NEW.collection_end_date, + /*no_of_containers */ NEW.no_of_containers, + /*vol_per_container */ NEW.vol_per_container, + /*clctn_volume */ NEW.clctn_volume, + /*seedlot_comment */ NEW.seedlot_comment, + /*interm_strg_client_number */ NEW.interm_strg_client_number, + /*interm_strg_locn_code */ NEW.interm_strg_locn_code, + /*interm_strg_st_date */ NEW.interm_strg_st_date, + /*interm_strg_end_date */ NEW.interm_strg_end_date, + /*interm_facility_code */ NEW.interm_facility_code, + /*female_gametic_mthd_code */ NEW.female_gametic_mthd_code, + /*male_gametic_mthd_code */ NEW.male_gametic_mthd_code, + /*controlled_cross_ind */ NEW.controlled_cross_ind, + /*biotech_processes_ind */ NEW.biotech_processes_ind, + /*pollen_contamination_ind */ NEW.pollen_contamination_ind, + /*pollen_contamination_pct */ NEW.pollen_contamination_pct, + /*contaminant_pollen_bv */ NEW.contaminant_pollen_bv, + /*pollen_contamination_mthd_code */ NEW.pollen_contamination_mthd_code, + /*total_parent_trees */ NEW.total_parent_trees, + /*smp_success_pct */ NEW.smp_success_pct, + /*effective_pop_size */ NEW.effective_pop_size, + /*smp_parents_outside */ NEW.smp_parents_outside, + /*non_orchard_pollen_contam_pct */ NEW.non_orchard_pollen_contam_pct, + /*extractory_client_number */ NEW.extractory_client_number, + /*extractory_locn_code */ NEW.extractory_locn_code, + /*extraction_st_date */ NEW.extraction_st_date, + /*extraction_end_date */ NEW.extraction_end_date, + /*temporary_strg_client_number */ NEW.temporary_strg_client_number, + /*temporary_strg_locn_code */ NEW.temporary_strg_locn_code, + /*temporary_strg_start_date */ NEW.temporary_strg_start_date, + /*temporary_strg_end_date */ NEW.temporary_strg_end_date, + /*interm_strg_locn */ NEW.interm_strg_locn, + /*declared_userid */ NEW.declared_userid, + /*declared_timestamp */ NEW.declared_timestamp, + /*entry_userid */ NEW.entry_userid, + /*entry_timestamp */ NEW.entry_timestamp, + /*seed_plan_unit_id */ NEW.seed_plan_unit_id, + /*bgc_zone_code */ NEW.bgc_zone_code, + /*bgc_zone_description */ NEW.bgc_zone_description, + /*bgc_subzone_code */ NEW.bgc_subzone_code, + /*variant */ NEW.variant, + /*bec_version_id */ NEW.bec_version_id, + /*elevation */ NEW.elevation, + /*latitude_degrees */ NEW.latitude_degrees, + /*latitude_minutes */ NEW.latitude_minutes, + /*latitude_seconds */ NEW.latitude_seconds, + /*longitude_degrees */ NEW.longitude_degrees, + /*longitude_minutes */ NEW.longitude_minutes, + /*longitude_seconds */ NEW.longitude_seconds, + /*collection_elevation */ NEW.collection_elevation, + /*collection_elevation_min */ NEW.collection_elevation_min, + /*collection_elevation_max */ NEW.collection_elevation_max, + /*collection_latitude_deg */ NEW.collection_latitude_deg, + /*collection_latitude_min */ NEW.collection_latitude_min, + /*collection_latitude_sec */ NEW.collection_latitude_sec, + /*collection_latitude_code */ NEW.collection_latitude_code, + /*collection_longitude_deg */ NEW.collection_longitude_deg, + /*collection_longitude_min */ NEW.collection_longitude_min, + /*collection_longitude_sec */ NEW.collection_longitude_sec, + /*collection_longitude_code */ NEW.collection_longitude_code, + /*elevation_min */ NEW.elevation_min, + /*elevation_max */ NEW.elevation_max, + /*latitude_deg_min */ NEW.latitude_deg_min, + /*latitude_min_min */ NEW.latitude_min_min, + /*latitude_sec_min */ NEW.latitude_sec_min, + /*latitude_deg_max */ NEW.latitude_deg_max, + /*latitude_min_max */ NEW.latitude_min_max, + /*latitude_sec_max */ NEW.latitude_sec_max, + /*longitude_deg_min */ NEW.longitude_deg_min, + /*longitude_min_min */ NEW.longitude_min_min, + /*longitude_sec_min */ NEW.longitude_sec_min, + /*longitude_deg_max */ NEW.longitude_deg_max, + /*longitude_min_max */ NEW.longitude_min_max, + /*longitude_sec_max */ NEW.longitude_sec_max, + /*smp_mean_bv_growth */ NEW.smp_mean_bv_growth, + /*area_of_use_comment */ NEW.area_of_use_comment, + /*approved_timestamp */ NEW.approved_timestamp, + /*approved_userid */ NEW.approved_userid, + /*mean_geom */ NEW.mean_geom, + /*update_userid */ NEW.update_userid, + /*update_timestamp */ NEW.update_timestamp, + /*revision_count */ NEW.revision_count + ); + RETURN NEW; + elsif (TG_OP = 'DELETE') then + v_old_data := ROW(OLD.*); + /* insert into spar.logged_actions (schema_name,table_name,user_name,action,original_data,query) + values (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data, current_query());*/ + /* AUDIT REVISION number used to order the statements executed in the row */ + v_auditrevision := (SELECT MAX(COALESCE(audit_revision_version,1))+1 FROM spar.seedlot_audit WHERE seedlot_number = NEW.seedlot_number) ; + INSERT INTO spar.seedlot_audit (spar_audit_code,db_user,audit_revision_version,seedlot_number,seedlot_status_code,applicant_client_number,applicant_locn_code,applicant_email_address,vegetation_code,genetic_class_code,seedlot_source_code,to_be_registrd_ind,bc_source_ind,collection_client_number,collection_locn_code,collection_start_date,collection_end_date,no_of_containers,vol_per_container,clctn_volume,seedlot_comment,interm_strg_client_number,interm_strg_locn_code,interm_strg_st_date,interm_strg_end_date,interm_facility_code,female_gametic_mthd_code,male_gametic_mthd_code,controlled_cross_ind,biotech_processes_ind,pollen_contamination_ind,pollen_contamination_pct,contaminant_pollen_bv,pollen_contamination_mthd_code,total_parent_trees,smp_success_pct,effective_pop_size,smp_parents_outside,non_orchard_pollen_contam_pct,extractory_client_number,extractory_locn_code,extraction_st_date,extraction_end_date,temporary_strg_client_number,temporary_strg_locn_code,temporary_strg_start_date,temporary_strg_end_date,interm_strg_locn,declared_userid,declared_timestamp,entry_userid,entry_timestamp,seed_plan_unit_id,bgc_zone_code,bgc_subzone_code,variant,bec_version_id,elevation,latitude_degrees,latitude_minutes,latitude_seconds,longitude_degrees,longitude_minutes,longitude_seconds,collection_elevation,collection_elevation_min,collection_elevation_max,collection_latitude_deg,collection_latitude_min,collection_latitude_sec,collection_latitude_code,collection_longitude_deg,collection_longitude_min,collection_longitude_sec,collection_longitude_code,elevation_min,elevation_max,latitude_deg_min,latitude_min_min,latitude_sec_min,latitude_deg_max,latitude_min_max,latitude_sec_max,longitude_deg_min,longitude_min_min,longitude_sec_min,longitude_deg_max,longitude_min_max,longitude_sec_max,smp_mean_bv_growth,area_of_use_comment,approved_timestamp,approved_userid,mean_geom,update_userid,update_timestamp,revision_count) + VALUES( + /*spar_audit_code */ 'D', + /*db_user */ session_user::TEXT, + /*audit_revision_version */ coalesce(v_auditrevision,1), + /*seedlot_number */ OLD.seedlot_number, + /*seedlot_status_code */ OLD.seedlot_status_code, + /*applicant_client_number */ OLD.applicant_client_number, + /*applicant_locn_code */ OLD.applicant_locn_code, + /*applicant_email_address */ OLD.applicant_email_address, + /*vegetation_code */ OLD.vegetation_code, + /*genetic_class_code */ OLD.genetic_class_code, + /*seedlot_source_code */ OLD.seedlot_source_code, + /*to_be_registrd_ind */ OLD.to_be_registrd_ind, + /*bc_source_ind */ OLD.bc_source_ind, + /*collection_client_number */ OLD.collection_client_number, + /*collection_locn_code */ OLD.collection_locn_code, + /*collection_start_date */ OLD.collection_start_date, + /*collection_end_date */ OLD.collection_end_date, + /*no_of_containers */ OLD.no_of_containers, + /*vol_per_container */ OLD.vol_per_container, + /*clctn_volume */ OLD.clctn_volume, + /*seedlot_comment */ OLD.seedlot_comment, + /*interm_strg_client_number */ OLD.interm_strg_client_number, + /*interm_strg_locn_code */ OLD.interm_strg_locn_code, + /*interm_strg_st_date */ OLD.interm_strg_st_date, + /*interm_strg_end_date */ OLD.interm_strg_end_date, + /*interm_facility_code */ OLD.interm_facility_code, + /*female_gametic_mthd_code */ OLD.female_gametic_mthd_code, + /*male_gametic_mthd_code */ OLD.male_gametic_mthd_code, + /*controlled_cross_ind */ OLD.controlled_cross_ind, + /*biotech_processes_ind */ OLD.biotech_processes_ind, + /*pollen_contamination_ind */ OLD.pollen_contamination_ind, + /*pollen_contamination_pct */ OLD.pollen_contamination_pct, + /*contaminant_pollen_bv */ OLD.contaminant_pollen_bv, + /*pollen_contamination_mthd_code */ OLD.pollen_contamination_mthd_code, + /*total_parent_trees */ OLD.total_parent_trees, + /*smp_success_pct */ OLD.smp_success_pct, + /*effective_pop_size */ OLD.effective_pop_size, + /*smp_parents_outside */ OLD.smp_parents_outside, + /*non_orchard_pollen_contam_pct */ OLD.non_orchard_pollen_contam_pct, + /*extractory_client_number */ OLD.extractory_client_number, + /*extractory_locn_code */ OLD.extractory_locn_code, + /*extraction_st_date */ OLD.extraction_st_date, + /*extraction_end_date */ OLD.extraction_end_date, + /*temporary_strg_client_number */ OLD.temporary_strg_client_number, + /*temporary_strg_locn_code */ OLD.temporary_strg_locn_code, + /*temporary_strg_start_date */ OLD.temporary_strg_start_date, + /*temporary_strg_end_date */ OLD.temporary_strg_end_date, + /*interm_strg_locn */ OLD.interm_strg_locn, + /*declared_userid */ OLD.declared_userid, + /*declared_timestamp */ OLD.declared_timestamp, + /*entry_userid */ OLD.entry_userid, + /*entry_timestamp */ OLD.entry_timestamp, + /*seed_plan_unit_id */ OLD.seed_plan_unit_id, + /*bgc_zone_code */ OLD.bgc_zone_code, + /*bgc_zone_description */ OLD.bgc_zone_description, + /*bgc_subzone_code */ OLD.bgc_subzone_code, + /*variant */ OLD.variant, + /*bec_version_id */ OLD.bec_version_id, + /*elevation */ OLD.elevation, + /*latitude_degrees */ OLD.latitude_degrees, + /*latitude_minutes */ OLD.latitude_minutes, + /*latitude_seconds */ OLD.latitude_seconds, + /*longitude_degrees */ OLD.longitude_degrees, + /*longitude_minutes */ OLD.longitude_minutes, + /*longitude_seconds */ OLD.longitude_seconds, + /*collection_elevation */ OLD.collection_elevation, + /*collection_elevation_min */ OLD.collection_elevation_min, + /*collection_elevation_max */ OLD.collection_elevation_max, + /*collection_latitude_deg */ OLD.collection_latitude_deg, + /*collection_latitude_min */ OLD.collection_latitude_min, + /*collection_latitude_sec */ OLD.collection_latitude_sec, + /*collection_latitude_code */ OLD.collection_latitude_code, + /*collection_longitude_deg */ OLD.collection_longitude_deg, + /*collection_longitude_min */ OLD.collection_longitude_min, + /*collection_longitude_sec */ OLD.collection_longitude_sec, + /*collection_longitude_code */ OLD.collection_longitude_code, + /*elevation_min */ OLD.elevation_min, + /*elevation_max */ OLD.elevation_max, + /*latitude_deg_min */ OLD.latitude_deg_min, + /*latitude_min_min */ OLD.latitude_min_min, + /*latitude_sec_min */ OLD.latitude_sec_min, + /*latitude_deg_max */ OLD.latitude_deg_max, + /*latitude_min_max */ OLD.latitude_min_max, + /*latitude_sec_max */ OLD.latitude_sec_max, + /*longitude_deg_min */ OLD.longitude_deg_min, + /*longitude_min_min */ OLD.longitude_min_min, + /*longitude_sec_min */ OLD.longitude_sec_min, + /*longitude_deg_max */ OLD.longitude_deg_max, + /*longitude_min_max */ OLD.longitude_min_max, + /*longitude_sec_max */ OLD.longitude_sec_max, + /*smp_mean_bv_growth */ OLD.smp_mean_bv_growth, + /*area_of_use_comment */ OLD.area_of_use_comment, + /*approved_timestamp */ OLD.approved_timestamp, + /*approved_userid */ OLD.approved_userid, + /*mean_geom */ OLD.mean_geom, + /*update_userid */ OLD.update_userid, + /*update_timestamp */ OLD.update_timestamp, + /*revision_count */ OLD.revision_count + ); + RETURN OLD; + elsif (TG_OP = 'INSERT') then + v_new_data := ROW(NEW.*); + INSERT INTO spar.seedlot_audit (spar_audit_code,db_user,audit_revision_version,seedlot_number,seedlot_status_code,applicant_client_number,applicant_locn_code,applicant_email_address,vegetation_code,genetic_class_code,seedlot_source_code,to_be_registrd_ind,bc_source_ind,collection_client_number,collection_locn_code,collection_start_date,collection_end_date,no_of_containers,vol_per_container,clctn_volume,seedlot_comment,interm_strg_client_number,interm_strg_locn_code,interm_strg_st_date,interm_strg_end_date,interm_facility_code,female_gametic_mthd_code,male_gametic_mthd_code,controlled_cross_ind,biotech_processes_ind,pollen_contamination_ind,pollen_contamination_pct,contaminant_pollen_bv,pollen_contamination_mthd_code,total_parent_trees,smp_success_pct,effective_pop_size,smp_parents_outside,non_orchard_pollen_contam_pct,extractory_client_number,extractory_locn_code,extraction_st_date,extraction_end_date,temporary_strg_client_number,temporary_strg_locn_code,temporary_strg_start_date,temporary_strg_end_date,interm_strg_locn,declared_userid,declared_timestamp,entry_userid,entry_timestamp,seed_plan_unit_id,bgc_zone_code,bgc_subzone_code,variant,bec_version_id,elevation,latitude_degrees,latitude_minutes,latitude_seconds,longitude_degrees,longitude_minutes,longitude_seconds,collection_elevation,collection_elevation_min,collection_elevation_max,collection_latitude_deg,collection_latitude_min,collection_latitude_sec,collection_latitude_code,collection_longitude_deg,collection_longitude_min,collection_longitude_sec,collection_longitude_code,elevation_min,elevation_max,latitude_deg_min,latitude_min_min,latitude_sec_min,latitude_deg_max,latitude_min_max,latitude_sec_max,longitude_deg_min,longitude_min_min,longitude_sec_min,longitude_deg_max,longitude_min_max,longitude_sec_max,smp_mean_bv_growth,area_of_use_comment,approved_timestamp,approved_userid,mean_geom,update_userid,update_timestamp,revision_count) + VALUES( + /*spar_audit_code */ 'I', + /*db_user */ session_user::TEXT, + /*audit_revision_version */ 1, -- 1st row version + /*seedlot_number */ NEW.seedlot_number, + /*seedlot_status_code */ NEW.seedlot_status_code, + /*applicant_client_number */ NEW.applicant_client_number, + /*applicant_locn_code */ NEW.applicant_locn_code, + /*applicant_email_address */ NEW.applicant_email_address, + /*vegetation_code */ NEW.vegetation_code, + /*genetic_class_code */ NEW.genetic_class_code, + /*seedlot_source_code */ NEW.seedlot_source_code, + /*to_be_registrd_ind */ NEW.to_be_registrd_ind, + /*bc_source_ind */ NEW.bc_source_ind, + /*collection_client_number */ NEW.collection_client_number, + /*collection_locn_code */ NEW.collection_locn_code, + /*collection_start_date */ NEW.collection_start_date, + /*collection_end_date */ NEW.collection_end_date, + /*no_of_containers */ NEW.no_of_containers, + /*vol_per_container */ NEW.vol_per_container, + /*clctn_volume */ NEW.clctn_volume, + /*seedlot_comment */ NEW.seedlot_comment, + /*interm_strg_client_number */ NEW.interm_strg_client_number, + /*interm_strg_locn_code */ NEW.interm_strg_locn_code, + /*interm_strg_st_date */ NEW.interm_strg_st_date, + /*interm_strg_end_date */ NEW.interm_strg_end_date, + /*interm_facility_code */ NEW.interm_facility_code, + /*female_gametic_mthd_code */ NEW.female_gametic_mthd_code, + /*male_gametic_mthd_code */ NEW.male_gametic_mthd_code, + /*controlled_cross_ind */ NEW.controlled_cross_ind, + /*biotech_processes_ind */ NEW.biotech_processes_ind, + /*pollen_contamination_ind */ NEW.pollen_contamination_ind, + /*pollen_contamination_pct */ NEW.pollen_contamination_pct, + /*contaminant_pollen_bv */ NEW.contaminant_pollen_bv, + /*pollen_contamination_mthd_code */ NEW.pollen_contamination_mthd_code, + /*total_parent_trees */ NEW.total_parent_trees, + /*smp_success_pct */ NEW.smp_success_pct, + /*effective_pop_size */ NEW.effective_pop_size, + /*smp_parents_outside */ NEW.smp_parents_outside, + /*non_orchard_pollen_contam_pct */ NEW.non_orchard_pollen_contam_pct, + /*extractory_client_number */ NEW.extractory_client_number, + /*extractory_locn_code */ NEW.extractory_locn_code, + /*extraction_st_date */ NEW.extraction_st_date, + /*extraction_end_date */ NEW.extraction_end_date, + /*temporary_strg_client_number */ NEW.temporary_strg_client_number, + /*temporary_strg_locn_code */ NEW.temporary_strg_locn_code, + /*temporary_strg_start_date */ NEW.temporary_strg_start_date, + /*temporary_strg_end_date */ NEW.temporary_strg_end_date, + /*interm_strg_locn */ NEW.interm_strg_locn, + /*declared_userid */ NEW.declared_userid, + /*declared_timestamp */ NEW.declared_timestamp, + /*entry_userid */ NEW.entry_userid, + /*entry_timestamp */ NEW.entry_timestamp, + /*seed_plan_unit_id */ NEW.seed_plan_unit_id, + /*bgc_zone_code */ NEW.bgc_zone_code, + /*bgc_zone_description */ NEW.bgc_zone_description, + /*bgc_subzone_code */ NEW.bgc_subzone_code, + /*variant */ NEW.variant, + /*bec_version_id */ NEW.bec_version_id, + /*elevation */ NEW.elevation, + /*latitude_degrees */ NEW.latitude_degrees, + /*latitude_minutes */ NEW.latitude_minutes, + /*latitude_seconds */ NEW.latitude_seconds, + /*longitude_degrees */ NEW.longitude_degrees, + /*longitude_minutes */ NEW.longitude_minutes, + /*longitude_seconds */ NEW.longitude_seconds, + /*collection_elevation */ NEW.collection_elevation, + /*collection_elevation_min */ NEW.collection_elevation_min, + /*collection_elevation_max */ NEW.collection_elevation_max, + /*collection_latitude_deg */ NEW.collection_latitude_deg, + /*collection_latitude_min */ NEW.collection_latitude_min, + /*collection_latitude_sec */ NEW.collection_latitude_sec, + /*collection_latitude_code */ NEW.collection_latitude_code, + /*collection_longitude_deg */ NEW.collection_longitude_deg, + /*collection_longitude_min */ NEW.collection_longitude_min, + /*collection_longitude_sec */ NEW.collection_longitude_sec, + /*collection_longitude_code */ NEW.collection_longitude_code, + /*elevation_min */ NEW.elevation_min, + /*elevation_max */ NEW.elevation_max, + /*latitude_deg_min */ NEW.latitude_deg_min, + /*latitude_min_min */ NEW.latitude_min_min, + /*latitude_sec_min */ NEW.latitude_sec_min, + /*latitude_deg_max */ NEW.latitude_deg_max, + /*latitude_min_max */ NEW.latitude_min_max, + /*latitude_sec_max */ NEW.latitude_sec_max, + /*longitude_deg_min */ NEW.longitude_deg_min, + /*longitude_min_min */ NEW.longitude_min_min, + /*longitude_sec_min */ NEW.longitude_sec_min, + /*longitude_deg_max */ NEW.longitude_deg_max, + /*longitude_min_max */ NEW.longitude_min_max, + /*longitude_sec_max */ NEW.longitude_sec_max, + /*smp_mean_bv_growth */ NEW.smp_mean_bv_growth, + /*area_of_use_comment */ NEW.area_of_use_comment, + /*approved_timestamp */ NEW.approved_timestamp, + /*approved_userid */ NEW.approved_userid, + /*mean_geom */ NEW.mean_geom, + /*update_userid */ NEW.update_userid, + /*update_timestamp */ NEW.update_timestamp, + /*revision_count */ NEW.revision_count + ); + RETURN NEW; + else + RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - Other action occurred: %, at %',TG_OP,now(); + RETURN NULL; + end if; + +EXCEPTION + WHEN data_exception then + --insert into spar.error_catch (erro) VALUES(CONCAT('DATA EXCEPTION ',SQLERRM)); + RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM; + RETURN NULL; + WHEN unique_violation then + --insert into spar.error_catch (erro) VALUES(CONCAT('UNIQUE EXCEPTION ',SQLERRM)); + RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM; + RETURN NULL; + WHEN others then + --insert into spar.error_catch (erro) VALUES(CONCAT(v_auditrevision, CONCAT('OTHER EXCEPTION ',SQLERRM))); + RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM; + RETURN NULL; +END; +$body$ +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = pg_catalog, spar; + +-- Drop existing trigger +DROP TRIGGER trg_seedlot_audit_DIU ON spar.seedlot; + +-- Trigger to be attached on spar.seedlot table +CREATE TRIGGER trg_seedlot_audit_DIU + AFTER INSERT OR UPDATE OR DELETE ON spar.seedlot + FOR EACH ROW EXECUTE PROCEDURE spar.seedlot_if_modified_func(); diff --git a/backend/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java b/backend/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java index d076f0984..f778758af 100644 --- a/backend/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java +++ b/backend/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java @@ -98,8 +98,32 @@ void getParentTreeGeneticQualityDataNoSpuTest() throws Exception { void findOrchardsWithVegCodeTest() throws Exception { String vegCode = "PLI"; - OrchardDto firstOrchard = new OrchardDto("123", "smOrchard", vegCode, 'S', "Seed lot", "PRD"); - OrchardDto secondOrchard = new OrchardDto("456", "xlOrchard", vegCode, 'S', "Seed lot", "TEST"); + OrchardDto firstOrchard = + new OrchardDto( + "123", + "smOrchard", + vegCode, + 'S', + "Seed lot", + "PRD", + "ICH", + "Interior Cedar -- Hemlock", + "dw", + '4', + 5); + OrchardDto secondOrchard = + new OrchardDto( + "456", + "xlOrchard", + vegCode, + 'S', + "Seed lot", + "TEST", + "IDF", + "Interior Douglas-fir", + "mk", + '1', + 5); List testList = new ArrayList<>() { @@ -121,9 +145,19 @@ void findOrchardsWithVegCodeTest() throws Exception { .andExpect(jsonPath("$[0].id").value("123")) .andExpect(jsonPath("$[0].vegetationCode").value(vegCode)) .andExpect(jsonPath("$[0].name").value("smOrchard")) + .andExpect(jsonPath("$[0].becZoneCode").value("ICH")) + .andExpect(jsonPath("$[0].becZoneDescription").value("Interior Cedar -- Hemlock")) + .andExpect(jsonPath("$[0].becSubzoneCode").value("dw")) + .andExpect(jsonPath("$[0].variant").value("4")) + .andExpect(jsonPath("$[0].becVersionId").value(5)) .andExpect(jsonPath("$[1].id").value("456")) .andExpect(jsonPath("$[1].vegetationCode").value(vegCode)) .andExpect(jsonPath("$[1].name").value("xlOrchard")) + .andExpect(jsonPath("$[1].becZoneCode").value("IDF")) + .andExpect(jsonPath("$[1].becZoneDescription").value("Interior Douglas-fir")) + .andExpect(jsonPath("$[1].becSubzoneCode").value("mk")) + .andExpect(jsonPath("$[1].variant").value("1")) + .andExpect(jsonPath("$[1].becVersionId").value(5)) .andReturn(); } diff --git a/backend/src/test/java/ca/bc/gov/backendstartapi/provider/OracleApiProviderTest.java b/backend/src/test/java/ca/bc/gov/backendstartapi/provider/OracleApiProviderTest.java index 7c99a23a1..0193fbaf5 100644 --- a/backend/src/test/java/ca/bc/gov/backendstartapi/provider/OracleApiProviderTest.java +++ b/backend/src/test/java/ca/bc/gov/backendstartapi/provider/OracleApiProviderTest.java @@ -191,4 +191,55 @@ void findParentTreesByVegCodeErrorTest() throws Exception { Assertions.assertEquals(HttpStatus.BAD_REQUEST, httpExc.getStatusCode()); } + + @Test + @DisplayName("Find Orchard with ID success test.") + void findOrchardById_shouldSucceed() { + when(loggedUserService.getLoggedUserToken()).thenReturn("1f7a4k5e8t9o5k6e9n8h5e2r6e"); + + String orchardId = "339"; + String url = "/null/api/orchards/" + orchardId; + + String json = + """ + { + "id": "339", + "name": "EAGLEROCK", + "vegetationCode": "PLI", + "lotTypeCode": "S", + "lotTypeDescription": "Seed Lot", + "stageCode": "PRD", + "becZoneCode": "CWH", + "becZoneDescription": "Coastal Western Hemlock", + "becSubzoneCode": "dm", + "variant": null, + "becVersionId": 5 + } + """; + + mockRestServiceServer + .expect(requestTo(url)) + .andRespond(withSuccess(json, MediaType.APPLICATION_JSON)); + + Optional orchardDtoOpt = oracleApiProvider.findOrchardById(orchardId); + + Assertions.assertFalse(orchardDtoOpt.isEmpty()); + Assertions.assertEquals(orchardId, orchardDtoOpt.get().id()); + Assertions.assertEquals("Coastal Western Hemlock", orchardDtoOpt.get().becZoneDescription()); + } + + @Test + @DisplayName("Find orchard by id should return empty on error") + void findOrchardById_shouldReturnEmpty_onError() { + when(loggedUserService.getLoggedUserToken()).thenReturn(""); + + String orchardId = "339"; + String url = "/null/api/orchards/" + orchardId; + + mockRestServiceServer.expect(requestTo(url)).andRespond(withStatus(HttpStatus.BAD_REQUEST)); + + Optional orchardOpt = oracleApiProvider.findOrchardById(orchardId); + + Assertions.assertTrue(orchardOpt.isEmpty()); + } } diff --git a/backend/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java b/backend/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java index e071f6a22..4f9607936 100644 --- a/backend/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java +++ b/backend/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java @@ -158,8 +158,32 @@ void findParentTreeGeneticQualityDataEmptyServiceTest() { void findOrchardByVegCodeSuccessServiceTest() { String vegCode = "FDI"; - OrchardDto firstOrchard = new OrchardDto("123", "smOrchard", vegCode, 'S', "Seed lot", "PRD"); - OrchardDto secondOrchard = new OrchardDto("456", "xlOrchard", vegCode, 'S', "Seed lot", "TEST"); + OrchardDto firstOrchard = + new OrchardDto( + "123", + "smOrchard", + vegCode, + 'S', + "Seed lot", + "PRD", + "ICH", + "Interior Cedar -- Hemlock", + "dw", + '4', + 5); + OrchardDto secondOrchard = + new OrchardDto( + "456", + "xlOrchard", + vegCode, + 'S', + "Seed lot", + "TEST", + "IDF", + "Interior Douglas-fir", + "mk", + '1', + 5); List testList = new ArrayList<>() { diff --git a/backend/src/test/java/ca/bc/gov/backendstartapi/service/SeedlotFormPutTest.java b/backend/src/test/java/ca/bc/gov/backendstartapi/service/SeedlotFormPutTest.java index f18a7f373..dfc7be5c9 100644 --- a/backend/src/test/java/ca/bc/gov/backendstartapi/service/SeedlotFormPutTest.java +++ b/backend/src/test/java/ca/bc/gov/backendstartapi/service/SeedlotFormPutTest.java @@ -9,6 +9,7 @@ import ca.bc.gov.backendstartapi.dto.CaculatedParentTreeValsDto; import ca.bc.gov.backendstartapi.dto.GeospatialRespondDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticQualityDto; import ca.bc.gov.backendstartapi.dto.PtCalculationResDto; import ca.bc.gov.backendstartapi.dto.SeedlotFormCollectionDto; @@ -427,16 +428,10 @@ void submitSeedlotForm_happyPath_shouldSucceed() { // Set area of use mocks int activeSpuId = 3; + String primaryOrchardId = mockedForm.seedlotFormOrchardDto().primaryOrchardId(); Optional activeSpuOptional = - Optional.of( - new ActiveOrchardSpuEntity( - mockedForm.seedlotFormOrchardDto().primaryOrchardId(), - activeSpuId, - true, - false, - false)); - when(orchardService.findSpuIdByOrchardWithActive( - mockedForm.seedlotFormOrchardDto().primaryOrchardId(), true)) + Optional.of(new ActiveOrchardSpuEntity(primaryOrchardId, activeSpuId, true, false, false)); + when(orchardService.findSpuIdByOrchardWithActive(primaryOrchardId, true)) .thenReturn(activeSpuOptional); AreaOfUseDto areaOfUseDto = new AreaOfUseDto(); @@ -448,6 +443,22 @@ void submitSeedlotForm_happyPath_shouldSucceed() { List spzList = List.of(spzDto1, spzDto2); areaOfUseDto.setSpzList(spzList); + OrchardDto oracleOrchardRet = + new OrchardDto( + primaryOrchardId, + "Primary Orchard", + seedlot.getVegetationCode(), + 'S', + "Seed Lot", + "PRD", + "SBS", + "Sub-Boreal Spruce", + "mk", + '1', + 5); + when(oracleApiProvider.findOrchardById(primaryOrchardId)) + .thenReturn(Optional.of(oracleOrchardRet)); + when(oracleApiProvider.getAreaOfUseData(activeSpuId)).thenReturn(Optional.of(areaOfUseDto)); Optional genClassOptional = Optional.of(new GeneticClassEntity()); @@ -517,5 +528,11 @@ void submitSeedlotForm_happyPath_shouldSucceed() { assertEquals(geospatialRespondDto.getMeanLongitudeMinute(), seedlot.getLongitudeMinMin()); assertEquals(0, seedlot.getLongitudeSecMax()); assertEquals(0, seedlot.getLongitudeSecMin()); + // BEC values + assertEquals(oracleOrchardRet.becZoneCode(), seedlot.getBgcZoneCode()); + assertEquals(oracleOrchardRet.becZoneDescription(), seedlot.getBgcZoneDescription()); + assertEquals(oracleOrchardRet.becSubzoneCode(), seedlot.getBgcSubzoneCode()); + assertEquals(oracleOrchardRet.variant(), seedlot.getVariant()); + assertEquals(oracleOrchardRet.becVersionId(), seedlot.getBecVersionId()); } } diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardLotTypeDescriptionDto.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java similarity index 75% rename from oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardLotTypeDescriptionDto.java rename to oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java index 43302780c..ebcd96ca0 100644 --- a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardLotTypeDescriptionDto.java +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/dto/OrchardDto.java @@ -7,7 +7,7 @@ * {@link ca.bc.gov.backendstartapi.entity.OrchardLotTypeCode}. */ @Schema(description = "Represents an Orchard object with an Orchard Lot Type.") -public record OrchardLotTypeDescriptionDto( +public record OrchardDto( @Schema( description = """ @@ -41,4 +41,10 @@ public record OrchardLotTypeDescriptionDto( @Schema( description = "A code which represents the current stage or status of an orchard.", example = "PRD") - String stageCode) {} + String stageCode, + @Schema(description = "The bgc zone code", example = "SBS") String becZoneCode, + @Schema(description = "The description of a bgc zone code", example = "Sub-Boreal Spruce") + String becZoneDescription, + @Schema(description = "The bgc sub-zone code", example = "wk") String becSubzoneCode, + @Schema(description = "The variant.", example = "1") Character variant, + @Schema(description = "The bec version id.", example = "5") Integer becVersionId) {} diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpoint.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpoint.java index 59e1dee35..a6dde226c 100644 --- a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpoint.java +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpoint.java @@ -2,11 +2,10 @@ import ca.bc.gov.backendstartapi.config.SparLog; import ca.bc.gov.backendstartapi.dto.AreaOfUseDto; -import ca.bc.gov.backendstartapi.dto.OrchardLotTypeDescriptionDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.OrchardParentTreeDto; import ca.bc.gov.backendstartapi.dto.ParentTreeDto; import ca.bc.gov.backendstartapi.dto.SameSpeciesTreeDto; -import ca.bc.gov.backendstartapi.entity.Orchard; import ca.bc.gov.backendstartapi.security.RoleAccessConfig; import ca.bc.gov.backendstartapi.service.OrchardService; import io.swagger.v3.oas.annotations.Operation; @@ -65,12 +64,11 @@ public class OrchardEndpoint { @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) }) @RoleAccessConfig({"SPAR_TSC_ADMIN", "SPAR_MINISTRY_ORCHARD", "SPAR_NONMINISTRY_ORCHARD"}) - public OrchardLotTypeDescriptionDto getOrchardById( + public OrchardDto getOrchardById( @PathVariable @Parameter(name = "id", in = ParameterIn.PATH, description = "Identifier of the orchard.") String id) { - Optional orchardLotType = - orchardService.findNotRetiredOrchardValidLotType(id); + Optional orchardLotType = orchardService.findNotRetiredOrchardValidLotType(id); return orchardLotType.orElseThrow( () -> @@ -130,7 +128,7 @@ public OrchardParentTreeDto getParentTreeGeneticQualityData( * Consumed by backend (postgres) service to retrieve a list of orchards with a vegCode. * * @param vegCode an {@link Orchard}'s vegCode - * @return an {@link List} of {@link OrchardLotTypeDescriptionDto} + * @return an {@link List} of {@link OrchardDto} * @throws ResponseStatusException if error occurs */ @GetMapping(path = "/vegetation-code/{vegCode}", produces = MediaType.APPLICATION_JSON_VALUE) @@ -148,7 +146,7 @@ public OrchardParentTreeDto getParentTreeGeneticQualityData( @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) }) @RoleAccessConfig({"SPAR_TSC_ADMIN", "SPAR_MINISTRY_ORCHARD", "SPAR_NONMINISTRY_ORCHARD"}) - public List getOrchardsByVegCode( + public List getOrchardsByVegCode( @PathVariable("vegCode") @Parameter(description = "The vegetation code of an orchard.") String vegCode) { SparLog.info("Received GET request for orchards with vegCode: " + vegCode); diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/BecZoneCodeEntity.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/BecZoneCodeEntity.java new file mode 100644 index 000000000..d160bf85c --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/BecZoneCodeEntity.java @@ -0,0 +1,40 @@ +package ca.bc.gov.backendstartapi.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 java.time.LocalDate; +import lombok.Getter; +import lombok.Setter; + +/** Represents a BEC Zone Code object in the database. */ +@Getter +@Setter +@Entity +@Table(name = "BEC_ZONE_CODE", schema = "THE") +@Schema(description = "Represents a BEC Zone Code object in the database.") +public class BecZoneCodeEntity { + + @Id + @Column(name = "BEC_ZONE_CODE") + @Schema(description = "BEC zone code", example = "BG") + private String code; + + @Column(name = "DESCRIPTION") + @Schema(description = "BEC zone code's description", example = "Bunchgrass") + private String description; + + @Column(name = "EFFECTIVE_DATE") + @Schema(description = "BEC zone code's effective date.", type = "string", format = "date") + private LocalDate effectiveDate; + + @Column(name = "EXPIRY_DATE") + @Schema(description = "BEC zone code's expiry date.", type = "string", format = "date") + private LocalDate expiryDate; + + @Column(name = "UPDATE_TIMESTAMP") + @Schema(description = "BEC zone code's update timestamp.", type = "string", format = "date") + private LocalDate updateTimeStamp; +} diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/Orchard.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/OrchardEntity.java similarity index 75% rename from oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/Orchard.java rename to oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/OrchardEntity.java index 863665b4e..e9796819e 100644 --- a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/Orchard.java +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/entity/OrchardEntity.java @@ -17,7 +17,7 @@ @Setter @Entity @Table(name = "ORCHARD") -public class Orchard { +public class OrchardEntity { @Id @Column(name = "ORCHARD_ID", length = 3) @@ -35,4 +35,16 @@ public class Orchard { @Column(name = "ORCHARD_STAGE_CODE", length = 3) private String stageCode; + + @Column(name = "BEC_ZONE", length = 4) + private String becZoneCode; + + @Column(name = "BEC_SUBZONE", length = 3) + private String becSubzoneCode; + + @Column(name = "VARIANT", length = 1) + private Character variant; + + @Column(name = "BEC_VERSION_ID") + private Integer becVersionId; } diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/BecZoneCodeRepository.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/BecZoneCodeRepository.java new file mode 100644 index 000000000..ad4c5a9a8 --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/BecZoneCodeRepository.java @@ -0,0 +1,7 @@ +package ca.bc.gov.backendstartapi.repository; + +import ca.bc.gov.backendstartapi.entity.BecZoneCodeEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +/** This interface enables the BEC Zone Code entity to be retrieved from the database. */ +public interface BecZoneCodeRepository extends JpaRepository {} diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/OrchardRepository.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/OrchardRepository.java index 69482ecd3..b6c926dfc 100644 --- a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/OrchardRepository.java +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/repository/OrchardRepository.java @@ -1,17 +1,17 @@ package ca.bc.gov.backendstartapi.repository; -import ca.bc.gov.backendstartapi.entity.Orchard; +import ca.bc.gov.backendstartapi.entity.OrchardEntity; import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; /** This repository class contains methods to retrieve Orchards from the database. */ -public interface OrchardRepository extends JpaRepository { +public interface OrchardRepository extends JpaRepository { - @Query("from Orchard o where o.stageCode <> 'RET' and o.id = ?1") - Optional findNotRetiredById(String id); + @Query("from OrchardEntity o where o.stageCode <> 'RET' and o.id = ?1") + Optional findNotRetiredById(String id); // Find all orchards that are not retired with a given vegCode - List findAllByVegetationCodeAndStageCodeNot(String vegCode, String stageCode); + List findAllByVegetationCodeAndStageCodeNot(String vegCode, String stageCode); } diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/BecZoneCodeService.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/BecZoneCodeService.java new file mode 100644 index 000000000..9a1f1ef71 --- /dev/null +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/BecZoneCodeService.java @@ -0,0 +1,42 @@ +package ca.bc.gov.backendstartapi.service; + +import ca.bc.gov.backendstartapi.config.SparLog; +import ca.bc.gov.backendstartapi.entity.BecZoneCodeEntity; +import ca.bc.gov.backendstartapi.repository.BecZoneCodeRepository; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** The class for BEC Zone Code Service. */ +@Service +@RequiredArgsConstructor +public class BecZoneCodeService { + + private final BecZoneCodeRepository becZoneCodeRepository; + + /** + * Get the description of a BEC Zone by a code, returns null if not found or code provided is + * null. + */ + public String getBecDescriptionByCode(String becZoneCode) { + SparLog.info("Begin service request to find the description of a given BEC zone code"); + + if (becZoneCode == null) { + SparLog.info("BEC Zone code param is null, returning null value for BEC zone description"); + return null; + } + + Optional optionalBecEntitiy = becZoneCodeRepository.findById(becZoneCode); + + if (optionalBecEntitiy.isEmpty()) { + SparLog.info( + "Cannot find a BEC zone code entity, returning null value for BEC zone description"); + return null; + } + + String description = optionalBecEntitiy.get().getDescription(); + SparLog.info( + "BEC zone code entity found, returning the description with value: {}", description); + return description; + } +} diff --git a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/OrchardService.java b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/OrchardService.java index cae14ff89..b6039272f 100644 --- a/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/OrchardService.java +++ b/oracle-api/src/main/java/ca/bc/gov/backendstartapi/service/OrchardService.java @@ -3,13 +3,13 @@ import ca.bc.gov.backendstartapi.config.SparLog; import ca.bc.gov.backendstartapi.dto.AreaOfUseDto; import ca.bc.gov.backendstartapi.dto.AreaOfUseSpuGeoDto; -import ca.bc.gov.backendstartapi.dto.OrchardLotTypeDescriptionDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.OrchardParentTreeDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticInfoDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticQualityDto; import ca.bc.gov.backendstartapi.dto.SameSpeciesTreeDto; import ca.bc.gov.backendstartapi.dto.SpzDto; -import ca.bc.gov.backendstartapi.entity.Orchard; +import ca.bc.gov.backendstartapi.entity.OrchardEntity; import ca.bc.gov.backendstartapi.entity.OrchardLotTypeCode; import ca.bc.gov.backendstartapi.entity.ParentTreeEntity; import ca.bc.gov.backendstartapi.entity.ParentTreeGeneticQuality; @@ -26,7 +26,6 @@ import ca.bc.gov.backendstartapi.repository.ParentTreeOrchardRepository; import ca.bc.gov.backendstartapi.repository.ParentTreeRepository; import ca.bc.gov.backendstartapi.repository.SeedPlanUnitRepository; -import ca.bc.gov.backendstartapi.repository.SeedPlanZoneRepository; import ca.bc.gov.backendstartapi.repository.TestedPtAreaOfUseSpuRepository; import ca.bc.gov.backendstartapi.repository.TestedPtAreaOfUseSpzRepository; import ca.bc.gov.backendstartapi.repository.TestedPtAreaofUseRepository; @@ -38,76 +37,67 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; /** This class contains methods to handle orchards. */ @Service +@RequiredArgsConstructor public class OrchardService { - private OrchardRepository orchardRepository; + private final OrchardRepository orchardRepository; - private ParentTreeOrchardRepository parentTreeOrchardRepository; + private final ParentTreeOrchardRepository parentTreeOrchardRepository; - private ParentTreeRepository parentTreeRepository; + private final ParentTreeRepository parentTreeRepository; - private ParentTreeGeneticQualityRepository parentTreeGeneticQualityRepository; + private final ParentTreeGeneticQualityRepository parentTreeGeneticQualityRepository; - private TestedPtAreaofUseRepository testedPtAreaofUseRepository; + private final TestedPtAreaofUseRepository testedPtAreaofUseRepository; - private TestedPtAreaOfUseSpzRepository testedPtAreaOfUseSpzRepository; + private final TestedPtAreaOfUseSpzRepository testedPtAreaOfUseSpzRepository; - private SeedPlanUnitRepository seedPlanUnitRepository; + private final SeedPlanUnitRepository seedPlanUnitRepository; - private TestedPtAreaOfUseSpuRepository testedPtAreaOfUseSpuRepository; + private final TestedPtAreaOfUseSpuRepository testedPtAreaOfUseSpuRepository; - OrchardService( - OrchardRepository orchardRepository, - ParentTreeOrchardRepository parentTreeOrchardRepository, - ParentTreeRepository parentTreeRepository, - ParentTreeGeneticQualityRepository parentTreeGeneticQualityRepository, - TestedPtAreaofUseRepository testedPtAreaofUseRepository, - TestedPtAreaOfUseSpzRepository testedPtAreaOfUseSpzRepository, - SeedPlanUnitRepository seedPlanUnitRepository, - TestedPtAreaOfUseSpuRepository testedPtAreaOfUseSpuRepository, - SeedPlanZoneRepository seedPlanZoneRepository) { - this.orchardRepository = orchardRepository; - this.parentTreeOrchardRepository = parentTreeOrchardRepository; - this.parentTreeRepository = parentTreeRepository; - this.parentTreeGeneticQualityRepository = parentTreeGeneticQualityRepository; - this.testedPtAreaofUseRepository = testedPtAreaofUseRepository; - this.testedPtAreaOfUseSpzRepository = testedPtAreaOfUseSpzRepository; - this.seedPlanUnitRepository = seedPlanUnitRepository; - this.testedPtAreaOfUseSpuRepository = testedPtAreaOfUseSpuRepository; - } + private final BecZoneCodeService becZoneCodeService; /** * Find a not retired {@link Orchard} with a valid {@link OrchardLotTypeCode} by Orchard's ID. * * @param id The Orchard's identification - * @return Optional of {@link OrchardLotTypeDescriptionDto} + * @return Optional of {@link OrchardDto} */ - public Optional findNotRetiredOrchardValidLotType(String id) { + public Optional findNotRetiredOrchardValidLotType(String id) { SparLog.info("Finding valid not retired Orchard by id: {}", id); - Optional orchard = orchardRepository.findNotRetiredById(id); + Optional orchard = orchardRepository.findNotRetiredById(id); if (orchard.isPresent()) { - OrchardLotTypeCode orchardLotTypeCode = orchard.get().getOrchardLotTypeCode(); + OrchardEntity orchardEntity = orchard.get(); + + OrchardLotTypeCode orchardLotTypeCode = orchardEntity.getOrchardLotTypeCode(); if (Objects.isNull(orchardLotTypeCode) || !orchardLotTypeCode.isValid()) { SparLog.warn("Orchard lot type is not valid!"); return Optional.empty(); } - OrchardLotTypeDescriptionDto descriptionDto = - new OrchardLotTypeDescriptionDto( - orchard.get().getId(), - orchard.get().getName(), - orchard.get().getVegetationCode(), + OrchardDto orchardDto = + new OrchardDto( + orchardEntity.getId(), + orchardEntity.getName(), + orchardEntity.getVegetationCode(), orchardLotTypeCode.getCode(), orchardLotTypeCode.getDescription(), - orchard.get().getStageCode()); + orchardEntity.getStageCode(), + orchardEntity.getBecZoneCode(), + becZoneCodeService.getBecDescriptionByCode(orchardEntity.getBecZoneCode()), + orchardEntity.getBecSubzoneCode(), + orchardEntity.getVariant(), + orchardEntity.getBecVersionId()); SparLog.info("Valid not retired Orchard found for id: {}", id); - return Optional.of(descriptionDto); + return Optional.of(orchardDto); } SparLog.info("Valid not retired Orchard not found for id: {}", id); @@ -129,7 +119,7 @@ public Optional findParentTreeGeneticQualityData( spuId); long starting = Instant.now().toEpochMilli(); - Optional orchard = orchardRepository.findById(orchardId); + Optional orchard = orchardRepository.findById(orchardId); long endingOne = Instant.now().toEpochMilli(); SparLog.debug("Time elapsed querying orchard by id: {}", endingOne - starting); @@ -164,26 +154,31 @@ public Optional findParentTreeGeneticQualityData( * @param vegCode {@link VegetationCode} identification * @return {@link Optional} of a {@link List} of {@link OrchardParentTreeDto} */ - public Optional> findNotRetOrchardsByVegCode(String vegCode) { + public Optional> findNotRetOrchardsByVegCode(String vegCode) { SparLog.info("Finding not retired Orchard by VegCode: {}", vegCode); - List resultList = new ArrayList<>(); + List resultList = new ArrayList<>(); - List orchardList = + List orchardList = orchardRepository.findAllByVegetationCodeAndStageCodeNot(vegCode.toUpperCase(), "RET"); orchardList.forEach( orchard -> { OrchardLotTypeCode orchardLotTypeCode = orchard.getOrchardLotTypeCode(); if (orchardLotTypeCode.isValid()) { - OrchardLotTypeDescriptionDto objToAdd = - new OrchardLotTypeDescriptionDto( + OrchardDto objToAdd = + new OrchardDto( orchard.getId(), orchard.getName(), orchard.getVegetationCode(), orchardLotTypeCode.getCode(), orchardLotTypeCode.getDescription(), - orchard.getStageCode()); + orchard.getStageCode(), + orchard.getBecZoneCode(), + becZoneCodeService.getBecDescriptionByCode(orchard.getBecZoneCode()), + orchard.getBecSubzoneCode(), + orchard.getVariant(), + orchard.getBecVersionId()); resultList.add(objToAdd); } }); diff --git a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java index 76fc9eca6..2a45278ff 100644 --- a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java +++ b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/endpoint/OrchardEndpointTest.java @@ -10,7 +10,7 @@ import ca.bc.gov.backendstartapi.dto.AreaOfUseDto; import ca.bc.gov.backendstartapi.dto.AreaOfUseSpuGeoDto; -import ca.bc.gov.backendstartapi.dto.OrchardLotTypeDescriptionDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.OrchardParentTreeDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticInfoDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticQualityDto; @@ -45,8 +45,19 @@ class OrchardEndpointTest { @Test @DisplayName("findByIdPrdSuccessTest") void findByIdPrdSuccessTest() throws Exception { - OrchardLotTypeDescriptionDto descriptionDto = - new OrchardLotTypeDescriptionDto("337", "GRANDVIEW", "PLI", 'S', "Seed Lot", "PRD"); + OrchardDto descriptionDto = + new OrchardDto( + "337", + "GRANDVIEW", + "PLI", + 'S', + "Seed Lot", + "PRD", + "ICH", + "Interior Cedar -- Hemlock", + "dw", + '4', + 5); when(orchardService.findNotRetiredOrchardValidLotType(any())) .thenReturn(Optional.of(descriptionDto)); @@ -64,6 +75,11 @@ void findByIdPrdSuccessTest() throws Exception { .andExpect(jsonPath("$.lotTypeCode").value("S")) .andExpect(jsonPath("$.lotTypeDescription").value("Seed Lot")) .andExpect(jsonPath("$.stageCode").value("PRD")) + .andExpect(jsonPath("$.becZoneCode").value("ICH")) + .andExpect(jsonPath("$.becZoneDescription").value("Interior Cedar -- Hemlock")) + .andExpect(jsonPath("$.becSubzoneCode").value("dw")) + .andExpect(jsonPath("$.variant").value("4")) + .andExpect(jsonPath("$.becVersionId").value(5)) .andReturn(); } @@ -171,12 +187,34 @@ void findParentTreeGeneticQualityNotFoundTest() throws Exception { void findOrchardsWithVegCodeSuccessEndpointTest() throws Exception { String vegCode = "PLI"; - OrchardLotTypeDescriptionDto firstOrchard = - new OrchardLotTypeDescriptionDto("123", "smOrchard", vegCode, 'S', "Seed lot", "PRD"); - OrchardLotTypeDescriptionDto secondOrchard = - new OrchardLotTypeDescriptionDto("456", "xlOrchard", vegCode, 'S', "Seed lot", "TEST"); - - List testList = + OrchardDto firstOrchard = + new OrchardDto( + "123", + "smOrchard", + vegCode, + 'S', + "Seed lot", + "PRD", + "ICH", + "Interior Cedar -- Hemlock", + "dw", + '4', + 5); + OrchardDto secondOrchard = + new OrchardDto( + "456", + "xlOrchard", + vegCode, + 'S', + "Seed lot", + "TEST", + "IDF", + "Interior Douglas-fir", + "mk", + '1', + 5); + + List testList = new ArrayList<>() { { add(firstOrchard); @@ -196,9 +234,19 @@ void findOrchardsWithVegCodeSuccessEndpointTest() throws Exception { .andExpect(jsonPath("$[0].id").value("123")) .andExpect(jsonPath("$[0].vegetationCode").value(vegCode)) .andExpect(jsonPath("$[0].name").value("smOrchard")) + .andExpect(jsonPath("$[0].becZoneCode").value("ICH")) + .andExpect(jsonPath("$[0].becZoneDescription").value("Interior Cedar -- Hemlock")) + .andExpect(jsonPath("$[0].becSubzoneCode").value("dw")) + .andExpect(jsonPath("$[0].variant").value("4")) + .andExpect(jsonPath("$[0].becVersionId").value(5)) .andExpect(jsonPath("$[1].id").value("456")) .andExpect(jsonPath("$[1].vegetationCode").value(vegCode)) .andExpect(jsonPath("$[1].name").value("xlOrchard")) + .andExpect(jsonPath("$[1].becZoneCode").value("IDF")) + .andExpect(jsonPath("$[1].becZoneDescription").value("Interior Douglas-fir")) + .andExpect(jsonPath("$[1].becSubzoneCode").value("mk")) + .andExpect(jsonPath("$[1].variant").value("1")) + .andExpect(jsonPath("$[1].becVersionId").value(5)) .andReturn(); } diff --git a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/repository/OrchardRepositoryTest.java b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/repository/OrchardRepositoryTest.java index a95f3d946..15de4cc31 100644 --- a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/repository/OrchardRepositoryTest.java +++ b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/repository/OrchardRepositoryTest.java @@ -1,6 +1,6 @@ package ca.bc.gov.backendstartapi.repository; -import ca.bc.gov.backendstartapi.entity.Orchard; +import ca.bc.gov.backendstartapi.entity.OrchardEntity; import ca.bc.gov.backendstartapi.entity.OrchardLotTypeCode; import java.util.List; import java.util.Optional; @@ -23,10 +23,10 @@ class OrchardRepositoryTest { @Test @DisplayName("findByIdSuccessTest") void findByIdSuccessTest() { - Optional orchardPrd = orchardRepository.findNotRetiredById("337"); + Optional orchardPrd = orchardRepository.findNotRetiredById("337"); Assertions.assertTrue(orchardPrd.isPresent()); - Orchard orchardOne = orchardPrd.get(); + OrchardEntity orchardOne = orchardPrd.get(); OrchardLotTypeCode orchardLotTypeCodeOne = orchardOne.getOrchardLotTypeCode(); Assertions.assertNotNull(orchardLotTypeCodeOne); @@ -36,10 +36,10 @@ void findByIdSuccessTest() { Assertions.assertEquals("Seed Lot", orchardLotTypeCodeOne.getDescription()); Assertions.assertEquals("PRD", orchardOne.getStageCode()); - Optional orchardEsb = orchardRepository.findNotRetiredById("820"); + Optional orchardEsb = orchardRepository.findNotRetiredById("820"); Assertions.assertTrue(orchardEsb.isPresent()); - Orchard orchardTwo = orchardEsb.get(); + OrchardEntity orchardTwo = orchardEsb.get(); OrchardLotTypeCode orchardLotTypeCodeTwo = orchardTwo.getOrchardLotTypeCode(); Assertions.assertNotNull(orchardLotTypeCodeTwo); @@ -53,7 +53,7 @@ void findByIdSuccessTest() { @Test @DisplayName("findByIdNotFoundTest") void findByIdNotFoundTest() { - Optional orchardRet = orchardRepository.findNotRetiredById("612"); + Optional orchardRet = orchardRepository.findNotRetiredById("612"); Assertions.assertTrue(orchardRet.isEmpty()); } @@ -63,7 +63,7 @@ void findByIdNotFoundTest() { void findOrchardByVegCodeRepoSuccessTest() { String vegCode = "PLI"; String stageCode = "RET"; - List orchardRet = + List orchardRet = orchardRepository.findAllByVegetationCodeAndStageCodeNot(vegCode, stageCode); Assertions.assertFalse(orchardRet.isEmpty()); @@ -77,7 +77,7 @@ void findOrchardByVegCodeRepoSuccessTest() { @Test @DisplayName("findOrchardByVegCodeRepoErrorTest") void findOrchardByVegCodeRepoErrorTest() { - List orchardRet = + List orchardRet = orchardRepository.findAllByVegetationCodeAndStageCodeNot("SX", "RET"); Assertions.assertTrue(orchardRet.isEmpty()); diff --git a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/BecZoneCodeServiceTest.java b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/BecZoneCodeServiceTest.java new file mode 100644 index 000000000..b2fcf1eb8 --- /dev/null +++ b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/BecZoneCodeServiceTest.java @@ -0,0 +1,54 @@ +package ca.bc.gov.backendstartapi.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import ca.bc.gov.backendstartapi.entity.BecZoneCodeEntity; +import ca.bc.gov.backendstartapi.repository.BecZoneCodeRepository; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; + +/** The test class for BEC zone code Service. */ +@ExtendWith(MockitoExtension.class) +public class BecZoneCodeServiceTest { + + @Mock BecZoneCodeRepository becZoneCodeRepository; + + @Autowired @InjectMocks private BecZoneCodeService becZoneCodeService; + + @Test + @DisplayName("Get a description of a BEC zone, success") + void getBecZoneDescription_shouldSucceed() { + String becZoneCode = "ICH"; + String becZoneDescription = "Interior Cedar -- Hemlock"; + BecZoneCodeEntity becZone = new BecZoneCodeEntity(); + becZone.setCode(becZoneCode); + becZone.setDescription(becZoneDescription); + + when(becZoneCodeRepository.findById(becZoneCode)).thenReturn(Optional.of(becZone)); + + String retVal = becZoneCodeService.getBecDescriptionByCode(becZoneCode); + + assertEquals(becZoneDescription, retVal); + } + + @Test + @DisplayName("Get a description of a null BEC zone code should return null") + void getDescriptionWithNull() { + assertEquals(null, becZoneCodeService.getBecDescriptionByCode(null)); + } + + @Test + @DisplayName("Get a description of a BEC zone should return null if entity not found") + void getDescriptionReturnNull__ifNotFound() { + when(becZoneCodeRepository.findById(any())).thenReturn(Optional.empty()); + assertEquals(null, becZoneCodeService.getBecDescriptionByCode("ICH")); + } +} diff --git a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java index 0f5813235..76afd32ef 100644 --- a/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java +++ b/oracle-api/src/test/java/ca/bc/gov/backendstartapi/service/OrchardServiceTest.java @@ -7,13 +7,13 @@ import ca.bc.gov.backendstartapi.dto.AreaOfUseDto; import ca.bc.gov.backendstartapi.dto.AreaOfUseSpuGeoDto; -import ca.bc.gov.backendstartapi.dto.OrchardLotTypeDescriptionDto; +import ca.bc.gov.backendstartapi.dto.OrchardDto; import ca.bc.gov.backendstartapi.dto.OrchardParentTreeDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticInfoDto; import ca.bc.gov.backendstartapi.dto.ParentTreeGeneticQualityDto; import ca.bc.gov.backendstartapi.dto.SameSpeciesTreeDto; import ca.bc.gov.backendstartapi.dto.SpzDto; -import ca.bc.gov.backendstartapi.entity.Orchard; +import ca.bc.gov.backendstartapi.entity.OrchardEntity; import ca.bc.gov.backendstartapi.entity.OrchardLotTypeCode; import ca.bc.gov.backendstartapi.entity.ParentTreeEntity; import ca.bc.gov.backendstartapi.entity.ParentTreeGeneticQuality; @@ -73,16 +73,22 @@ class OrchardServiceTest { @Mock private TestedPtAreaOfUseSpzRepository testedPtAreaOfUseSpzRepository; + @Mock BecZoneCodeService becZoneCodeService; + @Autowired @InjectMocks private OrchardService orchardService; @Test @DisplayName("findNotRetiredOrchardValidLotTypeTest_Prd") void findNotRetiredOrchardValidLotTypeTest_Prd() { - Orchard orchard = new Orchard(); + OrchardEntity orchard = new OrchardEntity(); orchard.setId("337"); orchard.setName("GRANDVIEW"); orchard.setVegetationCode("PLI"); orchard.setStageCode("PRD"); + orchard.setBecZoneCode("ICH"); + orchard.setBecSubzoneCode("dw"); + orchard.setVariant('4'); + orchard.setBecVersionId(5); LocalDate now = LocalDate.now(); @@ -96,8 +102,10 @@ void findNotRetiredOrchardValidLotTypeTest_Prd() { when(orchardRepository.findNotRetiredById(any())).thenReturn(Optional.of(orchard)); - Optional descriptionDto = - orchardService.findNotRetiredOrchardValidLotType("337"); + when(becZoneCodeService.getBecDescriptionByCode(orchard.getBecZoneCode())) + .thenReturn("Interior Cedar -- Hemlock"); + + Optional descriptionDto = orchardService.findNotRetiredOrchardValidLotType("337"); Assertions.assertTrue(descriptionDto.isPresent()); Assertions.assertEquals("337", descriptionDto.get().id()); @@ -106,16 +114,25 @@ void findNotRetiredOrchardValidLotTypeTest_Prd() { Assertions.assertEquals("PRD", descriptionDto.get().stageCode()); Assertions.assertEquals('S', descriptionDto.get().lotTypeCode()); Assertions.assertEquals("Seed Lot", descriptionDto.get().lotTypeDescription()); + Assertions.assertEquals(orchard.getBecZoneCode(), descriptionDto.get().becZoneCode()); + Assertions.assertEquals(orchard.getBecSubzoneCode(), descriptionDto.get().becSubzoneCode()); + Assertions.assertEquals(orchard.getVariant(), descriptionDto.get().variant()); + Assertions.assertEquals(orchard.getBecVersionId(), descriptionDto.get().becVersionId()); + Assertions.assertEquals("Interior Cedar -- Hemlock", descriptionDto.get().becZoneDescription()); } @Test @DisplayName("findNotRetiredOrchardValidLotTypeTest_Esb") void findNotRetiredOrchardValidLotTypeTest_Esb() { - Orchard orchard = new Orchard(); + OrchardEntity orchard = new OrchardEntity(); orchard.setId("820"); orchard.setName("FERNDALE INSTITUTE"); orchard.setVegetationCode("AX"); orchard.setStageCode("ESB"); + orchard.setBecZoneCode("ICH"); + orchard.setBecSubzoneCode("dw"); + orchard.setVariant('4'); + orchard.setBecVersionId(5); LocalDate now = LocalDate.now(); @@ -128,9 +145,10 @@ void findNotRetiredOrchardValidLotTypeTest_Esb() { orchard.setOrchardLotTypeCode(lotTypeCode); when(orchardRepository.findNotRetiredById(any())).thenReturn(Optional.of(orchard)); + when(becZoneCodeService.getBecDescriptionByCode(orchard.getBecZoneCode())) + .thenReturn("Interior Cedar -- Hemlock"); - Optional descriptionDto = - orchardService.findNotRetiredOrchardValidLotType("820"); + Optional descriptionDto = orchardService.findNotRetiredOrchardValidLotType("820"); Assertions.assertTrue(descriptionDto.isPresent()); Assertions.assertEquals("820", descriptionDto.get().id()); @@ -139,12 +157,17 @@ void findNotRetiredOrchardValidLotTypeTest_Esb() { Assertions.assertEquals("ESB", descriptionDto.get().stageCode()); Assertions.assertEquals('C', descriptionDto.get().lotTypeCode()); Assertions.assertEquals("Cutting Lot", descriptionDto.get().lotTypeDescription()); + Assertions.assertEquals(orchard.getBecZoneCode(), descriptionDto.get().becZoneCode()); + Assertions.assertEquals(orchard.getBecSubzoneCode(), descriptionDto.get().becSubzoneCode()); + Assertions.assertEquals(orchard.getVariant(), descriptionDto.get().variant()); + Assertions.assertEquals(orchard.getBecVersionId(), descriptionDto.get().becVersionId()); + Assertions.assertEquals("Interior Cedar -- Hemlock", descriptionDto.get().becZoneDescription()); } @Test @DisplayName("findNotRetiredOrchardValidLotTypeTest_Ret") void findNotRetiredOrchardValidLotTypeTest_Ret() { - Orchard orchard = new Orchard(); + OrchardEntity orchard = new OrchardEntity(); orchard.setId("612"); orchard.setName("E.KOOTENAY BREED A"); orchard.setVegetationCode("SX"); @@ -162,8 +185,7 @@ void findNotRetiredOrchardValidLotTypeTest_Ret() { when(orchardRepository.findNotRetiredById(any())).thenReturn(Optional.of(orchard)); - Optional descriptionDto = - orchardService.findNotRetiredOrchardValidLotType("612"); + Optional descriptionDto = orchardService.findNotRetiredOrchardValidLotType("612"); Assertions.assertTrue(descriptionDto.isEmpty()); } @@ -186,7 +208,7 @@ void findParentTreeGeneticQualityDataTest_Success() { String orchardId = "407"; // Orchard - Orchard orchard = new Orchard(); + OrchardEntity orchard = new OrchardEntity(); orchard.setId(orchardId); orchard.setName("Test"); orchard.setVegetationCode("FDC"); @@ -279,7 +301,7 @@ void findNotRetOrchardsByVegCodeSuccessServiceTest() { firstLotTypeCode.setExpiryDate(now.plusDays(3L)); firstLotTypeCode.setUpdateTimestamp(now); String vegCode = "SX"; - Orchard firstOrchard = new Orchard(); + OrchardEntity firstOrchard = new OrchardEntity(); firstOrchard.setId("612"); firstOrchard.setName("E.KOOTENAY BREED A"); firstOrchard.setVegetationCode(vegCode); @@ -293,7 +315,7 @@ void findNotRetOrchardsByVegCodeSuccessServiceTest() { secondLotTypeCode.setEffectiveDate(now.minusDays(1L)); secondLotTypeCode.setExpiryDate(now.plusDays(1L)); secondLotTypeCode.setUpdateTimestamp(now); - Orchard secondOrchard = new Orchard(); + OrchardEntity secondOrchard = new OrchardEntity(); secondOrchard.setId("613"); secondOrchard.setName("BURNABY TOWERS"); secondOrchard.setVegetationCode(vegCode); @@ -307,20 +329,19 @@ void findNotRetOrchardsByVegCodeSuccessServiceTest() { expiredlotTypeCode.setEffectiveDate(now.minusDays(3L)); expiredlotTypeCode.setExpiryDate(now.minusDays(1L)); expiredlotTypeCode.setUpdateTimestamp(now); - Orchard expiredOrchard = new Orchard(); + OrchardEntity expiredOrchard = new OrchardEntity(); expiredOrchard.setId("666"); expiredOrchard.setName("EXPIRED AND STINKS"); expiredOrchard.setVegetationCode(vegCode); expiredOrchard.setStageCode("ESB"); expiredOrchard.setOrchardLotTypeCode(expiredlotTypeCode); - List repoResult = List.of(firstOrchard, secondOrchard, expiredOrchard); + List repoResult = List.of(firstOrchard, secondOrchard, expiredOrchard); when(orchardRepository.findAllByVegetationCodeAndStageCodeNot(vegCode, "RET")) .thenReturn(repoResult); - List listToTest = - orchardService.findNotRetOrchardsByVegCode(vegCode).get(); + List listToTest = orchardService.findNotRetOrchardsByVegCode(vegCode).get(); Assertions.assertEquals(2, listToTest.size()); listToTest.forEach(