|
|
|
@ -53,6 +53,7 @@ import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
|
import java.io.*; |
|
|
|
|
import java.lang.reflect.Field; |
|
|
|
|
import java.net.URLEncoder; |
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
import java.time.Instant; |
|
|
|
@ -129,9 +130,10 @@ public class BasDosService {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 비행지역
|
|
|
|
|
List<BasDosPlanAreaRs> areaRsList = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
// area 객체를
|
|
|
|
|
for (DosFltPlanArea area : areaList) { |
|
|
|
|
if (area.getPlanSno().equals(planSno)) { |
|
|
|
|
Optional<DosFltPlanResult> first = resultList.stream().filter(result -> result.getPlanAreaSno().equals(area.getPlanAreaSno())).findFirst(); |
|
|
|
@ -143,6 +145,11 @@ public class BasDosService {
|
|
|
|
|
fltElevMax = dosFltPlanResult.getFltElevMax(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 1. 요청코드가 있을경우 [검색조건] |
|
|
|
|
* 2. 조회할 area의 승인코드 있을경우 |
|
|
|
|
* 3. 요청코드와 조회한 area의 승인코드가 맞지 않을경우 continue |
|
|
|
|
*/ |
|
|
|
|
if (rq.getApprovalCd() != null && approvalCd != null && !rq.getApprovalCd().equals(approvalCd.getCode())) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -175,6 +182,7 @@ public class BasDosService {
|
|
|
|
|
}); |
|
|
|
|
if (!isContain) continue; |
|
|
|
|
} else if ("DF0002-1".equals(cptAuthCode)) { |
|
|
|
|
// 운항과는 전체건수 조회
|
|
|
|
|
/* |
|
|
|
|
// TODO 운항과(김항소 관리 전역)
|
|
|
|
|
if(boundary == null) { |
|
|
|
@ -204,12 +212,15 @@ public class BasDosService {
|
|
|
|
|
.geometry(rqGeometry) |
|
|
|
|
.build(); |
|
|
|
|
boolean isDuplicatedAirspace = airspaceUtils.isDuplicatedAirspace(targetfeatureInfo, AirspaceUtils.AirspaceType.GIMPO); |
|
|
|
|
|
|
|
|
|
// 지역과 공역이 중복되지 않는다면 continue
|
|
|
|
|
if (!isDuplicatedAirspace) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
bufferCoordList = coordBuffers.stream().map(coord -> Map.of("lat", coord.y, "lon", coord.x)).collect(Collectors.toList()); |
|
|
|
|
if (area.getReqRadius() != null && area.getReqRadius() > 0) { |
|
|
|
|
// 승인요청 지역 바운더리 좌표
|
|
|
|
|
List<Coordinate> reqCoordBuffers = areaUtils.createCircle(new Coordinate(area.getLon(), area.getLat()), area.getReqRadius()); |
|
|
|
|
reqBufferCoordList = reqCoordBuffers.stream().map(coord -> Map.of("lat", coord.y, "lon", coord.x)).collect(Collectors.toList()); |
|
|
|
|
} |
|
|
|
@ -959,4 +970,330 @@ public class BasDosService {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 페이징처리 |
|
|
|
|
* @param rq |
|
|
|
|
* @param type |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
@Transactional(readOnly = true) |
|
|
|
|
public SearchBasDosPlanRS getPagingDosPlan(SearchBasDosPlanRQ rq, PlanSelectType type){ |
|
|
|
|
List<DosFltPlanBas> planBasList = dosFltPlanQueryRepository.findPlanByBasSearch(rq); |
|
|
|
|
|
|
|
|
|
if (planBasList.isEmpty()) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<Long> planSnoList = planBasList.stream().map(DosFltPlanBas::getPlanSno).collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
Long totalDataCount = dosFltPlanQueryRepository.countByPlanSnoInAndSearchOrderByZoneNoAsc(planSnoList, rq); |
|
|
|
|
Long totalPages = totalDataCount / rq.getPageDataSize(); |
|
|
|
|
|
|
|
|
|
if(rq.getPage() > totalPages || rq.getPage() < 1) throw new CustomException(ErrorCode.NON_VALID_PARAMETER, String.format("페이지는 [ %s ] page 부터 [ %s ] page 까지입니다.", 1, totalPages)); |
|
|
|
|
|
|
|
|
|
if(totalDataCount % rq.getPageDataSize() > 0) totalPages ++; |
|
|
|
|
|
|
|
|
|
Boolean isFirst = rq.getPage() == 1; |
|
|
|
|
Boolean isLast = rq.getPage().equals(totalPages); |
|
|
|
|
|
|
|
|
|
Pagination pagination = new Pagination(); |
|
|
|
|
pagination.setTotalDataCount(totalDataCount); |
|
|
|
|
pagination.setTotalPages(totalPages); |
|
|
|
|
pagination.setCurrentPage(rq.getPage()); |
|
|
|
|
pagination.setPageDataSize(rq.getPageDataSize()); |
|
|
|
|
pagination.setIsFirst(isFirst); |
|
|
|
|
pagination.setIsLast(isLast); |
|
|
|
|
|
|
|
|
|
Map<Long , DosFltPlanBas> fltPlanBasMap = this.getConvertMap(planBasList, "planSno", Long.class); |
|
|
|
|
|
|
|
|
|
List<DosFltPlanArea> areaList = dosFltPlanQueryRepository.findByPlanSnoInAndSearchOrderByZoneNoAsc(planSnoList, rq); |
|
|
|
|
List<DosFltPlanResult> resultList = dosFltPlanResultRepository.findByPlanSnoIn(planSnoList); |
|
|
|
|
|
|
|
|
|
Set<Long> areaPlanSno = areaList.stream().map(DosFltPlanArea::getPlanSno).collect(Collectors.toSet()); |
|
|
|
|
Set<Long> removePlanSnoSet = new HashSet<>(planSnoList); |
|
|
|
|
removePlanSnoSet.removeAll(areaPlanSno); |
|
|
|
|
|
|
|
|
|
List<Long> removeList = new ArrayList<>(removePlanSnoSet); |
|
|
|
|
for(Long removePlanSno : removeList){ |
|
|
|
|
fltPlanBasMap.remove(removePlanSno); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<BasDosPlanRs> rs = new ArrayList<>(); |
|
|
|
|
List<Geometry> boundary = null; |
|
|
|
|
|
|
|
|
|
for(Map.Entry<Long, DosFltPlanBas> entry : fltPlanBasMap.entrySet()){ |
|
|
|
|
Long planSno = entry.getKey(); |
|
|
|
|
DosFltPlanBas bas = entry.getValue(); |
|
|
|
|
|
|
|
|
|
String applyNo = bas.getApplyNo(); |
|
|
|
|
|
|
|
|
|
// 신청일시 분할
|
|
|
|
|
LocalDate applyDt = bas.getApplyDt(); |
|
|
|
|
String applyDtMonth = String.valueOf(applyDt.getMonthValue()); |
|
|
|
|
String applyDtDay = String.valueOf(applyDt.getDayOfMonth()); |
|
|
|
|
|
|
|
|
|
// 비행목적 - 비행목적은 레저비행, 사진/영상촬영을 제외한 나머지 목적은 기타 로 표현
|
|
|
|
|
String purpose = "기타"; |
|
|
|
|
String[] purposeTexts = {"레저비행", "사진/영상촬영"}; |
|
|
|
|
|
|
|
|
|
if (StringUtils.hasText(bas.getPurpose())) { |
|
|
|
|
purpose = Arrays.asList(purposeTexts).contains(bas.getPurpose()) ? bas.getPurpose() : "기타"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<BasDosPlanAreaRs> areaRsList = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < areaList.size(); i ++) { |
|
|
|
|
|
|
|
|
|
DosFltPlanArea area = areaList.get(i); |
|
|
|
|
|
|
|
|
|
if (area.getPlanSno().equals(planSno)) { |
|
|
|
|
Optional<DosFltPlanResult> first = resultList.stream().filter(result -> result.getPlanAreaSno().equals(area.getPlanAreaSno())).findFirst(); |
|
|
|
|
ApprovalCd approvalCd = null; |
|
|
|
|
Double fltElevMax = null; |
|
|
|
|
if (first.isPresent()) { |
|
|
|
|
DosFltPlanResult dosFltPlanResult = first.get(); |
|
|
|
|
approvalCd = ApprovalCd.fromCode(dosFltPlanResult.getApprovalCd()); |
|
|
|
|
fltElevMax = dosFltPlanResult.getFltElevMax(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 1. 요청코드가 있을경우 [검색조건] |
|
|
|
|
* 2. 조회할 area의 승인코드 있을경우 |
|
|
|
|
* 3. 요청코드와 조회한 area의 승인코드가 맞지 않을경우 continue |
|
|
|
|
*/ |
|
|
|
|
if (rq.getApprovalCd() != null && approvalCd != null && !rq.getApprovalCd().equals(approvalCd.getCode())) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ReviewedType이 UNNECESSARY(불필요)인 경우 ApprovalCd가 UNTARGETED_AREA(비대상)인 경우만 조회
|
|
|
|
|
if (rq.getReviewedType() == ReviewedType.UNNECESSARY) { |
|
|
|
|
if (approvalCd != ApprovalCd.UNTARGETED_AREA) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 사용자 부서에 따른 필터 관제과(DF0002), 운항과(DF0002-1)
|
|
|
|
|
String cptAuthCode = jwtTokenUtil.getCptAuthCodeByToken(); |
|
|
|
|
if (cptAuthCode != null) { |
|
|
|
|
Coordinate centerPoint = new Coordinate(area.getLon(), area.getLat()); |
|
|
|
|
if ("DF0002".equals(cptAuthCode)) { |
|
|
|
|
// 관제과와 관련된 내용으로만 필터링 reviewedProcType이 null이 아니라면 표출
|
|
|
|
|
if (area.getReviewedProcType() == null) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 관제과(9.3km)
|
|
|
|
|
AirspaceUtils airspaceUtils = AirspaceUtils.getInstance(); |
|
|
|
|
List<AirspaceUtils.FeatureInfo> airspaces = airspaceUtils.getAirspaces(AirspaceUtils.AirspaceType.GIMPO); |
|
|
|
|
GeometryFactory geometryFactory = new GeometryFactory(); |
|
|
|
|
Point point = geometryFactory.createPoint(centerPoint); |
|
|
|
|
boolean isContain = airspaces.stream().anyMatch(airspace -> { |
|
|
|
|
Geometry airspaceGeometry = airspace.getGeometry(); |
|
|
|
|
return airspaceGeometry.contains(point); |
|
|
|
|
}); |
|
|
|
|
if (!isContain) continue; |
|
|
|
|
} else if ("DF0002-1".equals(cptAuthCode)) { |
|
|
|
|
// 운항과는 전체건수 조회
|
|
|
|
|
/* |
|
|
|
|
// TODO 운항과(김항소 관리 전역)
|
|
|
|
|
if(boundary == null) { |
|
|
|
|
boundary = comnCoordinateService.getDeptGeometry("F0002"); |
|
|
|
|
} |
|
|
|
|
// log.info("boundary : {}", boundary);
|
|
|
|
|
GeometryFactory geometryFactory = new GeometryFactory(); |
|
|
|
|
Point point = geometryFactory.createPoint(centerPoint); |
|
|
|
|
boolean isContain = boundary.stream().anyMatch(geometry -> geometry.contains(point)); |
|
|
|
|
if(!isContain) continue; |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<Map<String, Double>> bufferCoordList = null; |
|
|
|
|
List<Map<String, Double>> reqBufferCoordList = null; |
|
|
|
|
if (type == PlanSelectType.LIST) { |
|
|
|
|
List<Coordinate> coordBuffers = areaUtils.createCircle(new Coordinate(area.getLon(), area.getLat()), area.getBufferZone()); |
|
|
|
|
if ("GIMPO".equalsIgnoreCase(rq.getSelectZone())) { |
|
|
|
|
AirspaceUtils airspaceUtils = AirspaceUtils.getInstance(); |
|
|
|
|
Geometry rqGeometry = airspaceUtils.createGeometryByCoordinate(coordBuffers); |
|
|
|
|
|
|
|
|
|
AirspaceUtils.FeatureInfo targetfeatureInfo = AirspaceUtils.FeatureInfo.builder() |
|
|
|
|
.lowElev(0D) |
|
|
|
|
.highElev(area.getFltElev()) |
|
|
|
|
.geometry(rqGeometry) |
|
|
|
|
.build(); |
|
|
|
|
boolean isDuplicatedAirspace = airspaceUtils.isDuplicatedAirspace(targetfeatureInfo, AirspaceUtils.AirspaceType.GIMPO); |
|
|
|
|
|
|
|
|
|
// 지역과 공역이 중복되지 않는다면 continue
|
|
|
|
|
if (!isDuplicatedAirspace) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
bufferCoordList = coordBuffers.stream().map(coord -> Map.of("lat", coord.y, "lon", coord.x)).collect(Collectors.toList()); |
|
|
|
|
if (area.getReqRadius() != null && area.getReqRadius() > 0) { |
|
|
|
|
// 승인요청 지역 바운더리 좌표
|
|
|
|
|
List<Coordinate> reqCoordBuffers = areaUtils.createCircle(new Coordinate(area.getLon(), area.getLat()), area.getReqRadius()); |
|
|
|
|
reqBufferCoordList = reqCoordBuffers.stream().map(coord -> Map.of("lat", coord.y, "lon", coord.x)).collect(Collectors.toList()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO 추후 Utils 생성
|
|
|
|
|
// 주소 분할 - 임시 순서대로 split
|
|
|
|
|
String addr = area.getAddr() != null ? area.getAddr() : ""; |
|
|
|
|
String[] addrArr = addr.split(" "); |
|
|
|
|
String addr1 = ""; |
|
|
|
|
String addr2 = ""; |
|
|
|
|
StringBuilder addrRest = new StringBuilder(); |
|
|
|
|
for (int j = 0; j < addrArr.length; j++) { |
|
|
|
|
switch (j) { |
|
|
|
|
case 0: |
|
|
|
|
addr1 = addrArr[j]; |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
addr2 = addrArr[j]; |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
addrRest.append(addrArr[j]); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
addrRest.append(" ").append(addrArr[j]); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String addr3 = addrRest.toString(); |
|
|
|
|
String limitZone = area.getLimitZone(); |
|
|
|
|
LimitZoneType limitZoneType = LimitZoneType.fromCode(limitZone); |
|
|
|
|
|
|
|
|
|
ReviewedType reviewedType = area.getReviewedType(); |
|
|
|
|
if (reviewedType == null) { |
|
|
|
|
reviewedType = approvalCd == ApprovalCd.UNTARGETED_AREA ? ReviewedType.UNNECESSARY : ReviewedType.WAIT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BasDosPlanAreaRs areaRs = BasDosPlanAreaRs.builder() |
|
|
|
|
.planAreaSno(area.getPlanAreaSno()) |
|
|
|
|
.planSno(area.getPlanSno()) |
|
|
|
|
.applyNo(applyNo) |
|
|
|
|
.applyDt(applyDt) |
|
|
|
|
.applyDtMonth(applyDtMonth) |
|
|
|
|
.applyDtDay(applyDtDay) |
|
|
|
|
.zoneNo(area.getZoneNo()) |
|
|
|
|
.bufferZone(area.getBufferZone()) |
|
|
|
|
.fltElev(area.getFltElev()) |
|
|
|
|
.lat(area.getLat()) |
|
|
|
|
.lon(area.getLon()) |
|
|
|
|
.addr(addr) |
|
|
|
|
.addr1(addr1) |
|
|
|
|
.addr2(addr2) |
|
|
|
|
.addr3(addr3) |
|
|
|
|
.approvalCd(approvalCd != null ? approvalCd.getCode() : null) |
|
|
|
|
.fltElevMax(fltElevMax) |
|
|
|
|
.reqElev(area.getReqElev()) |
|
|
|
|
.dtl(area.getDtl()) |
|
|
|
|
.era(area.getEra()) |
|
|
|
|
.rm(area.getRm()) |
|
|
|
|
.reviewedType(reviewedType) |
|
|
|
|
.reviewedReason(area.getReviewedReason()) |
|
|
|
|
.reviewedProcType(area.getReviewedProcType()) |
|
|
|
|
.reqRadius(area.getReqRadius()) |
|
|
|
|
.allowRadius(area.getAllowRadius()) |
|
|
|
|
.limitZoneCd(area.getLimitZone()) |
|
|
|
|
.limitZoneNm(limitZoneType != null ? limitZoneType.getMessage() : null) |
|
|
|
|
.bufferCoordList(bufferCoordList) |
|
|
|
|
.reqBufferCoordList(reqBufferCoordList) |
|
|
|
|
.build(); |
|
|
|
|
areaRsList.add(areaRs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
areaList.remove(area); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO :: 속도이슈 걸리는 곳.. [paging 하면 완화됨]
|
|
|
|
|
List<BasDosPlanDroneRs> droneList = null; |
|
|
|
|
List<BasDosPlanPilotRs> pilotList = null; |
|
|
|
|
if (type == PlanSelectType.LIST) { |
|
|
|
|
droneList = dosFltPlanDroneRepository.findByPlanSno(planSno).stream().map(drone -> { |
|
|
|
|
String weightCd = drone.getWeightCd(); |
|
|
|
|
WeightCdType weightCdType = WeightCdType.fromCode(weightCd); |
|
|
|
|
return BasDosPlanDroneRs.builder() |
|
|
|
|
.planDroneSno(drone.getPlanDroneSno()) |
|
|
|
|
.fbctnNo(drone.getFbctnNo()) |
|
|
|
|
.benefit(drone.getBenefit()) |
|
|
|
|
.weightCd(drone.getWeightCd()) |
|
|
|
|
.weightNm(weightCdType != null ? weightCdType.getMessage() : null) |
|
|
|
|
.insrncJoinYn(drone.getInsrncJoinYn()) |
|
|
|
|
.build(); |
|
|
|
|
}).collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
pilotList = dosFltPlanPilotRepository.findByPlanSno(planSno).stream().map(pilot -> { |
|
|
|
|
return BasDosPlanPilotRs.builder() |
|
|
|
|
.planPilotSno(pilot.getPlanPilotSno()) |
|
|
|
|
.pilotNm(pilot.getPilotNm()) |
|
|
|
|
.birthDate(pilot.getBirthDate()) |
|
|
|
|
.crtfctNo(pilot.getCrtfctNo()) |
|
|
|
|
.build(); |
|
|
|
|
}).collect(Collectors.toList()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BasDosPlanRs basRs = BasDosPlanRs.builder() |
|
|
|
|
.planSno(bas.getPlanSno()) |
|
|
|
|
.applyNo(bas.getApplyNo()) |
|
|
|
|
.applyDt(applyDt) |
|
|
|
|
.applyDtMonth(applyDtMonth) |
|
|
|
|
.applyDtDay(applyDtDay) |
|
|
|
|
.applyNm(bas.getApplyNm()) |
|
|
|
|
.schFltStDt(bas.getSchFltStDt()) |
|
|
|
|
.schFltEndDt(bas.getSchFltEndDt()) |
|
|
|
|
.purpose(purpose) |
|
|
|
|
.updateDt(bas.getUpdateDt()) |
|
|
|
|
.createDt(bas.getCreateDt()) |
|
|
|
|
.areaList(areaRsList) |
|
|
|
|
.droneList(droneList) |
|
|
|
|
.pilotList(pilotList) |
|
|
|
|
.build(); |
|
|
|
|
rs.add(basRs); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SearchBasDosPlanRS result = new SearchBasDosPlanRS(); |
|
|
|
|
result.setContent(rs); |
|
|
|
|
result.setPagination(pagination); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* List 노드객체의 컬럼중 하나를 Key값으로 잡아 Map을 만듬 |
|
|
|
|
* EX -> PlanBas의 planSno를 키값으로 잡아 Map<planSno, PlanBas> 형태로 변환 |
|
|
|
|
* @param list Map으로 바꿀 리스트 |
|
|
|
|
* @param fieldName Map의 key가 될 컬럼 이름 |
|
|
|
|
* @param keyType Map의 key가 될 클래스 타입 |
|
|
|
|
* @return |
|
|
|
|
* @param <P> |
|
|
|
|
* @param <B> |
|
|
|
|
* @param <C> |
|
|
|
|
*/ |
|
|
|
|
private <P, B extends List<C>, C> Map<P, C> getConvertMap(B list, String fieldName, Class<P> keyType) { |
|
|
|
|
Map<P, C> result = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
for (C node : list) { |
|
|
|
|
Field field = node.getClass().getDeclaredField(fieldName); |
|
|
|
|
field.setAccessible(true); // private 필드 접근 허용
|
|
|
|
|
|
|
|
|
|
P key = keyType.cast(field.get(node)); |
|
|
|
|
|
|
|
|
|
result.put(key, node); |
|
|
|
|
} |
|
|
|
|
} catch (IllegalAccessException | NoSuchFieldException | SecurityException e) { |
|
|
|
|
log.error("", e); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|