diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java index 11a30aa2..6706536d 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/controller/AcntTermsController.java @@ -1,37 +1,24 @@ package com.palnet.biz.api.acnt.terms.controller; -import java.util.List; - +import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; +import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; +import com.palnet.biz.api.acnt.terms.service.AcntTermsService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.ErrorResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; -import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; -import com.palnet.biz.api.acnt.terms.service.AcntTermsService; -import com.palnet.biz.api.anls.hstry.model.AnlsHstryDetailModel; -import com.palnet.biz.api.anls.hstry.model.AnlsHstryModel; -import com.palnet.biz.api.anls.hstry.model.AnlsHstryRqModel; -import com.palnet.biz.api.anls.hstry.service.AnlsHstryService; -import com.palnet.biz.api.comn.response.BasicResponse; -import com.palnet.biz.api.comn.response.ErrorResponse; -import com.palnet.biz.api.comn.response.SuccessResponse; -import com.palnet.biz.api.ctr.cntrl.service.CtrCntrlService; -import com.palnet.biz.sample.entity.SampleEntity; -import com.palnet.biz.sample.service.SampleService; -import com.palnet.comn.model.GPHistoryModel; - -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; +import java.util.List; @Log4j2 @RestController diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java index ab5b360a..a578ad46 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/model/AcntTermsRqModel.java @@ -1,11 +1,16 @@ package com.palnet.biz.api.acnt.terms.model; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; @Data -public class AcntTermsRqModel{ - - private String siteCd; - - private String langDivCd; +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AcntTermsRqModel { + private String siteCd; + private String termsCtgryCd; + private String langDivCd; } diff --git a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java index fc41e412..ddef5f36 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/acnt/terms/service/AcntTermsService.java @@ -1,35 +1,24 @@ package com.palnet.biz.api.acnt.terms.service; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - import com.palnet.biz.api.acnt.terms.model.AcntTermsRqModel; import com.palnet.biz.api.acnt.terms.model.AcntTermsRsModel; import com.palnet.biz.jpa.repository.pty.PtyTermsQueryRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import java.util.List; + +@Slf4j +@RequiredArgsConstructor @Service public class AcntTermsService { - - private Logger logger = LoggerFactory.getLogger(getClass()); - -// @Autowired -// private CtrCntrlBasRepository ctrCntrlBasRepository; - - @Autowired - private PtyTermsQueryRepository query; - - - - public List list(AcntTermsRqModel rq){ - - List resultList = query.list(rq); - - return resultList; - } - - + + private final PtyTermsQueryRepository query; + + public List list(AcntTermsRqModel rq) { + return query.list(rq); + } + + } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java index e8039436..292daa44 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/controller/BasFlightController.java @@ -122,12 +122,39 @@ public class BasFlightController { return ResponseEntity.ok().body(new SuccessResponse<>(result)); } + // LAANC 비행계획서 검증 + @PostMapping(value = "/plan/valid") + @ApiOperation(value = "비행계획서 등록") + @Tag(name = "비행계획서", description = "비행계획서 관련 API") + public ResponseEntity validPlan(@RequestBody BasFlightPlanModel rq) { + BasFlightPlanLaancRs rs = null; + try { + log.debug(">>> rq : {}", rq); + rs = basFlightService.validPlan(rq); + log.debug(">>> rs : {}", rs); + + } catch (CustomException e) { + Map resultMap = new HashMap(); + log.error("IGNORE : {}", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : {}", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return ResponseEntity.ok().body(new SuccessResponse<>(rs)); + } + // 비행계획서 등록 @PostMapping(value = "/plan/create") @ApiOperation(value = "비행계획서 등록") @Tag(name = "비행계획서", description = "비행계획서 관련 API") public ResponseEntity createPlan(@RequestBody BasFlightPlanModel rq) { - BasFlightPlanLaancRs rs = null; + BasFlightPlanCreateRs rs = null; try { log.debug(">>> rq : {}", rq); rs = basFlightService.createPlan(rq); diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanCreateRs.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanCreateRs.java new file mode 100644 index 00000000..7387a623 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanCreateRs.java @@ -0,0 +1,26 @@ +package com.palnet.biz.api.bas.flight.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * packageName : com.palnet.biz.api.bas.flight.model + * fileName : BasFlightPlanErrorRS + * author : dhji + * date : 2023-09-19(019) + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2023-09-19(019) dhji 최초 생성 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BasFlightPlanCreateRs { + private String pdfUrl; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java index 747205ea..6d91603e 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanLaancRs.java @@ -1,5 +1,6 @@ package com.palnet.biz.api.bas.flight.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -25,13 +26,24 @@ public class BasFlightPlanLaancRs { private String acrftInsuranceYn; // 항공기보험여부 private String acrftDuplicatedYn; // 기체 중복여부 private String planAreaDuplicatdYn; // 비행계획서비행구역 중복여부 - private String airspaceDuplicatedYn; // 공역 중복여부 + private String evaluatedTargetAreaYn; // 평가대상지역여부 - 공역과 겹칠때만 + private String flightAreaYn; // LAANC 기준 비행가능여부 + private String corpRegYn; // 기업(사업자)가입여부 public boolean isValid() { return "Y".equals(pilotQlfcYn) && "Y".equals(acrftInsuranceYn) && "N".equals(acrftDuplicatedYn) && "N".equals(planAreaDuplicatdYn) - && "N".equals(airspaceDuplicatedYn); + && "Y".equals(evaluatedTargetAreaYn) + && "Y".equals(flightAreaYn); + } + + @JsonIgnore + public boolean isValidAirspace() { + return "N".equals(acrftDuplicatedYn) + && "N".equals(planAreaDuplicatdYn) + && "Y".equals(evaluatedTargetAreaYn) + && "Y".equals(flightAreaYn); } } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java index 2b3b2776..bf08a2f0 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/model/BasFlightPlanModel.java @@ -1,5 +1,6 @@ package com.palnet.biz.api.bas.flight.model; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrTermsModel; import lombok.Data; import java.time.Instant; @@ -34,4 +35,8 @@ public class BasFlightPlanModel { // kac 추가 필드 private String corpRegYn; private String serviceType; + // laanc 정보 + private BasFlightPlanLaancRs validLance; + // 약관동의 + private List terms; } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java index 02fd52f4..616d0185 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/flight/service/BasFlightService.java @@ -1,5 +1,6 @@ package com.palnet.biz.api.bas.flight.service; +import com.palnet.biz.api.acnt.cstmr.model.AnctCstmrTermsModel; import com.palnet.biz.api.acnt.jwt.model.JwtGroupModel; import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; import com.palnet.biz.api.bas.flight.model.*; @@ -11,13 +12,16 @@ import com.palnet.biz.api.external.service.TsService; import com.palnet.biz.jpa.entity.*; import com.palnet.biz.jpa.repository.flt.*; import com.palnet.biz.jpa.repository.pty.PtyGroupQueryRepository; +import com.palnet.biz.jpa.repository.pty.PtyTermsAgreeTxnRepository; import com.palnet.biz.scheduler.ctr.model.CtrTrnsLctnModel; import com.palnet.biz.scheduler.ctr.service.CtrTrnsLctnService; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; import com.palnet.comn.utils.AirspaceUtils; import com.palnet.comn.utils.AreaUtils; import com.palnet.comn.utils.EncryptUtils; +import com.palnet.comn.utils.HttpUtils; import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.json.simple.JSONObject; @@ -25,7 +29,6 @@ import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -40,6 +43,7 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -63,6 +67,7 @@ public class BasFlightService { private final FltPlanPilotRepository fltPlanPilotRepository; private final FltPlanQueryRepository fltPlanQueryRepository; private final PtyGroupQueryRepository ptyPlanQueryRepository; + private final PtyTermsAgreeTxnRepository ptyTermsAgreeTxnRepository; private final TsService tsService; private final JwtTokenUtil jwtTokenUtil; private final AreaUtils areaUtils; @@ -151,12 +156,14 @@ public class BasFlightService { } public BasFlightPlanLaancRs planValid(BasFlightPlanModel rq) { + BasFlightPlanLaancRs rs = BasFlightPlanLaancRs.builder() .pilotQlfcYn("N") .acrftInsuranceYn("N") - .airspaceDuplicatedYn("N") .acrftDuplicatedYn("N") .planAreaDuplicatdYn("N") + .evaluatedTargetAreaYn("N") + .flightAreaYn("N") .build(); boolean isEqualsFltElev = false; @@ -179,7 +186,8 @@ public class BasFlightService { } if (effectivePlanList != null && !effectivePlanList.isEmpty()) { - plan: for (BasFlightPlanModel plan : effectivePlanList) { + plan: + for (BasFlightPlanModel plan : effectivePlanList) { // 1. 구역 조회 List areaList = fltPlanAreaRepository.findByPlanSnoOrderByPlanAreaSnoAsc(plan.getPlanSno()); @@ -260,7 +268,8 @@ public class BasFlightService { } // 3. 중복 기체 확인 - acrft: for (BasFlightPlanAreaCoordRq idntfNum : effectivePlanCount) { + acrft: + for (BasFlightPlanAreaCoordRq idntfNum : effectivePlanCount) { for (BasFlightPlanArcrftModel rqArcrft : rq.getArcrftList()) { if (rqArcrft.getIdntfNum().equals(idntfNum.getIdntfNum())) { // throw new CustomException(ErrorCode.ARCRFT_DATA_DUPLICATE); @@ -296,18 +305,27 @@ public class BasFlightService { AirspaceUtils airspaceUtils = AirspaceUtils.getInstance(); Geometry rqGeometry = airspaceUtils.createGeometryByCoordinate(rqCoordBufferList); Integer fltElev = Integer.valueOf(rqArea.getFltElev()); - if(fltElev == null) fltElev = 0; + if (fltElev == null) fltElev = 0; AirspaceUtils.FeatureInfo featureInfo = new AirspaceUtils.FeatureInfo(null, null, 0, fltElev, rqGeometry); + + // 평가 가능 지역 판단 boolean duplicatedAirspace = airspaceUtils.isDuplicatedAirspace(featureInfo); - rs.setAirspaceDuplicatedYn(duplicatedAirspace ? "Y" : "N"); + rs.setEvaluatedTargetAreaYn(duplicatedAirspace ? "Y" : "N"); + + // 비행 가능 지역 판단 + if (duplicatedAirspace) { + boolean validLaancAirspace = airspaceUtils.isValidLaancAirspace(featureInfo); + rs.setFlightAreaYn(validLaancAirspace ? "Y" : "N"); + } else { + rs.setFlightAreaYn("N"); + } + } return rs; } - // 비행계획서 등록 - @Transactional - public BasFlightPlanLaancRs createPlan(BasFlightPlanModel rq) { - + // 비행계획서 검증(LAANC) + public BasFlightPlanLaancRs validPlan(BasFlightPlanModel rq) { // 비행계획서 유효성 검사. BasFlightPlanLaancRs rs = this.planValid(rq); @@ -316,17 +334,30 @@ public class BasFlightService { .pilotci("조종사CI") .declarationnum("기체신고번호") .build(); + PilotValidRs pilotValidRs = tsService.callPilotValid(pilotValidRq); - if(pilotValidRs == null){ + if (pilotValidRs == null) { rs.setPilotQlfcYn("N"); rs.setAcrftInsuranceYn("N"); + rs.setCorpRegYn("N"); } else { rs.setPilotQlfcYn(pilotValidRs.getPilotcredentialyn()); rs.setAcrftInsuranceYn(pilotValidRs.getArcrftinsuranceyn()); + rs.setCorpRegYn(pilotValidRs.getCorpregyn()); } + return rs; + } + + // 비행계획서 등록 + @Transactional + public BasFlightPlanCreateRs createPlan(BasFlightPlanModel rq) { + + // 비행계획서 유효성 검사. + BasFlightPlanLaancRs basFlightPlanLaancRs = this.planValid(rq); + + // LAANC가 검증된것들만 DB저장 + if (!basFlightPlanLaancRs.isValidAirspace()) new CustomException(ErrorCode.PLAN_DATA_DUPLICATE); - // TODO LAANC가 검증된것들만 DB저장 - LAANC가 미승인이라도 저장해야하는지 확인 필요 - if(!rs.isValid()) return rs; // 비행계획서 String userId = jwtTokenUtil.getUserIdByToken(); @@ -336,7 +367,7 @@ public class BasFlightService { basEntity.setCreateUserId(userId); basEntity.setUpdateUserId(userId); // 사업자 유무 - TS 데이터 - basEntity.setCorpRegYn(pilotValidRs.getCorpregyn()); // 사업자유무 + basEntity.setCorpRegYn(rq.getValidLance().getCorpRegYn()); // 사업자유무 basEntity.setServiceType("PAV-KAC"); FltPlanBas rBasEntity = fltPlanBasRepository.save(basEntity); @@ -386,12 +417,32 @@ public class BasFlightService { arcrftEntity.setCreateUserId(userId); arcrftEntity.setUpdateUserId(userId); // 추가 필드 - arcrftEntity.setAcrftInsuranceYn(pilotValidRs.getArcrftinsuranceyn()); // 보험여부 + arcrftEntity.setAcrftInsuranceYn(rq.getValidLance().getAcrftInsuranceYn()); // 보험여부 // arcrftEntity.setInsuranceExperiod(null); // 보헌 유효기간 // arcrftEntity.setCorporationNm(null); // 법인명 fltPlanArcrftRepository.save(arcrftEntity); } } + // 약관 저장 + if (rq.getTerms() != null && !rq.getTerms().isEmpty()) { + for (AnctCstmrTermsModel agree : rq.getTerms()) { + PtyTermsAgreeTxn agreeEntity = new PtyTermsAgreeTxn(); + agreeEntity.setCstmrSno(basEntity.getCstmrSno()); + agreeEntity.setProcIp(HttpUtils.getRequestIp()); + agreeEntity.setTermsSno(agree.getTermsSno()); + agreeEntity.setUpdateDt(Instant.now()); + agreeEntity.setUpdateUserId(userId); + agreeEntity.setAgreeYn(agree.getAgreeYn()); + if (agree.getAgreeYn().equals("Y")) { + agreeEntity.setAgreeDt(Instant.now()); + } + ptyTermsAgreeTxnRepository.save(agreeEntity); + } + } else { + throw new CustomException(ErrorCode.FAIL, "약관등록 실패"); + } + // TODO PDF 생성 후 URL 가져오기 + BasFlightPlanCreateRs rs = new BasFlightPlanCreateRs(); return rs; } @@ -408,7 +459,7 @@ public class BasFlightService { .declarationnum("기체신고번호") .build(); PilotValidRs pilotValidRs = tsService.callPilotValid(pilotValidRq); - if(pilotValidRs == null){ + if (pilotValidRs == null) { rs.setPilotQlfcYn("N"); rs.setAcrftInsuranceYn("N"); } else { @@ -417,7 +468,7 @@ public class BasFlightService { } // LAANC가 검증된것들만 DB저장 - if(!rs.isValid()) return rs; + if (!rs.isValid()) return rs; if (rq != null && rq.getPlanSno() != null) { String userId = jwtTokenUtil.getUserIdByToken(); @@ -790,6 +841,4 @@ public class BasFlightService { return jsonObject; } - - } diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java index ae4af913..b6c5fc2d 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/PtyTermsAgreeTxn.java @@ -1,6 +1,9 @@ package com.palnet.biz.jpa.entity; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import javax.persistence.*; import java.io.Serializable; @@ -9,41 +12,43 @@ import java.time.Instant; /** * The persistent class for the PTY_TERMS_AGREE_TXN database table. - * */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor @Entity -@Table(name="PTY_TERMS_AGREE_TXN") -@NamedQuery(name="PtyTermsAgreeTxn.findAll", query="SELECT p FROM PtyTermsAgreeTxn p") +@Table(name = "PTY_TERMS_AGREE_TXN") +@NamedQuery(name = "PtyTermsAgreeTxn.findAll", query = "SELECT p FROM PtyTermsAgreeTxn p") public class PtyTermsAgreeTxn implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Id - @Column(name="AGREE_SNO") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private int agreeSno; + @Id + @Column(name = "AGREE_SNO") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int agreeSno; -// @Temporal(TemporalType.TIMESTAMP) - @Column(name="AGREE_DT", columnDefinition = "TIMESTAMP") - private Instant agreeDt; + // @Temporal(TemporalType.TIMESTAMP) + @Column(name = "AGREE_DT", columnDefinition = "TIMESTAMP") + private Instant agreeDt; - @Column(name="AGREE_YN") - private String agreeYn; + @Column(name = "AGREE_YN") + private String agreeYn; - @Column(name="CSTMR_SNO") - private int cstmrSno; + @Column(name = "CSTMR_SNO") + private int cstmrSno; - @Column(name="PROC_IP") - private String procIp; + @Column(name = "PROC_IP") + private String procIp; - @Column(name="TERMS_SNO") - private int termsSno; + @Column(name = "TERMS_SNO") + private int termsSno; -// @Temporal(TemporalType.TIMESTAMP) - @Column(name="UPDATE_DT", columnDefinition = "TIMESTAMP") - private Instant updateDt; + // @Temporal(TemporalType.TIMESTAMP) + @Column(name = "UPDATE_DT", columnDefinition = "TIMESTAMP") + private Instant updateDt; - @Column(name="UPDATE_USER_ID") - private String updateUserId; + @Column(name = "UPDATE_USER_ID") + private String updateUserId; } \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java index 61146401..bece9904 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/pty/PtyTermsQueryRepository.java @@ -18,44 +18,42 @@ import lombok.extern.log4j.Log4j2; @Log4j2 @Repository @RequiredArgsConstructor -public class PtyTermsQueryRepository{ - - - private final JPAQueryFactory query; - - public List list(AcntTermsRqModel rq){ - - QPtyTermsBas basEntity = QPtyTermsBas.ptyTermsBas; - QPtyTermsDtl dtlEntity = QPtyTermsDtl.ptyTermsDtl; - - BooleanBuilder builder = new BooleanBuilder(); - - builder.and(basEntity.lastTxnYn.eq("Y")); - builder.and(basEntity.siteCd.eq(rq.getSiteCd())); - - - List queryList = query.select(Projections.bean(AcntTermsRsModel.class , - basEntity.termsSno, - basEntity.siteCd, - basEntity.estbshDate, - basEntity.termsCtgryCd, - dtlEntity.id.langDivCd, - dtlEntity.termsTitleNm, - dtlEntity.termsCn, - dtlEntity.simpleCn - )) - .from(basEntity) - .leftJoin(dtlEntity) - .on(basEntity.termsSno.eq(dtlEntity.id.termsSno).and(dtlEntity.id.langDivCd.eq(rq.getLangDivCd()))) - .where(builder) - .orderBy(basEntity.updateDt.desc()) - .fetch(); - - return queryList; - } - - - - - +public class PtyTermsQueryRepository { + + + private final JPAQueryFactory query; + + public List list(AcntTermsRqModel rq) { + + QPtyTermsBas basEntity = QPtyTermsBas.ptyTermsBas; + QPtyTermsDtl dtlEntity = QPtyTermsDtl.ptyTermsDtl; + + BooleanBuilder builder = new BooleanBuilder(); + + builder.and(basEntity.lastTxnYn.eq("Y")); + builder.and(basEntity.siteCd.eq(rq.getSiteCd())); + builder.and(basEntity.termsCtgryCd.eq(rq.getTermsCtgryCd())); + + + List queryList = query.select(Projections.bean(AcntTermsRsModel.class, + basEntity.termsSno, + basEntity.siteCd, + basEntity.estbshDate, + basEntity.termsCtgryCd, + dtlEntity.id.langDivCd, + dtlEntity.termsTitleNm, + dtlEntity.termsCn, + dtlEntity.simpleCn + )) + .from(basEntity) + .leftJoin(dtlEntity) + .on(basEntity.termsSno.eq(dtlEntity.id.termsSno).and(dtlEntity.id.langDivCd.eq(rq.getLangDivCd()))) + .where(builder) + .orderBy(basEntity.updateDt.desc()) + .fetch(); + + return queryList; + } + + } diff --git a/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java index 80bfb004..6a37fb9e 100644 --- a/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java +++ b/pav-server/src/main/java/com/palnet/comn/utils/AirspaceUtils.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.util.modeler.FeatureInfo; import org.geotools.geojson.feature.FeatureJSON; import org.geotools.geojson.geom.GeometryJSON; import org.json.simple.JSONArray; @@ -56,8 +57,17 @@ public class AirspaceUtils { private static final AirspaceUtils INSTANCE = new AirspaceUtils(); } - // 공역 중복 검사 + // 공영 중복 검사 - 고도x public boolean isDuplicatedAirspace(FeatureInfo target) { + Geometry targetGeometry = target.getGeometry(); + return this.airspaces.stream().anyMatch(featureInfo -> { + Geometry featureGeometry = featureInfo.getGeometry(); + return featureGeometry.intersects(targetGeometry); + }); + } + + // 공역 중복 검사 + public boolean isDuplicatedAirspaceElev(FeatureInfo target) { if (this.airspaces == null || this.airspaces.isEmpty()) return true; Integer targetHighElev = target.getHighElev(); if (targetHighElev == null) targetHighElev = 0; @@ -68,16 +78,47 @@ public class AirspaceUtils { Geometry airspaceGeometry = airspace.getGeometry(); // 임시로 0~최대고도 기준으로 검증 - if(airspaceHighElev <= targetHighElev) { + if (airspaceHighElev <= targetHighElev) { if (airspaceGeometry.intersects(targetGeometry)) { return true; } } - } return false; } + /* + LAANC 공역 검사 + - 비행구역이 공역(금지구역)에 접근할 경우만 검사 - 통과 true, 실패 false + - 겹치지 않을 경우는 실패로 처리 - false + */ + public boolean isValidLaancAirspace(FeatureInfo target) { + if (this.airspaces == null || this.airspaces.isEmpty()) return true; + final int targetHighElev = target.getHighElev() != null ? target.getHighElev() : 0; + Geometry targetGeometry = target.getGeometry(); + + boolean isDuplicated = this.airspaces.stream().anyMatch(featureInfo -> { + Geometry featureGeometry = featureInfo.getGeometry(); + return featureGeometry.intersects(targetGeometry); + }); + // 공역(금지구역)과 겹치지 않을 경우는 실패로 처리 + if (!isDuplicated) return false; + + // 겹칠 경우 공역과 비교 + for (FeatureInfo featureInfo : this.airspaces) { + Geometry airspaceGeometry = featureInfo.getGeometry(); + int airspaceHighElev = featureInfo.getHighElev() != null ? featureInfo.getHighElev() : 0; + // 임시로 0~최대고도 기준으로 검증 + if (airspaceHighElev == 0 || airspaceHighElev < targetHighElev) { + if (airspaceGeometry.intersects(targetGeometry)) { + return false; + } + } + } + return true; + } + + public Geometry createGeometryByCoordinate(List target) { return this.createGeometryByCoordinate(target, "Polygon"); } @@ -102,11 +143,9 @@ public class AirspaceUtils { // 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화. private void getResourceAirspace() { ClassPathResource resource = new ClassPathResource(CLASS_PATH); - log.debug(">>> {}", resource); List geoJsonFiles = new ArrayList<>(); try { File folder = resource.getFile(); - log.debug(">>> {}", folder); File[] files = folder.listFiles(); for (File file : files) { if (file.isFile() && file.getName().endsWith("elev.json")) { @@ -120,7 +159,6 @@ public class AirspaceUtils { List featureInfos = new ArrayList<>(); for (File file : geoJsonFiles) { - log.debug("============ {} ===================", file.getName()); try (InputStreamReader isr = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { JSONParser jsonParser = new JSONParser(); JSONObject jsonObject = (JSONObject) jsonParser.parse(isr); @@ -253,12 +291,13 @@ public class AirspaceUtils { */ + log.info("=== 김포 정상 ==="); Coordinate[] polygonCoordinates6 = new Coordinate[]{ - new Coordinate(126.6186219,37.4260888), - new Coordinate(126.7662507,37.4473521), - new Coordinate(126.7223054,37.3578964), - new Coordinate(126.6186219,37.4260888) + new Coordinate(126.6186219, 37.4260888), + new Coordinate(126.7662507, 37.4473521), + new Coordinate(126.7223054, 37.3578964), + new Coordinate(126.6186219, 37.4260888) }; LinearRing linearRing6 = geometryFactory.createLinearRing(polygonCoordinates6); Polygon polygon6 = geometryFactory.createPolygon(linearRing6); @@ -266,15 +305,16 @@ public class AirspaceUtils { target6.setHighElev(0); target6.setLowElev(0); target6.setGeometry(polygon6); - boolean duplicatedAirspace6 = airspaceUtils.isDuplicatedAirspace(target6); +// boolean duplicatedAirspace6 = airspaceUtils.isDuplicatedAirspace(target6); + boolean duplicatedAirspace6 = airspaceUtils.isValidLaancAirspace(target6); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace6); log.info("=== 김포 120m 걸침 - 100 ==="); Coordinate[] polygonCoordinates7 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing7 = geometryFactory.createLinearRing(polygonCoordinates7); Polygon polygon7 = geometryFactory.createPolygon(linearRing7); @@ -282,15 +322,16 @@ public class AirspaceUtils { target7.setHighElev(100); target7.setLowElev(0); target7.setGeometry(polygon7); - boolean duplicatedAirspace7 = airspaceUtils.isDuplicatedAirspace(target7); +// boolean duplicatedAirspace7 = airspaceUtils.isDuplicatedAirspace(target7); + boolean duplicatedAirspace7 = airspaceUtils.isValidLaancAirspace(target7); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace7); log.info("=== 김포 120m 걸침 - 150 ==="); Coordinate[] polygonCoordinates8 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing8 = geometryFactory.createLinearRing(polygonCoordinates8); Polygon polygon8 = geometryFactory.createPolygon(linearRing8); @@ -298,15 +339,16 @@ public class AirspaceUtils { target8.setHighElev(150); target8.setLowElev(0); target8.setGeometry(polygon8); - boolean duplicatedAirspace8 = airspaceUtils.isDuplicatedAirspace(target8); +// boolean duplicatedAirspace8 = airspaceUtils.isDuplicatedAirspace(target8); + boolean duplicatedAirspace8 = airspaceUtils.isValidLaancAirspace(target8); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace8); log.info("=== 김포 120m 걸침 - 120 ==="); Coordinate[] polygonCoordinates9 = new Coordinate[]{ - new Coordinate(126.6828233,37.4553499), - new Coordinate(126.7456514,37.5082038), - new Coordinate(126.7796403,37.4414491), - new Coordinate(126.6828233,37.4553499) + new Coordinate(126.6828233, 37.4553499), + new Coordinate(126.7456514, 37.5082038), + new Coordinate(126.7796403, 37.4414491), + new Coordinate(126.6828233, 37.4553499) }; LinearRing linearRing9 = geometryFactory.createLinearRing(polygonCoordinates9); Polygon polygon9 = geometryFactory.createPolygon(linearRing9); @@ -314,15 +356,16 @@ public class AirspaceUtils { target9.setHighElev(120); target9.setLowElev(0); target9.setGeometry(polygon9); - boolean duplicatedAirspace9 = airspaceUtils.isDuplicatedAirspace(target9); +// boolean duplicatedAirspace9 = airspaceUtils.isDuplicatedAirspace(target9); + boolean duplicatedAirspace9 = airspaceUtils.isValidLaancAirspace(target9); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace9); log.info("=== 김포 40m 걸침 - 20 ==="); Coordinate[] polygonCoordinates10 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing10 = geometryFactory.createLinearRing(polygonCoordinates10); Polygon polygon10 = geometryFactory.createPolygon(linearRing10); @@ -330,15 +373,16 @@ public class AirspaceUtils { target10.setHighElev(20); target10.setLowElev(0); target10.setGeometry(polygon10); - boolean duplicatedAirspace10 = airspaceUtils.isDuplicatedAirspace(target10); +// boolean duplicatedAirspace10 = airspaceUtils.isDuplicatedAirspace(target10); + boolean duplicatedAirspace10 = airspaceUtils.isValidLaancAirspace(target10); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace10); log.info("=== 김포 40m 걸침 - 100 ==="); Coordinate[] polygonCoordinates11 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing11 = geometryFactory.createLinearRing(polygonCoordinates11); Polygon polygon11 = geometryFactory.createPolygon(linearRing11); @@ -346,15 +390,16 @@ public class AirspaceUtils { target11.setHighElev(100); target11.setLowElev(0); target11.setGeometry(polygon11); - boolean duplicatedAirspace11 = airspaceUtils.isDuplicatedAirspace(target11); +// boolean duplicatedAirspace11 = airspaceUtils.isDuplicatedAirspace(target11); + boolean duplicatedAirspace11 = airspaceUtils.isValidLaancAirspace(target11); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace11); log.info("=== 김포 40m 걸침 - 40 ==="); Coordinate[] polygonCoordinates12 = new Coordinate[]{ - new Coordinate(126.6750825,37.5134229), - new Coordinate(126.7804826,37.5168269), - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.6750825,37.5134229) + new Coordinate(126.6750825, 37.5134229), + new Coordinate(126.7804826, 37.5168269), + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.6750825, 37.5134229) }; LinearRing linearRing12 = geometryFactory.createLinearRing(polygonCoordinates12); Polygon polygon12 = geometryFactory.createPolygon(linearRing12); @@ -362,15 +407,16 @@ public class AirspaceUtils { target12.setHighElev(40); target12.setLowElev(0); target12.setGeometry(polygon12); - boolean duplicatedAirspace12 = airspaceUtils.isDuplicatedAirspace(target12); +// boolean duplicatedAirspace12 = airspaceUtils.isDuplicatedAirspace(target12); + boolean duplicatedAirspace12 = airspaceUtils.isValidLaancAirspace(target12); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace12); log.info("=== 김포 0 ==="); Coordinate[] polygonCoordinates13 = new Coordinate[]{ - new Coordinate(126.7679513,37.4853679), - new Coordinate(126.8074335,37.5572547), - new Coordinate(126.9097436,37.4477632), - new Coordinate(126.7679513,37.4853679) + new Coordinate(126.7679513, 37.4853679), + new Coordinate(126.8074335, 37.5572547), + new Coordinate(126.9097436, 37.4477632), + new Coordinate(126.7679513, 37.4853679) }; LinearRing linearRing13 = geometryFactory.createLinearRing(polygonCoordinates13); Polygon polygon13 = geometryFactory.createPolygon(linearRing13); @@ -378,7 +424,8 @@ public class AirspaceUtils { target13.setHighElev(0); target13.setLowElev(0); target13.setGeometry(polygon13); - boolean duplicatedAirspace13 = airspaceUtils.isDuplicatedAirspace(target13); +// boolean duplicatedAirspace13 = airspaceUtils.isDuplicatedAirspace(target13); + boolean duplicatedAirspace13 = airspaceUtils.isValidLaancAirspace(target13); log.info(">>> duplicatedAirspace : {}", duplicatedAirspace13); // 김포