feature/flight #9

Open
lkd9125 wants to merge 33 commits from feature/flight into develop
  1. 1
      app/kac-app/build.gradle
  2. 153
      app/kac-app/src/docs/asciidoc/index.adoc
  3. 3618
      app/kac-app/src/main/resources/static/docs/index.html
  4. 16
      app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java
  5. 653
      app/kac-app/src/test/java/kr/co/palnet/kac/flt/laanc/FlightLaancControllerTest.java
  6. 255
      app/kac-app/src/test/java/kr/co/palnet/kac/flt/plan/FlightPlanControllerTest.java
  7. 1
      app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java
  8. 8
      build.gradle
  9. 8
      common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseErrorCode.java
  10. 6
      data/com/src/main/java/kr/co/palnet/kac/data/com/domain/ComConfirmBas.java
  11. 6
      data/com/src/main/java/kr/co/palnet/kac/data/com/domain/ComFileBas.java
  12. 4
      data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComConfirmBasRepository.java
  13. 11
      data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComFileBasRepository.java
  14. 30
      data/com/src/main/java/kr/co/palnet/kac/data/com/service/ComConfirmDomainService.java
  15. 42
      data/com/src/main/java/kr/co/palnet/kac/data/com/service/ComFileDomainService.java
  16. 14
      data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/CtrCntrlBas.java
  17. 2
      data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/CtrCntrlHstryArea.java
  18. 20
      data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/join/CntrlJoinHstryAreaModel.java
  19. 83
      data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/repository/CtrCntrlBasQueryRepository.java
  20. 35
      data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/service/CtrCntrlDomainService.java
  21. 8
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanArcrft.java
  22. 8
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanArea.java
  23. 4
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanAreaCoord.java
  24. 20
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanBas.java
  25. 4
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanCtrCntrlRel.java
  26. 6
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanPilot.java
  27. 21
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/join/FltPlanBasJoinAreaModel.java
  28. 7
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanArcrftRepository.java
  29. 9
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanAreaRepository.java
  30. 6
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanBasRepository.java
  31. 81
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanQueryRepository.java
  32. 84
      data/flt/src/main/java/kr/co/palnet/kac/data/flt/service/FltPlanDomainService.java
  33. 19
      data/other/src/main/java/kr/co/palnet/kac/data/other/service/OtherDomainService.java
  34. 4
      data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java
  35. 14
      data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java
  36. 6
      data/user/build.gradle
  37. 44
      web/api-flight/build.gradle
  38. 27
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/ComnSmsLaancAprovModel.java
  39. 16
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/CtrTrnsLctnModel.java
  40. 28
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/TsQRcodeRQ.java
  41. 92
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/ComnSmsService.java
  42. 134
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/CtrTrnsLctnService.java
  43. 44
      web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/TsService.java
  44. 284
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/AirspaceUtils.java
  45. 344
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/AreaUtils.java
  46. 34
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/DateUtils.java
  47. 108
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/FileUtils.java
  48. 35
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/HttpUtils.java
  49. 165
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/PdfUtils.java
  50. 40
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/constant/ExtensionConstant.java
  51. 22
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/FlightPlanAreaCoordModel.java
  52. 61
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/LaancPdfModel.java
  53. 16
      web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/PdfBaseModel.java
  54. 104
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/controller/FlightLaancController.java
  55. 21
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/ComConfirmBasDTO.java
  56. 45
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/ComFileBasDTO.java
  57. 113
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanArcrftDTO.java
  58. 43
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanAreaCoordDTO.java
  59. 60
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanAreaDTO.java
  60. 119
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanBasDTO.java
  61. 87
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanPilotDTO.java
  62. 38
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/PtyTermsAgreeTxnDTO.java
  63. 127
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/SuredataEntityDTO.java
  64. 31
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/ArcrftTypeCd.java
  65. 34
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/ArcrftWghtCd.java
  66. 38
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltMethod.java
  67. 44
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltPurpose.java
  68. 30
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltType.java
  69. 13
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/AnctCstmrTermsModel.java
  70. 144
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancArcrftModel.java
  71. 44
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancAreaCoordModel.java
  72. 76
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancAreaModel.java
  73. 53
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CreateLaancPlanRQ.java
  74. 17
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CreateLaancPlanRS.java
  75. 73
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CstmrModel.java
  76. 138
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/detail/SearchLaancAprvDetailRS.java
  77. 18
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/pliotvalid/PilotValidRq.java
  78. 29
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/pliotvalid/PilotValidRs.java
  79. 17
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/FileModel.java
  80. 28
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/SearchLaancAprvRQ.java
  81. 140
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/SearchLaancAprvRS.java
  82. 18
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/tsqr/LaancTsQRcodeRQ.java
  83. 17
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/tsqr/LaancTsQRcodeRS.java
  84. 11
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAllowableElevationRS.java
  85. 21
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaByAirspaceModel.java
  86. 19
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaByElevModel.java
  87. 14
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaCoordModel.java
  88. 15
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancDuplicatedAirspaceRs.java
  89. 681
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/service/FlightLaancService.java
  90. 42
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/controller/FlightPlanController.java
  91. 55
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/CtrCntrlBasDTO.java
  92. 57
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/buffer/BufferAreaCoordModel.java
  93. 58
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/buffer/CreateBufferModel.java
  94. 23
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/schedule/SearchPlanScheduleRS.java
  95. 109
      web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/service/FlightPlanService.java
  96. 12524
      web/api-flight/src/main/resources/air/airgeo.json
  97. 25326
      web/api-flight/src/main/resources/air/elev2d/airgeo-elev.json
  98. 5547
      web/api-flight/src/main/resources/air/elev2d/gimpo-airport-2d-elev.json
  99. 5891
      web/api-flight/src/main/resources/air/elev2d/gimpo-airport-2d-elev.json.bak
  100. 5
      web/api-flight/src/main/resources/air/sample/airgeo-3d.json
  101. Some files were not shown because too many files have changed in this diff Show More

1
app/kac-app/build.gradle

@ -40,6 +40,7 @@ dependencies {
implementation project(":web:security")
implementation project(":web:api-common")
implementation project(":web:api-user")
implementation project(":web:api-flight")
}
ext {

153
app/kac-app/src/docs/asciidoc/index.adoc

@ -11,7 +11,7 @@ API 문서
:toclevels: 2
:sectlinks:
[[Common-Code-API]]
[[Common-API]]
== Common-Code API
[[Code-All]]
@ -174,7 +174,7 @@ include::{snippets}/com/code/lang/delete/http-response.adoc[]
***
[[User-Account-API]]
[[User-API]]
== User-Account API
=== [User 회원가입]
@ -241,4 +241,153 @@ include::{snippets}/user/account/update/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/user/account/update/http-response.adoc[]
***
[[Flight-API]]
== Flight-Laanc API
=== [Laanc 비행계획서 생성]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/create/plan/http-request.adoc[]
include::{snippets}/flight/laanc/create/plan/request-headers.adoc[]
include::{snippets}/flight/laanc/create/plan/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/create/plan/http-response.adoc[]
include::{snippets}/flight/laanc/create/plan/response-fields.adoc[]
***
=== [TS QR 코드 생성]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/ts/qr/http-request.adoc[]
include::{snippets}/flight/laanc/ts/qr/request-headers.adoc[]
include::{snippets}/flight/laanc/ts/qr/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/ts/qr/http-response.adoc[]
include::{snippets}/flight/laanc/ts/qr/response-fields.adoc[]
***
=== [TS QR 코드 확인]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/ts/qr/confirm/http-request.adoc[]
include::{snippets}/flight/laanc/ts/qr/confirm/request-headers.adoc[]
include::{snippets}/flight/laanc/ts/qr/confirm/path-parameters.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/ts/qr/confirm/http-response.adoc[]
include::{snippets}/flight/laanc/ts/qr/confirm/response-fields.adoc[]
***
=== [공역(금지구역) 체크]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/valid/duplicated/airspace/http-request.adoc[]
include::{snippets}/flight/laanc/valid/duplicated/airspace/request-headers.adoc[]
include::{snippets}/flight/laanc/valid/duplicated/airspace/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/valid/duplicated/airspace/http-response.adoc[]
include::{snippets}/flight/laanc/valid/duplicated/airspace/response-fields.adoc[]
***
=== [허용고도 조회]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/valid/elev/http-request.adoc[]
include::{snippets}/flight/laanc/valid/elev/request-headers.adoc[]
include::{snippets}/flight/laanc/valid/elev/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/valid/elev/http-response.adoc[]
include::{snippets}/flight/laanc/valid/elev/response-fields.adoc[]
***
=== [LAANC 승인 목록]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/list/http-request.adoc[]
include::{snippets}/flight/laanc/list/request-headers.adoc[]
include::{snippets}/flight/laanc/list/query-parameters.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/list/http-response.adoc[]
include::{snippets}/flight/laanc/list/response-fields.adoc[]
***
=== [LAANC 승인 상세 조회]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/laanc/detail/http-request.adoc[]
include::{snippets}/flight/laanc/detail/request-headers.adoc[]
include::{snippets}/flight/laanc/detail/path-parameters.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/laanc/detail/http-response.adoc[]
include::{snippets}/flight/laanc/detail/response-fields.adoc[]
***
== Flight-Plan API
=== [비행 계획서 작성 - 버퍼존 생성]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/plan/area/buffer/http-request.adoc[]
include::{snippets}/flight/plan/area/buffer/request-headers.adoc[]
include::{snippets}/flight/plan/area/buffer/request-fields.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/plan/area/buffer/http-response.adoc[]
include::{snippets}/flight/plan/area/buffer/response-fields.adoc[]
***
=== [비행 운항 스케줄 조회]
==== [HTTP REQUEST INFO]
include::{snippets}/flight/plan/schedule/http-request.adoc[]
include::{snippets}/flight/plan/schedule/request-headers.adoc[]
include::{snippets}/flight/plan/schedule/query-parameters.adoc[]
==== [HTTP RESPONSE INFO]
include::{snippets}/flight/plan/schedule/http-response.adoc[]
include::{snippets}/flight/plan/schedule/response-fields.adoc[]
***

3618
app/kac-app/src/main/resources/static/docs/index.html

File diff suppressed because it is too large Load Diff

16
app/kac-app/src/test/java/kr/co/palnet/kac/BaseTest.java

@ -1,15 +1,12 @@
package kr.co.palnet.kac;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import kr.co.palnet.kac.api.v1.user.account.model.detail.SearchUserRS;
import kr.co.palnet.kac.api.v1.user.account.model.register.FormRegisterRQ;
import kr.co.palnet.kac.api.v1.user.account.service.UserAccountService;
import kr.co.palnet.kac.app.KacAppApplication;
import kr.co.palnet.kac.config.security.model.BaseUserDetails;
import kr.co.palnet.kac.config.security.service.BaseUserDetailsService;
import kr.co.palnet.kac.config.security.util.JwtUtil;
import kr.co.palnet.kac.util.ObjectMapperUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -18,8 +15,9 @@ import org.springframework.mock.web.MockFilterConfig;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.BeanIds;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@ -27,7 +25,6 @@ import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
@ -47,6 +44,8 @@ public class BaseTest {
public MockMvc mockMvc;
protected String CREATE_USERNAME;
protected final String CREATE_PASSWORD = "palnet!234";
@BeforeEach
@ -73,6 +72,7 @@ public class BaseTest {
protected String getUserToken(){
String username = "TEST_" + System.currentTimeMillis();
this.CREATE_USERNAME = username;
String jsonRQ = """
{
@ -113,6 +113,12 @@ public class BaseTest {
BaseUserDetails userDetails = (BaseUserDetails) baseUserDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
SecurityContextHolder.getContext().setAuthentication(userToken);
return JwtUtil.makeAuthToken(userDetails);
}

653
app/kac-app/src/test/java/kr/co/palnet/kac/flt/laanc/FlightLaancControllerTest.java

@ -0,0 +1,653 @@
package kr.co.palnet.kac.flt.laanc;
import kr.co.palnet.kac.BaseTest;
import kr.co.palnet.kac.api.v1.flight.laanc.model.FltPlanBasDTO;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CreateLaancPlanRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.service.FlightLaancService;
import kr.co.palnet.kac.config.security.util.SessionHelper;
import kr.co.palnet.kac.util.ObjectMapperUtils;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.restdocs.headers.HeaderDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.transaction.annotation.Transactional;
import java.util.UUID;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class FlightLaancControllerTest extends BaseTest {
@Autowired
private FlightLaancService flightLaancService;
private final String BASE_URL = "/v1/flight/laanc";
private final String GRANT_TYPE = "Bearer";
@DisplayName("LAANC 승인 상세 조회")
@Test
@Transactional
public void getLaancAprvDetail() throws Exception{
String token = this.getUserToken();
String planSno = this.testCreatePlan().getPlanSno().toString();
this.mockMvc.perform(
RestDocumentationRequestBuilders.get(this.BASE_URL + "/detail/{planSno}", planSno)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/detail",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
pathParameters(
parameterWithName("planSno").description("비행계획서 일련번호")
),
responseFields(
fieldWithPath("planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호"),
fieldWithPath("groupId").type(JsonFieldType.STRING).description("그룹 아이디"),
fieldWithPath("cstmrSno").type(JsonFieldType.NUMBER).description("작성자 일련번호"),
fieldWithPath("memberName").type(JsonFieldType.STRING).description("작성자 이름"),
fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"),
fieldWithPath("hpno").type(JsonFieldType.STRING).description("연락처"),
fieldWithPath("clncd").type(JsonFieldType.STRING).description("국가번호(연락처)"),
fieldWithPath("addr").type(JsonFieldType.STRING).description("주소").optional(),
fieldWithPath("addrDtlCn").type(JsonFieldType.STRING).description("상세주소").optional(),
fieldWithPath("zip").type(JsonFieldType.STRING).description("우편번호").optional(),
fieldWithPath("schFltStDt").type(JsonFieldType.STRING).description("비행시작일시"),
fieldWithPath("schFltEndDt").type(JsonFieldType.STRING).description("비행종료일시"),
fieldWithPath("fltPurpose").type(JsonFieldType.STRING).description("비행목적"),
fieldWithPath("fltType").type(JsonFieldType.STRING).description("상업/비사업 구분"),
fieldWithPath("fltTypeNm").type(JsonFieldType.STRING).description("상업/비사업 구분 코드"),
fieldWithPath("aprvlYn").type(JsonFieldType.STRING).description("승인여부"),
fieldWithPath("aprvlDt").type(JsonFieldType.STRING).description("승인일자"),
fieldWithPath("fileGroupNo").type(JsonFieldType.NUMBER).description("파일그룹번호"),
fieldWithPath("createUserId").type(JsonFieldType.STRING).description("등록자ID"),
fieldWithPath("createDt").type(JsonFieldType.STRING).description("등록일시"),
fieldWithPath("updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("serviceType").type(JsonFieldType.STRING).description("각 항별 코드"),
fieldWithPath("corpRegYn").type(JsonFieldType.STRING).description("기업여부"),
fieldWithPath("pdfUrl").type(JsonFieldType.STRING).description("공문URL"),
fieldWithPath("areaList").type(JsonFieldType.ARRAY).description("비행구역 리스트"),
fieldWithPath("areaList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행구역 일련번호"),
fieldWithPath("areaList[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호"),
fieldWithPath("areaList[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("areaList[].fltMethod").type(JsonFieldType.STRING).description("비행방식"),
fieldWithPath("areaList[].fltAreaAddr").type(JsonFieldType.STRING).description("비행구역주소"),
fieldWithPath("areaList[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존"),
fieldWithPath("areaList[].fltElev").type(JsonFieldType.STRING).description("고도"),
fieldWithPath("areaList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("areaList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("areaList[].updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("areaList[].updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("areaList[].docState").type(JsonFieldType.STRING).description("코드"),
fieldWithPath("areaList[].bufferCoordList").type(JsonFieldType.ARRAY).description("비행 버퍼 좌표리스트").optional(),
fieldWithPath("areaList[].fltMothoeRm").type(JsonFieldType.STRING).description("비행방식(기타)"),
fieldWithPath("areaList[].coordList").type(JsonFieldType.ARRAY).description("비행구역 좌표리스트").optional(),
fieldWithPath("areaList[].coordList[].planAreaCoordSno").type(JsonFieldType.NUMBER).description("비행구역좌표 일련번호"),
fieldWithPath("areaList[].coordList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행계획비행구역 일련번호"),
fieldWithPath("areaList[].coordList[].lat").type(JsonFieldType.NUMBER).description("위도"),
fieldWithPath("areaList[].coordList[].lon").type(JsonFieldType.NUMBER).description("경"),
fieldWithPath("areaList[].coordList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("areaList[].coordList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("areaList[].coordList[].docState").type(JsonFieldType.STRING).description("코드"),
fieldWithPath("arcrftList").type(JsonFieldType.ARRAY).description("비행기체 리스트"),
fieldWithPath("arcrftList[].planArcrftSno").type(JsonFieldType.NUMBER).description("계획서 기체 일련번호"),
fieldWithPath("arcrftList[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호"),
fieldWithPath("arcrftList[].arcrftSno").type(JsonFieldType.NUMBER).description("기체 일련번호").optional(),
fieldWithPath("arcrftList[].idntfNum").type(JsonFieldType.STRING).description("식별번호(기체번호)"),
fieldWithPath("arcrftList[].groupNm").type(JsonFieldType.STRING).description("그룹명"),
fieldWithPath("arcrftList[].prdctNum").type(JsonFieldType.STRING).description("제작번호"),
fieldWithPath("arcrftList[].arcrftTypeCd").type(JsonFieldType.STRING).description("기체종류코드"),
fieldWithPath("arcrftList[].arcrftModelNm").type(JsonFieldType.STRING).description("기체모델명"),
fieldWithPath("arcrftList[].prdctCmpnNm").type(JsonFieldType.STRING).description("제작자"),
fieldWithPath("arcrftList[].prdctDate").type(JsonFieldType.STRING).description("제작일자").optional(),
fieldWithPath("arcrftList[].arcrftLngth").type(JsonFieldType.NUMBER).description("기체길이"),
fieldWithPath("arcrftList[].arcrftWdth").type(JsonFieldType.NUMBER).description("길체폭"),
fieldWithPath("arcrftList[].arcrftHght").type(JsonFieldType.NUMBER).description("기체높이"),
fieldWithPath("arcrftList[].arcrftWght").type(JsonFieldType.NUMBER).description("기체중량"),
fieldWithPath("arcrftList[].wghtTypeCd").type(JsonFieldType.STRING).description("중량구분코드"),
fieldWithPath("arcrftList[].imageUrl").type(JsonFieldType.STRING).description("이미지URL"),
fieldWithPath("arcrftList[].takeoffWght").type(JsonFieldType.NUMBER).description("최대이륙중량"),
fieldWithPath("arcrftList[].useYn").type(JsonFieldType.STRING).description("사용여부"),
fieldWithPath("arcrftList[].cameraYn").type(JsonFieldType.STRING).description("카메라탑재여부"),
fieldWithPath("arcrftList[].insrncYn").type(JsonFieldType.STRING).description("보험가입여부"),
fieldWithPath("arcrftList[].ownerNm").type(JsonFieldType.STRING).description("소유자명(법인명)"),
fieldWithPath("arcrftList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("arcrftList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("arcrftList[].updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("arcrftList[].updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("arcrftList[].docState").type(JsonFieldType.STRING).description("코드"),
fieldWithPath("arcrftList[].idntfTypeCd").type(JsonFieldType.STRING).description("식별장치종류코드").optional(),
fieldWithPath("arcrftList[].acrftInsuranceYn").type(JsonFieldType.STRING).description("기체보험유무"),
fieldWithPath("arcrftList[].insuranceExperiod").type(JsonFieldType.STRING).description("보험유효기간").optional(),
fieldWithPath("arcrftList[].corporationNm").type(JsonFieldType.STRING).description("법인명").optional(),
fieldWithPath("arcrftList[].arcrftWghtCd").type(JsonFieldType.STRING).description("자체중량코드"),
fieldWithPath("pilotList").type(JsonFieldType.ARRAY).description("조종자 정보 리스트").optional(),
fieldWithPath("pilotList[].planPilotSno").type(JsonFieldType.NUMBER).description("조종자 일련번호"),
fieldWithPath("pilotList[].planSno").type(JsonFieldType.NUMBER).description("비행계획서일련번호"),
fieldWithPath("pilotList[].cstmrSno").type(JsonFieldType.NUMBER).description("고객일련번호"),
fieldWithPath("pilotList[].groupNm").type(JsonFieldType.STRING).description("그룹명"),
fieldWithPath("pilotList[].memberName").type(JsonFieldType.STRING).description("회원이름"),
fieldWithPath("pilotList[].email").type(JsonFieldType.STRING).description("이메일"),
fieldWithPath("pilotList[].hpno").type(JsonFieldType.STRING).description("휴대폰번"),
fieldWithPath("pilotList[].clncd").type(JsonFieldType.STRING).description("국가전화번호"),
fieldWithPath("pilotList[].addr").type(JsonFieldType.STRING).description("주소").optional(),
fieldWithPath("pilotList[].addrDtlCn").type(JsonFieldType.STRING).description("주소 상세내용").optional(),
fieldWithPath("pilotList[].zip").type(JsonFieldType.STRING).description("우편번호").optional(),
fieldWithPath("pilotList[].qlfcNo").type(JsonFieldType.STRING).description("자격번호").optional(),
fieldWithPath("pilotList[].carrer").type(JsonFieldType.STRING).description("경력").optional(),
fieldWithPath("pilotList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("pilotList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("pilotList[].updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("pilotList[].updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("arcrftWght").type(JsonFieldType.STRING).description("기체 중량설명"),
fieldWithPath("elev").type(JsonFieldType.STRING).description("비행고도")
)
)
)
.andExpect(status().isOk());
}
@DisplayName("LAANC 승인 목록")
@Test
@Transactional
public void getLaancAprvList() throws Exception{
// TODO::TEST로 만들 비행계획서 필요함
String token = this.getUserToken();
FltPlanBasDTO fltPlanBasDto = this.testCreatePlan();
String createStDate = fltPlanBasDto.getCreateDt().toLocalDate().minusDays(1).toString();
String createEndDate = fltPlanBasDto.getCreateDt().toLocalDate().plusDays(1).toString();
this.mockMvc.perform(
get(this.BASE_URL + "/list")
.param("createStDate",createStDate)
.param("createEndDate",createEndDate)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/list",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
queryParameters(
parameterWithName("createStDate").description("검색 시작일").optional(),
parameterWithName("createEndDate").description("검색 끝일").optional(),
parameterWithName("memberName").description("이름").optional()
),
responseFields(
fieldWithPath("[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호").optional(),
fieldWithPath("[].groupId").type(JsonFieldType.STRING).description("그룹 아이디").optional(),
fieldWithPath("[].cstmrSno").type(JsonFieldType.NUMBER).description("작성자 일련번호").optional(),
fieldWithPath("[].memberName").type(JsonFieldType.STRING).description("작성자 이름").optional(),
fieldWithPath("[].email").type(JsonFieldType.STRING).description("이메일").optional(),
fieldWithPath("[].hpno").type(JsonFieldType.STRING).description("연락처").optional(),
fieldWithPath("[].clncd").type(JsonFieldType.STRING).description("국가번호(연락처)").optional(),
fieldWithPath("[].addr").type(JsonFieldType.STRING).description("주소").optional(),
fieldWithPath("[].addrDtlCn").type(JsonFieldType.STRING).description("상세주소").optional(),
fieldWithPath("[].zip").type(JsonFieldType.STRING).description("우편번호").optional(),
fieldWithPath("[].schFltStDt").type(JsonFieldType.STRING).description("비행시작일시").optional(),
fieldWithPath("[].schFltEndDt").type(JsonFieldType.STRING).description("비행종료일시").optional(),
fieldWithPath("[].fltPurpose").type(JsonFieldType.STRING).description("비행목적").optional(),
fieldWithPath("[].fltType").type(JsonFieldType.STRING).description("상업/비사업 구분").optional(),
fieldWithPath("[].fltTypeNm").type(JsonFieldType.STRING).description("상업/비사업 구분 코드").optional(),
fieldWithPath("[].aprvlYn").type(JsonFieldType.STRING).description("승인여부").optional(),
fieldWithPath("[].aprvlDt").type(JsonFieldType.STRING).description("승인일자").optional(),
fieldWithPath("[].fileGroupNo").type(JsonFieldType.NUMBER).description("파일그룹번호").optional(),
fieldWithPath("[].createUserId").type(JsonFieldType.STRING).description("등록자ID").optional(),
fieldWithPath("[].createDt").type(JsonFieldType.STRING).description("등록일시").optional(),
fieldWithPath("[].updateUserId").type(JsonFieldType.STRING).description("수정자ID").optional(),
fieldWithPath("[].updateDt").type(JsonFieldType.STRING).description("수정일시").optional(),
fieldWithPath("[].serviceType").type(JsonFieldType.STRING).description("각 항별 코드").optional(),
fieldWithPath("[].corpRegYn").type(JsonFieldType.STRING).description("기업여부").optional(),
fieldWithPath("[].pdfUrl").type(JsonFieldType.STRING).description("공문URL").optional(),
fieldWithPath("[].areaList").type(JsonFieldType.ARRAY).description("비행구역 리스트").optional(),
fieldWithPath("[].areaList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행구역 일련번호"),
fieldWithPath("[].areaList[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호"),
fieldWithPath("[].areaList[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].areaList[].fltMethod").type(JsonFieldType.STRING).description("비행방식"),
fieldWithPath("[].areaList[].fltAreaAddr").type(JsonFieldType.STRING).description("비행구역주소"),
fieldWithPath("[].areaList[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존"),
fieldWithPath("[].areaList[].fltElev").type(JsonFieldType.STRING).description("고도"),
fieldWithPath("[].areaList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("[].areaList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("[].areaList[].updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("[].areaList[].updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("[].areaList[].docState").type(JsonFieldType.STRING).description("코드"),
fieldWithPath("[].areaList[].coordList").type(JsonFieldType.ARRAY).description("비행구역 좌표리스트").optional(),
fieldWithPath("[].areaList[].bufferCoordList").type(JsonFieldType.ARRAY).description("비행 버퍼 좌표리스트").optional(),
fieldWithPath("[].areaList[].fltMothoeRm").type(JsonFieldType.STRING).description("비행방식(기타)"),
fieldWithPath("[].arcrftList").type(JsonFieldType.ARRAY).description("비행기체 리스트").optional(),
fieldWithPath("[].arcrftList[].planArcrftSno").type(JsonFieldType.NUMBER).description("계획서 기체 일련번호"),
fieldWithPath("[].arcrftList[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호"),
fieldWithPath("[].arcrftList[].arcrftSno").type(JsonFieldType.NUMBER).description("기체 일련번호").optional(),
fieldWithPath("[].arcrftList[].idntfNum").type(JsonFieldType.STRING).description("식별번호(기체번호)"),
fieldWithPath("[].arcrftList[].groupNm").type(JsonFieldType.STRING).description("그룹명"),
fieldWithPath("[].arcrftList[].prdctNum").type(JsonFieldType.STRING).description("제작번호"),
fieldWithPath("[].arcrftList[].arcrftTypeCd").type(JsonFieldType.STRING).description("기체종류코드"),
fieldWithPath("[].arcrftList[].arcrftModelNm").type(JsonFieldType.STRING).description("기체모델명"),
fieldWithPath("[].arcrftList[].prdctCmpnNm").type(JsonFieldType.STRING).description("제작자"),
fieldWithPath("[].arcrftList[].prdctDate").type(JsonFieldType.STRING).description("제작일자").optional(),
fieldWithPath("[].arcrftList[].arcrftLngth").type(JsonFieldType.NUMBER).description("기체길이"),
fieldWithPath("[].arcrftList[].arcrftWdth").type(JsonFieldType.NUMBER).description("길체폭"),
fieldWithPath("[].arcrftList[].arcrftHght").type(JsonFieldType.NUMBER).description("기체높이"),
fieldWithPath("[].arcrftList[].arcrftWght").type(JsonFieldType.NUMBER).description("기체중량"),
fieldWithPath("[].arcrftList[].wghtTypeCd").type(JsonFieldType.STRING).description("중량구분코드"),
fieldWithPath("[].arcrftList[].imageUrl").type(JsonFieldType.STRING).description("이미지URL"),
fieldWithPath("[].arcrftList[].takeoffWght").type(JsonFieldType.NUMBER).description("최대이륙중량"),
fieldWithPath("[].arcrftList[].useYn").type(JsonFieldType.STRING).description("사용여부"),
fieldWithPath("[].arcrftList[].cameraYn").type(JsonFieldType.STRING).description("카메라탑재여부"),
fieldWithPath("[].arcrftList[].insrncYn").type(JsonFieldType.STRING).description("보험가입여부"),
fieldWithPath("[].arcrftList[].ownerNm").type(JsonFieldType.STRING).description("소유자명(법인명)"),
fieldWithPath("[].arcrftList[].createUserId").type(JsonFieldType.STRING).description("생성자ID"),
fieldWithPath("[].arcrftList[].createDt").type(JsonFieldType.STRING).description("생성일시"),
fieldWithPath("[].arcrftList[].updateUserId").type(JsonFieldType.STRING).description("수정자ID"),
fieldWithPath("[].arcrftList[].updateDt").type(JsonFieldType.STRING).description("수정일시"),
fieldWithPath("[].arcrftList[].docState").type(JsonFieldType.STRING).description("코드"),
fieldWithPath("[].arcrftList[].idntfTypeCd").type(JsonFieldType.STRING).description("식별장치종류코드").optional(),
fieldWithPath("[].arcrftList[].acrftInsuranceYn").type(JsonFieldType.STRING).description("기체보험유무"),
fieldWithPath("[].arcrftList[].insuranceExperiod").type(JsonFieldType.STRING).description("보험유효기간").optional(),
fieldWithPath("[].arcrftList[].corporationNm").type(JsonFieldType.STRING).description("법인명").optional(),
fieldWithPath("[].arcrftList[].arcrftWghtCd").type(JsonFieldType.STRING).description("자체중량코드"),
fieldWithPath("[].pilotList").type(JsonFieldType.ARRAY).description("공문URL").optional(),
fieldWithPath("[].arcrftWght").type(JsonFieldType.STRING).description("기체 중량설명").optional(),
fieldWithPath("[].elev").type(JsonFieldType.STRING).description("비행고도").optional()
)
)
)
.andExpect(status().isOk());
}
@DisplayName("허용고도 조회")
@Test
@Transactional
public void getAllowableElevation() throws Exception{
String jsonRQ = """
[
{
"areaType" : "LINE",
"bufferZone" : 100,
"coordList" : [
{
"lat" : 127.277715,
"lon" : 37.406649
},
{
"lat" : 127.158070,
"lon" : 37.409050
}
]
}
]
""";
String token = this.getUserToken();
this.mockMvc.perform(
post(this.BASE_URL + "/valid/elev")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonRQ)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/valid/elev",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
requestFields(
fieldWithPath("[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존 크기"),
fieldWithPath("[].coordList").type(JsonFieldType.ARRAY).description("비행구역 좌표리스트"),
fieldWithPath("[].coordList[].lat").type(JsonFieldType.NUMBER).description("경도 [ex -> 126.706806]"),
fieldWithPath("[].coordList[].lon").type(JsonFieldType.NUMBER).description("위도 [ex -> 37.50854]")
),
responseFields(
fieldWithPath("allowableElevation").description("비행고도 허용값")
)
)
)
.andExpect(status().isOk());
}
@DisplayName("공역(금지구역) 체크")
@Test
@Transactional
public void getDuplicatedAirspace() throws Exception{
String jsonRQ = """
[
{
"areaType" : "LINE",
"bufferZone" : 100,
"fltElev" : 130,
"coordList" : [
{
"lat" : 126.706806,
"lon" : 37.50854
},
{
"lat" : 126.7108901,
"lon" : 37.5094849
},
{
"lat" : 126.7091884,
"lon" : 37.5068526
}
]
}
]
""";
String token = this.getUserToken();
this.mockMvc.perform(
post(this.BASE_URL + "/valid/duplicated/airspace")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonRQ)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/valid/duplicated/airspace",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
requestFields(
fieldWithPath("[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존 크기"),
fieldWithPath("[].fltElev").type(JsonFieldType.NUMBER).description("비행 고도"),
fieldWithPath("[].coordList").type(JsonFieldType.ARRAY).description("비행구역 좌표리스트"),
fieldWithPath("[].coordList[].lat").type(JsonFieldType.NUMBER).description("경도 [ex -> 126.706806]"),
fieldWithPath("[].coordList[].lon").type(JsonFieldType.NUMBER).description("위도 [ex -> 37.50854]")
),
responseFields(
fieldWithPath("[].rq.areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].rq.bufferZone").type(JsonFieldType.NUMBER).description("버퍼존 크기"),
fieldWithPath("[].rq.fltElev").type(JsonFieldType.STRING).description("비행 고도"),
fieldWithPath("[].rq.coordList").type(JsonFieldType.ARRAY).description("비행구역 좌표리스트"),
fieldWithPath("[].rq.coordList[].lat").type(JsonFieldType.NUMBER).description("경도 [ex -> 126.706806]"),
fieldWithPath("[].rq.coordList[].lon").type(JsonFieldType.NUMBER).description("위도 [ex -> 37.50854]"),
fieldWithPath("[].duplicated").type(JsonFieldType.BOOLEAN).description("공역 체크값")
)
)
)
.andExpect(status().isOk());
}
@DisplayName("TS QR 코드 확인")
@Test
@Transactional
public void checkQrcode() throws Exception{
String token = this.getUserToken();
String confirmKey = UUID.randomUUID().toString();
flightLaancService.testCreateQRCode(confirmKey, this.CREATE_USERNAME);
this.mockMvc.perform(
RestDocumentationRequestBuilders.get(this.BASE_URL + "/ts/qr/{confirmKey}", confirmKey)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/ts/qr/confirm",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
pathParameters(
parameterWithName("confirmKey").description("컨펌키")
),
responseFields(
fieldWithPath("rspCode").type(JsonFieldType.STRING).description("결과코드"),
fieldWithPath("rspMessage").type(JsonFieldType.STRING).description("결과메시지"),
fieldWithPath("pilotcredentialyn").type(JsonFieldType.STRING).description("조종사자격증명여부"),
fieldWithPath("arcrftinsuranceyn").type(JsonFieldType.STRING).description("기체보험가입여부"),
fieldWithPath("arcrftdeclaration").type(JsonFieldType.STRING).description("기체신고여부"),
fieldWithPath("corpregyn").type(JsonFieldType.STRING).description("사업자유무"),
fieldWithPath("rq").type(JsonFieldType.OBJECT).description("QR코드 데이터").optional()
)
)
)
.andExpect(status().isOk());
}
@DisplayName("TS QR 코드 생성")
@Test
@Transactional
public void createQRcode() throws Exception{
String jsonRQ = """
{
"idntfNum" : "C1CM0231251"
}
""";
String token = this.getUserToken();
this.mockMvc.perform(
post(this.BASE_URL + "/ts/qr")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonRQ)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/ts/qr",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
requestFields(
fieldWithPath("idntfNum").type(JsonFieldType.STRING).description("기체 식별번호")
),
responseFields(
fieldWithPath("qrcode").type(JsonFieldType.STRING).description("QR코드 데이터"),
fieldWithPath("confirmKey").type(JsonFieldType.STRING).description("컨펌 키")
)
)
)
.andExpect(status().isCreated());
}
@DisplayName("비행계획서 생성")
@Test
@Transactional
public void createPlan() throws Exception{
String jsonRQ = """
{
"cstmrSno": 3,
"fltType": "COMMERCIAL",
"schFltStDt": "2024-02-25T11:43:00",
"schFltEndDt": "2024-02-28T15:46:00",
"fltPurpose": "06",
"serviceType": "KAC",
"areaList" : [
{
"areaType": "LINE",
"fltMethod": "02",
"fltMothoeRm": "",
"bufferZone": "100",
"fltElev": "100",
"coordList": [
{
"lat": 37.51625845252909,
"lon": 126.72340194011286
},
{
"lat": 37.512215014051776,
"lon": 126.72058946300956
},
{
"lat": 37.51123897883966,
"lon": 126.72463239884405
}
]
}
],
"arcrftList" : [
{
"idntfNum": "PA0001",
"groupNm": "",
"prdctNum": "",
"arcrftTypeCd": "11",
"arcrftModelNm": "",
"prdctCmpnNm": "",
"prdctDate": "",
"arcrftLngth": 0,
"arcrftWghtCd": "8",
"arcrftHght": 0,
"arcrftWght": 0,
"wghtTypeCd": "",
"imageUrl": "",
"takeoffWght": 0,
"useYn": "",
"cameraYn": "",
"insrncYn": "",
"ownerNm": ""
}
],
"terms": [
]
}
""";
String token = this.getUserToken();
this.mockMvc.perform(
post(this.BASE_URL + "/create/plan")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonRQ)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/laanc/create/plan",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
requestFields(
fieldWithPath("cstmrSno").type(JsonFieldType.NUMBER).description("회원 고유번호").optional(),
fieldWithPath("fltType").type(JsonFieldType.STRING).description("비행유형 - 상업/비상업"),
fieldWithPath("schFltStDt").type(JsonFieldType.STRING).description("비행시작일시"),
fieldWithPath("schFltEndDt").type(JsonFieldType.STRING).description("비행종료일시"),
fieldWithPath("fltPurpose").type(JsonFieldType.STRING).description("비행목적"),
fieldWithPath("serviceType").type(JsonFieldType.STRING).description("각 청들 코드"),
fieldWithPath("areaList").type(JsonFieldType.ARRAY).description("비행구역 리스트"),
fieldWithPath("areaList[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("areaList[].fltMethod").type(JsonFieldType.STRING).description("비행방식"),
fieldWithPath("areaList[].fltMothoeRm").type(JsonFieldType.STRING).description("비행방식(기타)").optional(),
fieldWithPath("areaList[].bufferZone").type(JsonFieldType.STRING).description("버퍼존"),
fieldWithPath("areaList[].fltElev").type(JsonFieldType.STRING).description("비행고도"),
fieldWithPath("areaList[].coordList").type(JsonFieldType.ARRAY).description("비행 좌표 리스트"),
fieldWithPath("areaList[].coordList[].lat").type(JsonFieldType.NUMBER).description("위도"),
fieldWithPath("areaList[].coordList[].lon").type(JsonFieldType.NUMBER).description("경도"),
fieldWithPath("arcrftList").type(JsonFieldType.ARRAY).description("비행기체 정보리스트"),
fieldWithPath("arcrftList[].idntfNum").type(JsonFieldType.STRING).description("식별번호(기체번호)"),
fieldWithPath("arcrftList[].groupNm").type(JsonFieldType.STRING).description("그룹명").optional(),
fieldWithPath("arcrftList[].prdctNum").type(JsonFieldType.STRING).description("제작번호").optional(),
fieldWithPath("arcrftList[].arcrftTypeCd").type(JsonFieldType.STRING).description("기체종류코드"),
fieldWithPath("arcrftList[].arcrftModelNm").type(JsonFieldType.STRING).description("기체모델명").optional(),
fieldWithPath("arcrftList[].prdctCmpnNm").type(JsonFieldType.STRING).description("제작자").optional(),
fieldWithPath("arcrftList[].prdctDate").type(JsonFieldType.STRING).description("제작일자").optional(),
fieldWithPath("arcrftList[].arcrftLngth").type(JsonFieldType.NUMBER).description("기체길이").optional(),
fieldWithPath("arcrftList[].arcrftWghtCd").type(JsonFieldType.STRING).description("자체중량코드"),
fieldWithPath("arcrftList[].arcrftHght").type(JsonFieldType.NUMBER).description("기체높이").optional(),
fieldWithPath("arcrftList[].arcrftWght").type(JsonFieldType.NUMBER).description("기체중량").optional(),
fieldWithPath("arcrftList[].wghtTypeCd").type(JsonFieldType.STRING).description("중량구분코드").optional(),
fieldWithPath("arcrftList[].imageUrl").type(JsonFieldType.STRING).description("이미지URL").optional(),
fieldWithPath("arcrftList[].takeoffWght").type(JsonFieldType.NUMBER).description("최대이륙중량").optional(),
fieldWithPath("arcrftList[].useYn").type(JsonFieldType.STRING).description("사용여부").optional(),
fieldWithPath("arcrftList[].cameraYn").type(JsonFieldType.STRING).description("카메라탑재여부").optional(),
fieldWithPath("arcrftList[].insrncYn").type(JsonFieldType.STRING).description("보험가입여부").optional(),
fieldWithPath("arcrftList[].ownerNm").type(JsonFieldType.STRING).description("소유자명(법인명)").optional(),
fieldWithPath("terms").type(JsonFieldType.ARRAY).description("약관동의리스트").optional(),
fieldWithPath("terms[].termsSno").type(JsonFieldType.NUMBER).description("약관 일련번호").optional(),
fieldWithPath("terms[].agressYn").type(JsonFieldType.STRING).description("동의 여부").optional()
),
responseFields(
fieldWithPath("pdfUrl").type(JsonFieldType.STRING).description("PDF 다운로드 URL").optional(),
fieldWithPath("address").type(JsonFieldType.STRING).description("주소").optional()
)
)
)
.andExpect(status().isCreated());
}
private FltPlanBasDTO testCreatePlan(){
String jsonRQ = "{\"cstmrSno\": 3,\"fltType\": \"COMMERCIAL\",\"schFltStDt\": \"2024-02-21T11:43:00\",\"schFltEndDt\": \"2024-02-22T15:46:00\",\"fltPurpose\": \"06\",\"serviceType\": \"KAC\",\"areaList\" : [{\"areaType\": \"LINE\",\"fltMethod\": \"02\",\"fltMothoeRm\": \"\",\"bufferZone\": \"100\",\"fltElev\": \"100\",\"coordList\": [{\"lat\": 37.51625845252909,\"lon\": 126.72340194011286},{\"lat\": 37.512215014051776,\"lon\": 126.72058946300956},{\"lat\": 37.51123897883966,\"lon\": 126.72463239884405}]}],\"arcrftList\" : [{\"idntfNum\": \"PA0001\",\"groupNm\": \"\",\"prdctNum\": \"\",\"arcrftTypeCd\": \"11\",\"arcrftModelNm\": \"\",\"prdctCmpnNm\": \"\",\"prdctDate\": \"\",\"arcrftLngth\": 0,\"arcrftWghtCd\": \"8\",\"arcrftHght\": 0,\"arcrftWght\": 0,\"wghtTypeCd\": \"\",\"imageUrl\": \"\",\"takeoffWght\": 0,\"useYn\": \"\",\"cameraYn\": \"\",\"insrncYn\": \"\",\"ownerNm\": \"\"}],\"terms\": []}".trim();
CreateLaancPlanRQ rq;
try{
rq = ObjectMapperUtils.getObjectMapper().readValue(jsonRQ, CreateLaancPlanRQ.class);
flightLaancService.createPlan(rq);
} catch (Exception e){
e.printStackTrace();
}
return flightLaancService.testDescPlanSno();
}
}

255
app/kac-app/src/test/java/kr/co/palnet/kac/flt/plan/FlightPlanControllerTest.java

@ -0,0 +1,255 @@
package kr.co.palnet.kac.flt.plan;
import kr.co.palnet.kac.BaseTest;
import kr.co.palnet.kac.api.v1.flight.laanc.model.FltPlanBasDTO;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CreateLaancPlanRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.service.FlightLaancService;
import kr.co.palnet.kac.api.v1.flight.plan.model.CtrCntrlBasDTO;
import kr.co.palnet.kac.api.v1.flight.plan.service.FlightPlanService;
import kr.co.palnet.kac.util.ObjectMapperUtils;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.restdocs.headers.HeaderDocumentation;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.restdocs.request.RequestDocumentation.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
public class FlightPlanControllerTest extends BaseTest {
@Autowired
private FlightLaancService flightLaancService;
@Autowired
private FlightPlanService flightPlanService;
private final String BASE_URL = "/v1/flight/plan";
private final String GRANT_TYPE = "Bearer";
@DisplayName("비행 운항 스케줄 조회")
@Test
@Transactional
public void getPlanSchedule() throws Exception{
String token = this.getUserToken();
LocalDate searchDate = LocalDate.now().plusDays(2);
this.testCreateData(searchDate);
this.mockMvc.perform(
get(this.BASE_URL + "/schedule")
.param("searchDate", searchDate.toString())
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/plan/schedule",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
queryParameters(
parameterWithName("searchDate").description("검색일자")
),
responseFields(
fieldWithPath("[].groupId").type(JsonFieldType.STRING).description("그룹아이디").optional(),
fieldWithPath("[].groupNm").type(JsonFieldType.STRING).description("그룹 명").optional(),
fieldWithPath("[].ownerNm").type(JsonFieldType.STRING).description("기체 소유자 이름").optional(),
fieldWithPath("[].idntfNum").type(JsonFieldType.STRING).description("기체 식별번호"),
fieldWithPath("[].startAddress").type(JsonFieldType.STRING).description("비행시작 주소").optional(),
fieldWithPath("[].endAddress").type(JsonFieldType.STRING).description("비행종료 주소").optional(),
fieldWithPath("[].schFltStDt").type(JsonFieldType.STRING).description("비행계획서 시작일").optional(),
fieldWithPath("[].schFltEndDt").type(JsonFieldType.STRING).description("비행계획서 종료일").optional(),
fieldWithPath("[].cntrlId").type(JsonFieldType.STRING).description("관제ID"),
fieldWithPath("[].cntrlStDt").type(JsonFieldType.STRING).description("비행 시작시간"),
fieldWithPath("[].cntrlEndDt").type(JsonFieldType.STRING).description("비행 종료시간"),
fieldWithPath("[].statusCd").type(JsonFieldType.STRING).description("스테이터스").optional()
)
)
)
.andExpect(status().isOk());
}
@DisplayName("비행 계획서 작성 - 버퍼존 생성")
@Test
@Transactional
public void createBuffer() throws Exception{
String token = this.getUserToken();
String jsonRQ = """
[
{
"planAreaSno": 0,
"planSno": 0,
"areaType": "LINE",
"fltMethod": "",
"fltMothoeRm": "",
"bufferZone": 100,
"fltElev": 0,
"createUserId": "",
"createDt": "",
"updateUserId": "",
"updateDt": "",
"coordList": [
{
"planAreaCoordSno": 0,
"planAreaSno": 0,
"lat": 37.53540376761919,
"lon": 126.70505084176824,
"createUserId": "",
"createDt": ""
},
{
"planAreaCoordSno": 0,
"planAreaSno": 0,
"lat": 37.53254793498979,
"lon": 126.71167265598018,
"createUserId": "",
"createDt": ""
}
]
}
]
""";
this.mockMvc.perform(
post(this.BASE_URL + "/area/buffer")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(jsonRQ)
.accept(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", GRANT_TYPE + " " + token)
)
.andDo(print())
.andDo(
document(
"flight/plan/area/buffer",
preprocessResponse(prettyPrint()),
HeaderDocumentation.requestHeaders(
HeaderDocumentation.headerWithName("Authorization").description("Access토큰 [로그인 발급]")
),
requestFields(
fieldWithPath("[].planAreaSno").type(JsonFieldType.NUMBER).description("비행구역 일련번호").optional(),
fieldWithPath("[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호").optional(),
fieldWithPath("[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].fltMethod").type(JsonFieldType.STRING).description("비행방식").optional(),
fieldWithPath("[].fltMothoeRm").type(JsonFieldType.STRING).description("비행방식(기타)").optional(),
fieldWithPath("[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존"),
fieldWithPath("[].fltElev").type(JsonFieldType.NUMBER).description("비행고도").optional(),
fieldWithPath("[].createUserId").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].createDt").type(JsonFieldType.STRING).description("생성일시").optional(),
fieldWithPath("[].updateUserId").type(JsonFieldType.STRING).description("수정자ID").optional(),
fieldWithPath("[].updateDt").type(JsonFieldType.STRING).description("수정일시").optional(),
fieldWithPath("[].coordList").type(JsonFieldType.ARRAY).description("좌표리스트"),
fieldWithPath("[].coordList[].planAreaCoordSno").type(JsonFieldType.NUMBER).description("비행구역좌표 일련번호").optional(),
fieldWithPath("[].coordList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행계획비행구역 일련번호").optional(),
fieldWithPath("[].coordList[].lat").type(JsonFieldType.NUMBER).description("위도 [ ex -> 37.53540376761919 ] "),
fieldWithPath("[].coordList[].lon").type(JsonFieldType.NUMBER).description("경도 [ ex -> 126.70505084176824 ]"),
fieldWithPath("[].coordList[].createUserId").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].coordList[].createDt").type(JsonFieldType.STRING).description("생성일시").optional()
),
responseFields(
fieldWithPath("[].planAreaSno").type(JsonFieldType.NUMBER).description("비행구역 일련번호").optional(),
fieldWithPath("[].planSno").type(JsonFieldType.NUMBER).description("비행계획서 일련번호").optional(),
fieldWithPath("[].areaType").type(JsonFieldType.STRING).description("비행구역 생성타입"),
fieldWithPath("[].fltMethod").type(JsonFieldType.STRING).description("비행방식").optional(),
fieldWithPath("[].fltAreaAddr").type(JsonFieldType.STRING).description("비행지역주소").optional(),
fieldWithPath("[].fltMothoeRm").type(JsonFieldType.STRING).description("비행방식(기타)").optional(),
fieldWithPath("[].bufferZone").type(JsonFieldType.NUMBER).description("버퍼존"),
fieldWithPath("[].fltElev").type(JsonFieldType.STRING).description("비행고도").optional(),
fieldWithPath("[].createUserId").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].createDt").type(JsonFieldType.STRING).description("생성일시").optional(),
fieldWithPath("[].updateUserId").type(JsonFieldType.STRING).description("수정자ID").optional(),
fieldWithPath("[].updateDt").type(JsonFieldType.STRING).description("수정일시").optional(),
fieldWithPath("[].docState").type(JsonFieldType.STRING).description("코드").optional(),
fieldWithPath("[].bufferCoordList").type(JsonFieldType.ARRAY).description("좌표리스트"),
fieldWithPath("[].bufferCoordList[].planAreaCoordSno").type(JsonFieldType.NUMBER).description("비행구역좌표 일련번호").optional(),
fieldWithPath("[].bufferCoordList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행계획비행구역 일련번호").optional(),
fieldWithPath("[].bufferCoordList[].lat").type(JsonFieldType.NUMBER).description("위도 [ ex -> 37.53540376761919 ] "),
fieldWithPath("[].bufferCoordList[].lon").type(JsonFieldType.NUMBER).description("경도 [ ex -> 126.70505084176824 ]"),
fieldWithPath("[].bufferCoordList[].createUserId").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].bufferCoordList[].createDt").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].bufferCoordList[].docState").type(JsonFieldType.STRING).description("코드").optional(),
fieldWithPath("[].coordList").type(JsonFieldType.ARRAY).description("좌표리스트"),
fieldWithPath("[].coordList[].planAreaCoordSno").type(JsonFieldType.NUMBER).description("비행구역좌표 일련번호").optional(),
fieldWithPath("[].coordList[].planAreaSno").type(JsonFieldType.NUMBER).description("비행계획비행구역 일련번호").optional(),
fieldWithPath("[].coordList[].lat").type(JsonFieldType.NUMBER).description("위도 [ ex -> 37.53540376761919 ] "),
fieldWithPath("[].coordList[].lon").type(JsonFieldType.NUMBER).description("경도 [ ex -> 126.70505084176824 ]"),
fieldWithPath("[].coordList[].createUserId").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].coordList[].createDt").type(JsonFieldType.STRING).description("생성자ID").optional(),
fieldWithPath("[].coordList[].docState").type(JsonFieldType.STRING).description("코드").optional()
)
)
)
.andExpect(status().isOk());
}
private FltPlanBasDTO testCreateData(LocalDate searchData){
LocalDateTime plusOneDay = LocalDateTime.now().plusDays(1);
LocalDateTime plusThreeDay = LocalDateTime.now().plusDays(3);
String jsonRQ = "{\"cstmrSno\": 3,\"fltType\": \"COMMERCIAL\",\"schFltStDt\": \"%s\",\"schFltEndDt\": \"%s\",\"fltPurpose\": \"06\",\"serviceType\": \"KAC\",\"areaList\" : [{\"areaType\": \"LINE\",\"fltMethod\": \"02\",\"fltMothoeRm\": \"\",\"bufferZone\": \"100\",\"fltElev\": \"100\",\"coordList\": [{\"lat\": 37.51625845252909,\"lon\": 126.72340194011286},{\"lat\": 37.512215014051776,\"lon\": 126.72058946300956},{\"lat\": 37.51123897883966,\"lon\": 126.72463239884405}]}],\"arcrftList\" : [{\"idntfNum\": \"PA0001\",\"groupNm\": \"\",\"prdctNum\": \"\",\"arcrftTypeCd\": \"11\",\"arcrftModelNm\": \"\",\"prdctCmpnNm\": \"\",\"prdctDate\": \"\",\"arcrftLngth\": 0,\"arcrftWghtCd\": \"8\",\"arcrftHght\": 0,\"arcrftWght\": 0,\"wghtTypeCd\": \"\",\"imageUrl\": \"\",\"takeoffWght\": 0,\"useYn\": \"\",\"cameraYn\": \"\",\"insrncYn\": \"\",\"ownerNm\": \"\"}],\"terms\": []}"
.trim()
.formatted(plusOneDay.toString(), plusThreeDay.toString());
CreateLaancPlanRQ rq;
FltPlanBasDTO result = new FltPlanBasDTO();
try{
rq = ObjectMapperUtils.getObjectMapper().readValue(jsonRQ, CreateLaancPlanRQ.class);
flightLaancService.createPlan(rq);
result = flightLaancService.testDescPlanSno();
LocalDateTime ctEndDt = searchData.atStartOfDay().plusHours(2);
LocalDateTime ctStDt = searchData.atStartOfDay();
CtrCntrlBasDTO ctrCntrlBasDTO = new CtrCntrlBasDTO();
ctrCntrlBasDTO.setAvrgSpeed(0.0);
ctrCntrlBasDTO.setBttrCnsmptn(null);
ctrCntrlBasDTO.setTtlDstnc(33.30811254417446);
ctrCntrlBasDTO.setTtlTime(0.0);
ctrCntrlBasDTO.setCntrlEndDt(ctEndDt);
ctrCntrlBasDTO.setCntrlStDt(ctStDt);
ctrCntrlBasDTO.setCreateDt(LocalDateTime.now());
ctrCntrlBasDTO.setFlghtEndDt(null);
ctrCntrlBasDTO.setFlghtStDt(null);
ctrCntrlBasDTO.setUpdateDt(LocalDateTime.now());
ctrCntrlBasDTO.setEndTypeCd("01");
ctrCntrlBasDTO.setObjectTypeCd("DRON");
ctrCntrlBasDTO.setStatusCd("99");
ctrCntrlBasDTO.setTtlDstncType("M");
ctrCntrlBasDTO.setTtlTimeType(null);
ctrCntrlBasDTO.setIdntfNum("PA0001");
ctrCntrlBasDTO.setCntrlId("00121354-7c41-4637-8283-c34c508625ac");
ctrCntrlBasDTO.setProcStatusYn("N");
flightPlanService.testCreateCtrCntrlBas(ctrCntrlBasDTO);
} catch (Exception e){
e.printStackTrace();
}
return result;
}
}

1
app/kac-app/src/test/java/kr/co/palnet/kac/user/account/UserAccountControllerTest.java

@ -11,7 +11,6 @@ import org.springframework.restdocs.headers.HeaderDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.restdocs.payload.JsonFieldType;
import org.springframework.transaction.annotation.Transactional;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;

8
build.gradle

@ -32,7 +32,13 @@ allprojects {
plugins.apply("idea")
repositories {
mavenCentral()
mavenCentral {
content {
excludeModule("javax.media", "jai_core")
}
}
maven { url "https://repo.osgeo.org/repository/release" }
}
configurations {

8
common/core/src/main/java/kr/co/palnet/kac/core/exception/BaseErrorCode.java

@ -25,7 +25,13 @@ public enum BaseErrorCode {
WEB_NOT_FOUND("WB404", HttpStatus.INTERNAL_SERVER_ERROR, "찾을수 없는 페이지"),
WEB_API_ERROR("WB500", HttpStatus.INTERNAL_SERVER_ERROR, "외부 연동 에러"),
DATA_ALREADY_EXISTS("DT001", HttpStatus.INTERNAL_SERVER_ERROR, "이미 등록된 데이터"),
DATA_EMPTY("DT002", HttpStatus.INTERNAL_SERVER_ERROR, "데이터 없음");
DATA_EMPTY("DT002", HttpStatus.INTERNAL_SERVER_ERROR, "데이터 없음"),
QR_EXPIRED("QR001", HttpStatus.BAD_REQUEST ,"QR코드 유효기간이 만료되었습니다")
;
private final String code;

6
data/com/src/main/java/kr/co/palnet/kac/data/com/domain/ComConfirmBas.java

@ -6,7 +6,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
import java.time.LocalDateTime;
@Data
@Builder
@ -61,7 +61,7 @@ public class ComConfirmBas {
// 생성일시
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정사용자ID
@Column(name = "UPDATE_USER_ID", length = 30, nullable = false)
@ -69,6 +69,6 @@ public class ComConfirmBas {
// 수정일시
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
}

6
data/com/src/main/java/kr/co/palnet/kac/data/com/domain/ComFileBas.java

@ -6,7 +6,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
import java.time.LocalDateTime;
@Data
@ -62,7 +62,7 @@ public class ComFileBas {
// 삭제일시
@Column(name = "DEL_DT", columnDefinition = "datetime")
private Instant delDt;
private LocalDateTime delDt;
// 생성사용자ID
@Column(name = "CREATE_USER_ID", length = 30, updatable = false, nullable = false)
@ -70,7 +70,7 @@ public class ComFileBas {
// 생성일시
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
}

4
data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComConfirmBasRepository.java

@ -3,6 +3,10 @@ package kr.co.palnet.kac.data.com.repository;
import kr.co.palnet.kac.data.com.domain.ComConfirmBas;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface ComConfirmBasRepository extends JpaRepository<ComConfirmBas, Integer> {
Optional<ComConfirmBas> findFirstByConfirmKeyOrderByCreateDtDesc(String confirmKey);
}

11
data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComFileBasRepository.java

@ -3,6 +3,15 @@ package kr.co.palnet.kac.data.com.repository;
import kr.co.palnet.kac.data.com.domain.ComFileBas;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ComFileBasRepository extends JpaRepository<ComFileBas, Integer> {
import java.util.List;
import java.util.Optional;
public interface ComFileBasRepository extends JpaRepository<ComFileBas, Long> {
Optional<ComFileBas> findFirstByOrderByFileGroupNoDesc();
Optional<List<ComFileBas>> findByFileGroupNoInAndDelYnOrderByCreateDtDesc(List<Long> fileGroupNos, String delYn);
Optional<ComFileBas> findFirstByFileGroupNoAndDelYnOrderByCreateDtDesc(Long fileGroupNo, String delYn);
}

30
data/com/src/main/java/kr/co/palnet/kac/data/com/service/ComConfirmDomainService.java

@ -0,0 +1,30 @@
package kr.co.palnet.kac.data.com.service;
import kr.co.palnet.kac.data.com.domain.ComConfirmBas;
import kr.co.palnet.kac.data.com.repository.ComConfirmBasRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@Slf4j
@RequiredArgsConstructor
public class ComConfirmDomainService {
private final ComConfirmBasRepository comConfirmBasRepository;
public ComConfirmBas saveComConfirmBas(ComConfirmBas entity){
return comConfirmBasRepository.save(entity);
}
public Optional<ComConfirmBas> findFirstByConfirmKeyOrderByCreateDtDesc(String confirmKey){
return comConfirmBasRepository.findFirstByConfirmKeyOrderByCreateDtDesc(confirmKey);
}
public void flush(){
comConfirmBasRepository.flush();
}
}

42
data/com/src/main/java/kr/co/palnet/kac/data/com/service/ComFileDomainService.java

@ -0,0 +1,42 @@
package kr.co.palnet.kac.data.com.service;
import kr.co.palnet.kac.data.com.domain.ComFileBas;
import kr.co.palnet.kac.data.com.repository.ComFileBasRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
@RequiredArgsConstructor
public class ComFileDomainService {
private final ComFileBasRepository comFileBasRepository;
public ComFileBas saveComFileBas(ComFileBas entity){
return comFileBasRepository.save(entity);
}
public Long findFirstByOrderByFileGroupNoDesc(){
Optional<ComFileBas> entityData = comFileBasRepository.findFirstByOrderByFileGroupNoDesc();
if(entityData.isPresent()){
ComFileBas lastComFileBas = entityData.get();
return lastComFileBas.getFileGroupNo() + 1;
} else {
return 1L;
}
}
public Optional<List<ComFileBas>> findByFileGroupNoInAndDelYnOrderByCreateDtDesc(List<Long> fileGroupNos, String delYn){
return comFileBasRepository.findByFileGroupNoInAndDelYnOrderByCreateDtDesc(fileGroupNos, delYn);
}
public Optional<ComFileBas> findFirstByFileGroupNoAndDelYnOrderByCreateDtDesc(Long fileGroupNo){
return comFileBasRepository.findFirstByFileGroupNoAndDelYnOrderByCreateDtDesc(fileGroupNo, "N");
}
}

14
data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/CtrCntrlBas.java

@ -3,7 +3,7 @@ package kr.co.palnet.kac.data.ctr.model;
import jakarta.persistence.*;
import lombok.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
@ -39,19 +39,19 @@ public class CtrCntrlBas {
// 비행시작일시
@Column(name = "FLGHT_ST_DT", columnDefinition = "datetime(6)")
private Instant flghtStDt;
private LocalDateTime flghtStDt;
// 비행종료일시
@Column(name = "FLGHT_END_DT", columnDefinition = "datetime(6)")
private Instant flghtEndDt;
private LocalDateTime flghtEndDt;
// 관제시작일시
@Column(name = "CNTRL_ST_DT", columnDefinition = "datetime(6)", nullable = false)
private Instant cntrlStDt;
private LocalDateTime cntrlStDt;
// 관제종료일시
@Column(name = "CNTRL_END_DT", columnDefinition = "datetime(6)")
private Instant cntrlEndDt;
private LocalDateTime cntrlEndDt;
// 총비행시간
@Column(name = "TTL_TIME", columnDefinition = "double default 0.0")
@ -87,11 +87,11 @@ public class CtrCntrlBas {
// 생성일시
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정일시
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
@OneToMany(mappedBy = "ctrCntrlBas", fetch = FetchType.LAZY)
private List<CtrCntrlHstry> ctrCntrlHstryList;

2
data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/CtrCntrlHstryArea.java

@ -29,7 +29,7 @@ public class CtrCntrlHstryArea {
// 이력일련번호
@Column(name = "HSTRY_SNO", nullable = false) // mysql :: "int unsigned"
private int hstrySno;
private Long hstrySno;
// 관제ID
@Column(name = "CNTRL_ID", length = 60, nullable = false)

20
data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/model/join/CntrlJoinHstryAreaModel.java

@ -0,0 +1,20 @@
package kr.co.palnet.kac.data.ctr.model.join;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class CntrlJoinHstryAreaModel {
private String startAddress;
private String endAddress;
private String cntrlId;
private LocalDateTime cntrlStDt;
private LocalDateTime cntrlEndDt;
private String statusCd;
}

83
data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/repository/CtrCntrlBasQueryRepository.java

@ -0,0 +1,83 @@
package kr.co.palnet.kac.data.ctr.repository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import kr.co.palnet.kac.data.ctr.model.QCtrCntrlBas;
import kr.co.palnet.kac.data.ctr.model.QCtrCntrlHstryArea;
import kr.co.palnet.kac.data.ctr.model.join.CntrlJoinHstryAreaModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Repository
@Slf4j
@RequiredArgsConstructor
public class CtrCntrlBasQueryRepository {
private final JPAQueryFactory query;
public Optional<List<CntrlJoinHstryAreaModel>> findByIdntfNumAndSearchDate(String idntfNum, LocalDateTime schFltStDt, LocalDateTime schFltEndDt){
QCtrCntrlBas cntrlBas = QCtrCntrlBas.ctrCntrlBas;
QCtrCntrlHstryArea cntrlHstryArea = QCtrCntrlHstryArea.ctrCntrlHstryArea;
BooleanBuilder builder = new BooleanBuilder();
builder.and(cntrlBas.cntrlStDt.loe(schFltEndDt))
.and(cntrlBas.cntrlStDt.goe(schFltStDt))
.and(cntrlBas.idntfNum.eq(idntfNum));
return Optional.ofNullable(query.select(Projections.bean(
CntrlJoinHstryAreaModel.class,
ExpressionUtils.as(
JPAExpressions.select(
cntrlHstryArea.area1.concat(" ")
.concat(cntrlHstryArea.area2).concat(" ")
.concat(cntrlHstryArea.area3).concat(" ")
.concat(cntrlHstryArea.landNm).concat(" ")
.concat(cntrlHstryArea.landNum)
)
.from(cntrlHstryArea)
.where(cntrlHstryArea.cntrlId.eq(cntrlBas.cntrlId)
.and(cntrlHstryArea.actnType.eq("01"))),
"startAddress"
),
ExpressionUtils.as(
JPAExpressions.select(
cntrlHstryArea.area1.concat(" ")
.concat(cntrlHstryArea.area2).concat(" ")
.concat(cntrlHstryArea.area3).concat(" ")
.concat(cntrlHstryArea.landNm).concat(" ")
.concat(cntrlHstryArea.landNum)
)
.from(cntrlHstryArea)
.where(cntrlHstryArea.cntrlId.eq(cntrlBas.cntrlId)
.and(cntrlHstryArea.actnType.eq("99"))),
"endAddress"
),
cntrlBas.cntrlId,
cntrlBas.cntrlStDt,
cntrlBas.cntrlEndDt,
new CaseBuilder()
.when(cntrlBas.statusCd.eq("01")).then("F")
.when(cntrlBas.statusCd.eq("99")).then("S")
.otherwise("B").as("statusCd")
))
.from(cntrlBas)
.where(builder)
.orderBy(cntrlBas.cntrlStDt.asc())
.fetch());
}
}

35
data/ctr/src/main/java/kr/co/palnet/kac/data/ctr/service/CtrCntrlDomainService.java

@ -0,0 +1,35 @@
package kr.co.palnet.kac.data.ctr.service;
import kr.co.palnet.kac.data.ctr.model.CtrCntrlBas;
import kr.co.palnet.kac.data.ctr.model.join.CntrlJoinHstryAreaModel;
import kr.co.palnet.kac.data.ctr.repository.CtrCntrlBasQueryRepository;
import kr.co.palnet.kac.data.ctr.repository.CtrCntrlBasRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
@RequiredArgsConstructor
public class CtrCntrlDomainService {
private final CtrCntrlBasRepository ctrCntrlBasRepository;
private final CtrCntrlBasQueryRepository ctrCntrlBasQueryRepository;
public Optional<List<CntrlJoinHstryAreaModel>> findCntrlJoinHstryAreaByIdntfNumAndSearchDate(String idntfNum, LocalDateTime schFltStDt, LocalDateTime schFltEndDt){
return ctrCntrlBasQueryRepository.findByIdntfNumAndSearchDate(idntfNum, schFltStDt, schFltEndDt);
}
public CtrCntrlBas saveCtrCntrlBas(CtrCntrlBas entity){
return ctrCntrlBasRepository.save(entity);
}
}

8
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanArcrft.java

@ -4,7 +4,7 @@ import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalDate;
@Data
@ -114,7 +114,7 @@ public class FltPlanArcrft {
// 보험유효기간
@Column(name = "INSURANCE_EXPERIOD", columnDefinition = "datetime")
private String insuranceExperiod;
private LocalDateTime insuranceExperiod;
// 법인명
@Column(name = "CORPORATION_NM", length = 100)
@ -130,7 +130,7 @@ public class FltPlanArcrft {
// 생성일시
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정사용자ID
@Column(name = "UPDATE_USER_ID", length = 30, nullable = false)
@ -139,7 +139,7 @@ public class FltPlanArcrft {
// 수정일시
@UpdateTimestamp
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
@JoinColumn(
name = "PLAN_SNO", insertable = false, updatable = false,

8
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanArea.java

@ -5,7 +5,7 @@ import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
@Data
@ -64,7 +64,7 @@ public class FltPlanArea {
// 생성일시
@CreationTimestamp
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정사용자ID
@Column(name = "UPDATE_USER_ID", length = 30, nullable = false)
@ -73,7 +73,7 @@ public class FltPlanArea {
// 수정일시
@UpdateTimestamp
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
@JoinColumn(
name = "PLAN_SNO", insertable = false, updatable = false,
@ -82,7 +82,7 @@ public class FltPlanArea {
@ManyToOne(fetch = FetchType.LAZY)
private FltPlanBas fltPlanBas;
@OneToMany(mappedBy = "fltPlanArea", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "fltPlanArea", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<FltPlanAreaCoord> fltPlanAreaCoordList;
}

4
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanAreaCoord.java

@ -4,7 +4,7 @@ import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import java.time.Instant;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@ -46,7 +46,7 @@ public class FltPlanAreaCoord {
// 생성일시
@CreationTimestamp
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
@JoinColumn(
name = "PLAN_AREA_SNO", insertable = false, updatable = false,

20
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanBas.java

@ -3,7 +3,7 @@ package kr.co.palnet.kac.data.flt.model;
import jakarta.persistence.*;
import lombok.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
@Data
@ -69,11 +69,11 @@ public class FltPlanBas {
// 예정비행시작시간
@Column(name = "SCH_FLT_ST_DT", columnDefinition = "datetime(6)", nullable = false)
private Instant schFltStDt;
private LocalDateTime schFltStDt;
// 예정비행종료시간
@Column(name = "SCH_FLT_END_DT", columnDefinition = "datetime(6)", nullable = false)
private Instant schFltEndDt;
private LocalDateTime schFltEndDt;
// 비행목적
@Column(name = "FLT_PURPOSE", length = 200, nullable = false)
@ -93,7 +93,7 @@ public class FltPlanBas {
// 승인일시
@Column(name = "APRVL_DT", columnDefinition = "datetime")
private Instant aprvlDt;
private LocalDateTime aprvlDt;
// 삭제여부
@Column(name = "DEL_YN", columnDefinition = "char(1) default 'N'", nullable = false)
@ -109,7 +109,7 @@ public class FltPlanBas {
// 생성일시
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정사용자ID
@Column(name = "UPDATE_USER_ID", length = 30, nullable = false)
@ -117,18 +117,18 @@ public class FltPlanBas {
// 수정일시
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<FltPlanArea> fltPlanAreaList;
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<FltPlanArcrft> fltPlanArcrftList;
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<FltPlanPilot> fltPlanPilotList;
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY)
@OneToMany(mappedBy = "fltPlanBas", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<FltPlanCtrCntrlRel> fltPlanCtrCntrlRelList;
}

4
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanCtrCntrlRel.java

@ -21,7 +21,7 @@ public class FltPlanCtrCntrlRel {
@Builder
public static class FltPlanCtrCntrlRelId implements Serializable {
private String cntrlId;
private Integer planSno;
private Long planSno;
}
// 관제ID
@ -32,7 +32,7 @@ public class FltPlanCtrCntrlRel {
// 비행계획서일련번호
@Id
@Column(name = "PLAN_SNO") // mysql :: "int unsigned"
private Integer planSno;
private Long planSno;
// 식별번호
@Column(name = "IDNTF_NUM", length = 30, nullable = false)

6
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/FltPlanPilot.java

@ -5,7 +5,7 @@ import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.Instant;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@ -83,7 +83,7 @@ public class FltPlanPilot {
// 생성일시
@CreationTimestamp
@Column(name = "CREATE_DT", columnDefinition = "datetime", updatable = false, nullable = false)
private Instant createDt;
private LocalDateTime createDt;
// 수정사용자ID
@Column(name = "UPDATE_USER_ID", length = 30, nullable = false)
@ -92,7 +92,7 @@ public class FltPlanPilot {
// 수정일시
@UpdateTimestamp
@Column(name = "UPDATE_DT", columnDefinition = "datetime", nullable = false)
private Instant updateDt;
private LocalDateTime updateDt;
@JoinColumn(
name = "PLAN_SNO", insertable = false, updatable = false,

21
data/flt/src/main/java/kr/co/palnet/kac/data/flt/model/join/FltPlanBasJoinAreaModel.java

@ -0,0 +1,21 @@
package kr.co.palnet.kac.data.flt.model.join;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FltPlanBasJoinAreaModel {
private Long planSno;
private String groupId;
private LocalDateTime schFltStDt;
private LocalDateTime schFltEndDt;
private String ownerNm;
private String idntfNum;
}

7
data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanArcrftRepository.java

@ -3,6 +3,11 @@ package kr.co.palnet.kac.data.flt.repository;
import kr.co.palnet.kac.data.flt.model.FltPlanArcrft;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FltPlanArcrftRepository extends JpaRepository<FltPlanArcrft, Integer> {
import java.util.List;
import java.util.Optional;
public interface FltPlanArcrftRepository extends JpaRepository<FltPlanArcrft, Long> {
public Optional<List<FltPlanArcrft>> findByPlanSno(Long planSno);
}

9
data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanAreaRepository.java

@ -3,5 +3,12 @@ package kr.co.palnet.kac.data.flt.repository;
import kr.co.palnet.kac.data.flt.model.FltPlanArea;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FltPlanAreaRepository extends JpaRepository<FltPlanArea, Integer> {
import java.util.List;
import java.util.Optional;
public interface FltPlanAreaRepository extends JpaRepository<FltPlanArea, Long> {
public Optional<List<FltPlanArea>> findByPlanSno(Long planSno);
}

6
data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanBasRepository.java

@ -3,6 +3,10 @@ package kr.co.palnet.kac.data.flt.repository;
import kr.co.palnet.kac.data.flt.model.FltPlanBas;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FltPlanBasRepository extends JpaRepository<FltPlanBas, Integer> {
import java.util.Optional;
public interface FltPlanBasRepository extends JpaRepository<FltPlanBas, Long> {
public Optional<FltPlanBas> findTopByOrderByPlanSnoDesc();
}

81
data/flt/src/main/java/kr/co/palnet/kac/data/flt/repository/FltPlanQueryRepository.java

@ -0,0 +1,81 @@
package kr.co.palnet.kac.data.flt.repository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import kr.co.palnet.kac.data.flt.model.FltPlanBas;
import kr.co.palnet.kac.data.flt.model.QFltPlanArcrft;
import kr.co.palnet.kac.data.flt.model.QFltPlanBas;
import kr.co.palnet.kac.data.flt.model.join.FltPlanBasJoinAreaModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Repository
@Slf4j
@RequiredArgsConstructor
public class FltPlanQueryRepository {
private final JPAQueryFactory query;
public Optional<List<FltPlanBas>> findAllBySearch(String memberName, LocalDateTime createStDate, LocalDateTime createEndDate){
QFltPlanBas bas = QFltPlanBas.fltPlanBas;
BooleanBuilder builder = new BooleanBuilder();
if(StringUtils.hasText(memberName)){
builder.and(bas.memberName.contains(memberName));
}
if(createStDate != null) {
builder.and(bas.createDt.goe(createStDate));
}
if(createEndDate != null){
builder.and(bas.createDt.lt(createEndDate));
}
return Optional.ofNullable(query
.select(bas)
.from(bas)
.where(builder)
.orderBy(bas.createDt.desc())
.fetch());
}
public Optional<List<FltPlanBasJoinAreaModel>> findAllBySearch(String searchDate){
QFltPlanBas fltPlanBas = QFltPlanBas.fltPlanBas;
QFltPlanArcrft fltPlanArcrft = QFltPlanArcrft.fltPlanArcrft;
LocalDateTime searchDateParam = LocalDate.parse(searchDate).atStartOfDay();
BooleanBuilder builder = new BooleanBuilder();
builder.and(fltPlanBas.schFltStDt.loe(searchDateParam))
.and(fltPlanBas.schFltEndDt.goe(searchDateParam))
.and(fltPlanBas.aprvlYn.eq("Y"));
return Optional.ofNullable(query.
select(Projections.bean(
FltPlanBasJoinAreaModel.class,
fltPlanBas.planSno,
fltPlanBas.groupId,
fltPlanBas.schFltStDt,
fltPlanBas.schFltEndDt,
fltPlanArcrft.ownerNm,
fltPlanArcrft.idntfNum
))
.from(fltPlanBas)
.leftJoin(fltPlanArcrft)
.on(fltPlanBas.planSno.eq(fltPlanArcrft.planSno))
.where(builder)
.orderBy(fltPlanBas.schFltStDt.asc())
.fetch());
}
}

84
data/flt/src/main/java/kr/co/palnet/kac/data/flt/service/FltPlanDomainService.java

@ -0,0 +1,84 @@
package kr.co.palnet.kac.data.flt.service;
import kr.co.palnet.kac.data.flt.model.*;
import kr.co.palnet.kac.data.flt.model.join.FltPlanBasJoinAreaModel;
import kr.co.palnet.kac.data.flt.repository.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class FltPlanDomainService {
private final FltPlanBasRepository fltPlanBasRepository;
private final FltPlanQueryRepository fltPlanQueryRepository;
private final FltPlanAreaRepository fltPlanAreaRepository;
private final FltPlanAreaCoordRepository fltPlanAreaCoordRepository;
private final FltPlanPilotRepository fltPlanPilotRepository;
private final FltPlanArcrftRepository fltPlanArcrftRepository;
public Optional<List<FltPlanBas>> findAllFltPlanBasBySearch(String memberName, LocalDateTime createStDate, LocalDateTime createEndDate){
return fltPlanQueryRepository.findAllBySearch(memberName, createStDate, createEndDate);
}
public FltPlanBas findByOrderByPlanSnoDesc(){
Optional<FltPlanBas> fltPlanBasData = fltPlanBasRepository.findTopByOrderByPlanSnoDesc();
return fltPlanBasData.orElse(null);
}
public Optional<List<FltPlanBasJoinAreaModel>> findAllFltPlanBasBySearch(String searchDate){
return fltPlanQueryRepository.findAllBySearch(searchDate);
}
public Optional<FltPlanBas> findById(Long planSno){
return fltPlanBasRepository.findById(planSno);
}
public FltPlanBas saveFltPlanBas(FltPlanBas entity){
return fltPlanBasRepository.save(entity);
}
public Optional<List<FltPlanArea>> findFltPlanAreaByPlanSno(Long planSno){
return fltPlanAreaRepository.findByPlanSno(planSno);
}
public FltPlanArea saveFltPlanArea(FltPlanArea entity){
return fltPlanAreaRepository.save(entity);
}
public FltPlanAreaCoord saveFltPlanAreaCoord(FltPlanAreaCoord entity){
return fltPlanAreaCoordRepository.save(entity);
}
public FltPlanPilot saveFltPlanPilot(FltPlanPilot entity){
return fltPlanPilotRepository.save(entity);
}
public Optional<List<FltPlanArcrft>> findFltPlanArcrftByPlanSno(Long planSno){
return fltPlanArcrftRepository.findByPlanSno(planSno);
}
public FltPlanArcrft saveFltPlanArcrft(FltPlanArcrft entity){
return fltPlanArcrftRepository.save(entity);
}
}

19
data/other/src/main/java/kr/co/palnet/kac/data/other/service/OtherDomainService.java

@ -0,0 +1,19 @@
package kr.co.palnet.kac.data.other.service;
import kr.co.palnet.kac.data.other.model.SuredataEntity;
import kr.co.palnet.kac.data.other.repository.SuredataRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class OtherDomainService {
private final SuredataRepository suredataRepository;
public SuredataEntity saveSuredate(SuredataEntity entity){
return suredataRepository.save(entity);
}
}

4
data/pty/src/main/java/kr/co/palnet/kac/data/pty/repository/PtyGroupBasRepository.java

@ -4,7 +4,11 @@ import kr.co.palnet.kac.data.pty.model.PtyGroupBas;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface PtyGroupBasRepository extends JpaRepository<PtyGroupBas, String> {
public Optional<List<PtyGroupBas>> findByGroupNm(String groupNm);
}

14
data/pty/src/main/java/kr/co/palnet/kac/data/pty/service/PtyGroupDomainService.java

@ -20,19 +20,23 @@ public class PtyGroupDomainService {
private final PtyCstmrGroupRepository ptyCstmrGroupRepository;
public Optional<List<PtyCstmrGroup>> findJoinGroupByCstmrSno(Long cstmrSno){
public Optional<List<PtyCstmrGroup>> findPtyCstmrGroupJoinGroupByCstmrSno(Long cstmrSno){
return ptyCstmrGroupRepository.findByCstmrSnoAndJoinYn(cstmrSno, "Y");
}
public Optional<List<PtyCstmrGroup>> findByGroupId(String groupId){
public Optional<List<PtyCstmrGroup>> findPtyCstmrGroupByGroupId(String groupId){
return ptyCstmrGroupRepository.findByGroupId(groupId);
}
public Optional<List<PtyCstmrGroup>> findByCstmrSno(Long cstmrSno){
public Optional<List<PtyGroupBas>> findPtyGroupBasByGroupNm(String groupNm){
return ptyGroupBasRepository.findByGroupNm(groupNm);
}
public Optional<List<PtyCstmrGroup>> findPtyCstmrGroupByCstmrSno(Long cstmrSno){
return ptyCstmrGroupRepository.findByCstmrSno(cstmrSno);
}
public Optional<PtyCstmrGroup> findByGroupIdAndCstmrSno(String groupId, Long cstmrSno){
public Optional<PtyCstmrGroup> findPtyCstmrGroupByGroupIdAndCstmrSno(String groupId, Long cstmrSno){
return ptyCstmrGroupRepository.findByGroupIdAndCstmrSno(groupId, cstmrSno);
}
@ -40,7 +44,7 @@ public class PtyGroupDomainService {
return ptyCstmrGroupRepository.save(entity);
}
public PtyGroupBas findById(String id){
public PtyGroupBas findPtyGroupBasById(String id){
return ptyGroupBasRepository.findById(id).orElse(null);
}

6
data/user/build.gradle

@ -0,0 +1,6 @@
dependencies {
}

44
web/api-flight/build.gradle

@ -0,0 +1,44 @@
dependencies {
implementation "$boot:spring-boot-starter-web"
implementation "$boot:spring-boot-starter-data-jpa"
implementation 'javax.media:jai_core:1.1.3'
// thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// pdf create
implementation 'com.itextpdf:html2pdf:5.0.3'
// other
implementation 'org.apache.httpcomponents.client5:httpclient5:5.3'
implementation 'org.apache.commons:commons-io:1.3.2'
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
// geometry
implementation 'com.esri.geometry:esri-geometry-api:2.2.4'
implementation 'org.locationtech.proj4j:proj4j:1.3.0'
implementation 'org.locationtech.proj4j:proj4j-epsg:1.3.0'
implementation 'org.locationtech.jts:jts-core:1.19.0'
implementation 'org.geotools:gt-geojson:29.2'
implementation 'org.geotools:gt-coverage:29.2'
implementation 'org.geotools:gt-geotiff:29.2'
implementation 'org.geotools:gt-epsg-hsql:29.2'
// QR Code
implementation 'com.google.zxing:core:3.5.2'
implementation 'com.google.zxing:javase:3.5.2'
compileOnly 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
implementation project(":common:core")
implementation project(":common:util")
implementation project(":data:flt")
implementation project(":data:ctr")
implementation project(":data:com")
implementation project(":data:pty")
implementation project(":data:other")
compileOnly project(":web:security")
}

27
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/ComnSmsLaancAprovModel.java vendored

@ -0,0 +1,27 @@
package kr.co.palnet.kac.api.external.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ComnSmsLaancAprovModel {
private String callphone; // 수신번호
private String pilotName; // 조종사 이름
// private String birthDate; // 조종사 생년월일
private String schFltStDt; // 비행시작일시
private String schFltEndDt; // 비행종료일시
private String fltPurpose; // 비행목적
// private String arcrftType; // 등록 종류
// private String idntfNum; // 신고번호
private String address; // 주소
private String elev; // 고도
// private String createDt; // 신청일자
}

16
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/CtrTrnsLctnModel.java vendored

@ -0,0 +1,16 @@
package kr.co.palnet.kac.api.external.model;
import lombok.Data;
@Data
public class CtrTrnsLctnModel {
private Long hstryAreaSno;
private String area1;
private String area2;
private String area3;
private String zipCd;
private String landNm;
private String landNum;
private String areaType;
private String areaNm;
}

28
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/model/TsQRcodeRQ.java vendored

@ -0,0 +1,28 @@
package kr.co.palnet.kac.api.external.model;
import lombok.Builder;
import lombok.Data;
@Data
public class TsQRcodeRQ {
private String type; // 5 (한국공항공사) - 고정
private String rtnUrl; // 리턴 url - 고정
private String reqId; // 추적 코드
private String submittype; // 기체신고번호
private String applyUser; // 사용자 인증 코드 ci
public TsQRcodeRQ() {
this.type = "5";
this.rtnUrl = "";
}
@Builder
public TsQRcodeRQ(String rtnUrl, String reqId, String submittype, String applyUser) {
this.type = "5";
this.rtnUrl = rtnUrl;
this.reqId = reqId;
this.submittype = submittype;
this.applyUser = applyUser;
}
}

92
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/ComnSmsService.java vendored

@ -0,0 +1,92 @@
package kr.co.palnet.kac.api.external.service;
import kr.co.palnet.kac.api.external.model.ComnSmsLaancAprovModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.SuredataEntityDTO;
import kr.co.palnet.kac.api.util.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@Slf4j
@RequiredArgsConstructor
@Service
public class ComnSmsService {
/**
* 비행승인시 SMS를 보내는 기능.
* @param model
*/
public SuredataEntityDTO sendLaancAprovSms(ComnSmsLaancAprovModel model) {
log.info("sendSms : {}", model);
ClassPathResource resource = new ClassPathResource("templates/sms/SmsLaancAprov.txt");
String template = "";
try(BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))){
StringBuilder stringBuilder = new StringBuilder();
String line;
boolean firstLine = true; // 첫 번째 줄은 개행 문자를 추가하지 않음
while ((line = br.readLine()) != null) {
if (firstLine) {
firstLine = false;
} else {
stringBuilder.append("\n"); // 개행 문자 추가
}
stringBuilder.append(line);
}
template = stringBuilder.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
template = template.replace("${pilotName}", model.getPilotName());
template = template.replace("${schFltStDt}", model.getSchFltStDt());
template = template.replace("${schFltEndDt}", model.getSchFltEndDt());
template = template.replace("${fltPurpose}", model.getFltPurpose());
template = template.replace("${address}", model.getAddress());
template = template.replace("${elev}", model.getElev());
SuredataEntityDTO dto = getInitialEntity();
dto.setSubject("[비행승인 완료]");
dto.setMsg(template);
dto.setCallname(model.getPilotName());
dto.setCallphone(model.getCallphone());
dto.setKind("M");
log.info("entity : {}", dto);
log.info("========================================");
log.info("message : {}", template);
log.info("========================================");
log.info("message : {}", dto.getMsg());
if(dto.getBatchflag() == null) dto.setBatchflag(0);
return dto;
}
/**
* 데이터베이스에 추가할 메세지 발송이력 데이터를 셋팅함.
* @return
*/
public SuredataEntityDTO getInitialEntity() {
String nowStr = DateUtils.toDateTimeStringByFormat(LocalDateTime.now(), "yyyyMMddHHmmss");
SuredataEntityDTO dto = new SuredataEntityDTO();
dto.setUsercode("palnet");
dto.setIntime(nowStr);
dto.setReqname("한국공항공사");
dto.setReqphone("0262003912"); // 1661-2626
// entity.setCallname("지대한");
// entity.setCallphone("010-0000-0000");
// entity.setSubject("주제");
// entity.setMsg("");
dto.setReqtime("00000000000000");
dto.setResult("0");
dto.setKind("S");
return dto;
}
}

134
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/CtrTrnsLctnService.java vendored

@ -0,0 +1,134 @@
package kr.co.palnet.kac.api.external.service;
import kr.co.palnet.kac.api.external.model.CtrTrnsLctnModel;
import kr.co.palnet.kac.core.exception.BaseErrorCode;
import kr.co.palnet.kac.util.ObjectMapperUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.List;
import java.util.Map;
@Service
public class CtrTrnsLctnService {
@Value("${naver.api.url}")
private String NAVER_API_URL;
@Value("${naver.api.id}")
private String NAVER_API_ID;
@Value("${naver.api.key}")
private String NAVER_API_KEY;
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 위치에 맞는 값에 대한 주소로 변환하는 기능.
* @param lat
* @param lon
* @return
*/
public CtrTrnsLctnModel convertLatlonToAddress(double lat , double lon) {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000); //타임아웃 설정 5초
factory.setConnectionRequestTimeout(5000);//타임아웃 설정 5초
RestTemplate restTemplate = new RestTemplate(factory);
HttpHeaders header = new HttpHeaders();
header.add("X-NCP-APIGW-API-KEY-ID", NAVER_API_ID);
header.add("X-NCP-APIGW-API-KEY", NAVER_API_KEY);
HttpEntity<?> entity = new HttpEntity<>(header);
UriComponents uri = UriComponentsBuilder.fromHttpUrl(NAVER_API_URL)
.queryParam("request", "coordsToaddr")
.queryParam("coords", lon + "," + lat)
.queryParam("sourcecrs", "epsg:4326")
.queryParam("output", "json")
// .queryParam("orders", "roadaddr")
.queryParam("orders", "addr,roadaddr")
.build();
ResponseEntity<Map> resultMap = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Map.class);
HttpStatusCode rsStatus = resultMap.getStatusCode();
if(rsStatus != HttpStatus.OK){
logger.debug("response error occurs.");
return null;
}
Map body = resultMap.getBody();
Map apiStatus = (Map)body.get("status");
try {
logger.debug(ObjectMapperUtils.getObjectMapper().writeValueAsString(body));
} catch (Exception e){
logger.error("",e);
}
String name = (String)apiStatus.get("name");
if(!"ok".equals(name)){
if(apiStatus != null){
logger.debug("get aera api response error occurs. : {}/{}", name, apiStatus.get("message"));
}else{
logger.debug("get aera api response error occurs.");
}
// logger.debug("{}\t/{}\t/{}\t/{}\t/{}", dto.getUserSno(), dto.getLctSno(), dto.getLat(), dto.getLon(), dto.getCreatDt());
logger.debug(BaseErrorCode.FAILED.message());
return null;
// throw new CustomException(ErrorCode.FAIL);
}
CtrTrnsLctnModel model = new CtrTrnsLctnModel();
List results = (List)body.get("results");
// 리스트에서 도로명 타입의 검색결과가 있는지 확인
// 있을 경우 해당 인덱스로 area 주소 반환
int typeIndex = -1;
for(Object result : results){
typeIndex++;
if("roadaddr".equals(((Map) result).get("name"))) break;
}
if(typeIndex < 0) {
logger.debug(BaseErrorCode.DATA_EMPTY.message());
return null;
}
Map result = (Map)results.get(typeIndex);
result.forEach((resultKey, resultValue) -> {
// log.debug(">>> resultKey / resultValue : {} / {}",resultKey, resultValue);
if("region".equals(resultKey)){
model.setArea1(((Map)((Map)resultValue).get("area1")).get("name").toString());
model.setArea2(((Map)((Map)resultValue).get("area2")).get("name").toString());
model.setArea3(((Map)((Map)resultValue).get("area3")).get("name").toString());
}
if("land".equals(resultKey)){
String landNum = ((Map)resultValue).get("number1").toString();
if(!"".equals(((Map)resultValue).get("number2").toString())){
landNum += "-" + ((Map)resultValue).get("number2").toString();
}
model.setLandNum(landNum);
if(((Map)resultValue).containsKey("name")){
model.setLandNm(((Map)resultValue).get("name").toString());
}else{
model.setLandNm("");
}
model.setZipCd(((Map)((Map)resultValue).get("addition1")).get("value").toString());
model.setAreaType(((Map)((Map)resultValue).get("addition0")).get("type").toString());
model.setAreaNm(((Map)((Map)resultValue).get("addition0")).get("value").toString());
}
});
return model;
}
}

44
web/api-flight/src/main/java/kr/co/palnet/kac/api/external/service/TsService.java vendored

@ -0,0 +1,44 @@
package kr.co.palnet.kac.api.external.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@Service
@Slf4j
@RequiredArgsConstructor
public class TsService {
public byte[] createQrcode(String params) throws WriterException, IOException {
// 바코드 색상 값
// int qrcodeColor = 0xFF2e4e96;
int qrcodeColor = 0xFF000000;
// 배경 색상 값
int backgroundColor = 0xFFFFFFFF;
QRCodeWriter qrCodeWriter = new QRCodeWriter();
// 300x300
BitMatrix bitMatrix = qrCodeWriter.encode(params, BarcodeFormat.QR_CODE, 300, 300);
MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(qrcodeColor, backgroundColor);
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, matrixToImageConfig);
// ImageIO를 사용한 바코드 파일쓰기
// boolean png = ImageIO.write(bufferedImage, "png", new File("stoneQR2.png"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", outputStream);
return outputStream.toByteArray();
}
}

284
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/AirspaceUtils.java

@ -0,0 +1,284 @@
package kr.co.palnet.kac.api.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.opengis.feature.simple.SimpleFeature;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class AirspaceUtils {
private final String CLASS_PATH = "air/elev2d";
private final GeometryFactory geometryFactory = new GeometryFactory();
private List<FeatureInfo> airspaces;
private AirspaceUtils() {
// 초기화
log.info("===== AirspaceUtils init =====");
this.loadResourceAirspace();
}
public static AirspaceUtils getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
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;
Geometry targetGeometry = target.getGeometry();
for (FeatureInfo airspace : this.airspaces) {
Integer airspaceHighElev = airspace.getHighElev();
Geometry airspaceGeometry = airspace.getGeometry();
// 임시로 0~최대고도 기준으로 검증
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;
}
// get allowable elevation
public Integer getAllowElevation(Geometry target) {
Integer allowElevation = null;
if (this.airspaces == null || this.airspaces.isEmpty()) return null;
// target과 겹치는 airspace 조회
List<FeatureInfo> duplicationAirspace = this.airspaces.stream().filter(featureInfo -> {
Geometry featureGeometry = featureInfo.getGeometry();
return featureGeometry.intersects(target);
}).collect(Collectors.toList());
// 중복된 airspace가 없을 경우 기본 허용고도 반환 150m(관제권x)
if (duplicationAirspace.isEmpty()) return 150;
allowElevation = duplicationAirspace.stream().map(FeatureInfo::getHighElev).min(Integer::compareTo).orElse(150);
return allowElevation;
}
// convert coordiate to geometry
public Geometry createGeometryByCoordinate(List<Coordinate> target) {
return this.createGeometryByCoordinate(target, "Polygon");
}
// convert coordiate to geometry
public Geometry createGeometryByCoordinate(List<Coordinate> target, String type) {
Geometry geometry = null;
if ("Polygon".equals(type)) {
if (target == null || target.isEmpty()) return null;
log.info(">>> {}", target.get(0) != target.get(target.size() - 1));
if (target.get(0) != target.get(target.size() - 1)) {
target.add(target.get(0));
}
geometry = this.geometryFactory.createPolygon(target.toArray(new Coordinate[0]));
} else if ("LineString".equals(type)) {
geometry = this.geometryFactory.createLineString(target.toArray(new Coordinate[0]));
} else if ("Point".equals(type)) {
geometry = this.geometryFactory.createPoint(target.get(0));
}
return geometry;
}
// get geometry
private List<Geometry> getAirspaceGeometry() {
return this.airspaces.stream().map(FeatureInfo::getGeometry).collect(Collectors.toList());
}
// 파일에서 공역 데이터 가져와서 geometry로 변환 - 초기화.
private void loadResourceAirspace() {
List<FeatureInfo> featureInfos = new ArrayList<>();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = null;
try {
resources = resolver.getResources("classpath:" + CLASS_PATH + "/*-elev.json");
} catch (IOException e) {
log.warn("airspaces load error : {}", e.getMessage());
}
if (resources == null) {
log.info("airspace resources is null");
return;
}
for (Resource resource : resources) {
try (InputStream is = resource.getInputStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
List<FeatureInfo> fis = this.convertGeoJsonToGeometry(jsonObject);
featureInfos.addAll(fis);
} catch (Exception e) {
log.warn("airspace resource read error : {}", e.getMessage());
}
}
log.info(">>> featureInfos size : {}", featureInfos.size());
this.airspaces = featureInfos;
}
private List<FeatureInfo> convertGeoJsonToGeometry(JSONObject jsonObject) {
List<FeatureInfo> featureInfos = new ArrayList<>();
String type = (String) jsonObject.get("type");
if ("FeatureCollection".equals(type)) {
List<JSONObject> features = (List<JSONObject>) jsonObject.get("features");
// log.debug(">>> features size : {}", features.size());
for (JSONObject feature : features) {
JSONObject geometryObject = (JSONObject) feature.get("geometry");
String geometryType = String.valueOf(geometryObject.get("type"));
List<JSONObject> coordinatesObject = (List<JSONObject>) geometryObject.get("coordinates");
if ("Polygon".equals(geometryType)) {
List<JSONArray> innerObject = (List<JSONArray>) coordinatesObject.get(0);
JSONArray firstCoords = innerObject.get(0);
JSONArray lastCoords = innerObject.get(innerObject.size() - 1);
BigDecimal ff = new BigDecimal(String.valueOf(firstCoords.get(0)));
BigDecimal fl = new BigDecimal(String.valueOf(firstCoords.get(1)));
BigDecimal lf = new BigDecimal(String.valueOf(lastCoords.get(0)));
BigDecimal ll = new BigDecimal(String.valueOf(lastCoords.get(1)));
if (!ff.equals(lf) || !fl.equals(ll)) {
JSONObject propertiesObject = (JSONObject) feature.get("properties");
// String nameObject = String.valueOf(propertiesObject.get("name"));
// String descriptionObject = String.valueOf(propertiesObject.get("description"));
// log.info("coords first and last coords not eqauls : name/descriion = {}/{}", nameObject, descriptionObject);
innerObject.add(firstCoords);
}
}
try {
FeatureJSON featureJSON = new FeatureJSON();
SimpleFeature simpleFeature = null;
simpleFeature = featureJSON.readFeature(feature.toJSONString());
Boolean use = Boolean.valueOf(String.valueOf(simpleFeature.getAttribute("use")));
if (use) {
String name = String.valueOf(simpleFeature.getAttribute("name"));
String description = String.valueOf(simpleFeature.getAttribute("description"));
Integer lowElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("lowElev")));
Integer highElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("highElev")));
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry();
// log.debug(">>> name, description, use, lowElev, highElev : {}, {}, {}, {}, {}", name, description, use, lowElev, highElev);
FeatureInfo info = new FeatureInfo(name, description, lowElev, highElev, geometry);
featureInfos.add(info);
}
} catch (IOException e) {
log.error("geometry json read error : {}", e.getMessage());
}
}
} else if ("Feature".equals(type)) {
FeatureJSON featureJSON = new FeatureJSON();
try {
SimpleFeature simpleFeature = featureJSON.readFeature(jsonObject.toJSONString());
Boolean use = Boolean.valueOf(String.valueOf(simpleFeature.getAttribute("use")));
if (use) {
String name = String.valueOf(simpleFeature.getAttribute("name"));
String description = String.valueOf(simpleFeature.getAttribute("description"));
Integer lowElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("lowElev")));
Integer highElev = Integer.parseInt(String.valueOf(simpleFeature.getAttribute("highElev")));
Geometry geometry = (Geometry) simpleFeature.getDefaultGeometry();
FeatureInfo info = new FeatureInfo(name, description, lowElev, highElev, geometry);
featureInfos.add(info);
}
} catch (IOException e) {
log.error("geometry json read error : {}", e.getMessage());
}
} else {
GeometryJSON geoJson = new GeometryJSON();
try {
Geometry geometry = geoJson.read(jsonObject.toJSONString());
FeatureInfo info = new FeatureInfo(null, null, null, null, geometry);
} catch (IOException e) {
log.error("geometry json read error : {}", e.getMessage());
}
}
return featureInfos;
}
public int getSize() {
if(this.airspaces == null) return 0;
return this.airspaces.size();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class FeatureInfo {
private String name;
private String description;
private Integer lowElev;
private Integer highElev;
private Geometry geometry;
}
}

344
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/AreaUtils.java

@ -0,0 +1,344 @@
package kr.co.palnet.kac.api.util;
import kr.co.palnet.kac.api.util.model.FlightPlanAreaCoordModel;
import lombok.extern.slf4j.Slf4j;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.buffer.BufferParameters;
import org.locationtech.jts.util.GeometricShapeFactory;
import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.CRSFactory;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.locationtech.proj4j.ProjCoordinate;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Component
@Slf4j
public class AreaUtils {
private List<Polygon> polygons = new ArrayList<>();
private List<Point> points = new ArrayList<>();
private GeometryFactory geometryFactory = new GeometryFactory();
public AreaUtils() throws Exception {
this.init();
}
/**
* TODO 좌표계 변환
*
* @param coordList
* @return
*/
@Cacheable(value = "coordTransform")
public List<Coordinate> transform(List<Coordinate> coordList, String from, String to) {
CRSFactory factory = new CRSFactory();
CoordinateReferenceSystem srcCRS = factory.createFromName(from);
CoordinateReferenceSystem tgtCRS = factory.createFromName(to);
BasicCoordinateTransform transform = new BasicCoordinateTransform(srcCRS, tgtCRS);
List<Coordinate> result = new ArrayList<>();
for(Coordinate coord : coordList) {
ProjCoordinate projCoordinate = new ProjCoordinate(coord.getX(), coord.getY());
ProjCoordinate projTrasform = transform.transform(projCoordinate, new ProjCoordinate());
Coordinate target = new Coordinate(projTrasform.x, projTrasform.y);
result.add(target);
}
return result;
}
/**
* TODO 비행 구역 생성시 장애물 영역 포함 체크
*
* @param targetCoordList - 비행구역 좌표 리스트
* @return boolean - true(비정상), false(정상)
*/
public boolean overlaps(List<Coordinate> targetCoordList) {
boolean result = false;
targetCoordList.add(targetCoordList.get(0));
Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {}));
/* 공역 데이터 */
if(polygons.size() > 0) {
for(Polygon polygon : polygons) {
Geometry overlabsGeometry = geometryFactory.createGeometry(polygon);
Geometry targetGeometry = geometryFactory.createGeometry(targetPolygon);
boolean over = targetPolygon.overlaps(polygon);
if(over) {
result = true;
break;
}
}
}
return result;
}
/**
* TODO 구역 포함 여부
*
* @param targetCoordList - 생성 구역
* @param effectiveCoordList - 유효한 비행 구역
* @return boolean - true(비정상), false(정상)
*/
public boolean overlaps(List<Coordinate> targetCoordList, List<Coordinate> effectiveCoordList) {
targetCoordList.add(targetCoordList.get(0));
Polygon targetPolygon = geometryFactory.createPolygon(targetCoordList.toArray(new Coordinate[] {}));
effectiveCoordList.add(effectiveCoordList.get(0));
Polygon effectivePolygon = geometryFactory.createPolygon(effectiveCoordList.toArray(new Coordinate[] {}));
return targetPolygon.overlaps(effectivePolygon);
}
/**
* TODO 드론 관제시 정상 비행 체크 (공역)
*
* @param targetCoordinate - 드론 좌표 정보
* @return boolean - true(비정상), false(정상)
*/
public boolean contains(Coordinate targetCoordinate) {
boolean result = true;
Point target = geometryFactory.createPoint(targetCoordinate);
for(Polygon polygon : polygons) {
boolean contains = polygon.contains(target);
if(contains) {
result = true;
break;
}
}
return result;
}
/**
* TODO 드론 관제시 정상 비행 체크 (비행 구역)
*
* @param areaCoordList - 비행 구역 좌표 리스트
* @param targetCoordinate - 드론 좌표 정보
* @return boolean - true(비정상), false(정상)
*/
public boolean contains(List<Coordinate> areaCoordList, Coordinate targetCoordinate) {
boolean result = true;
areaCoordList.add(areaCoordList.get(0));
if(targetCoordinate != null) {
Polygon plan = geometryFactory.createPolygon(areaCoordList.toArray(new Coordinate[]{})); // 비행 구역
Point target = geometryFactory.createPoint(targetCoordinate);
result = plan.contains(target);
// target.contains(plan);
}
return result;
}
/**
* TODO 비행 구역 - Buffer 영역 생성
*
* @param coordList - 비행 구역 기초 좌표 리스트
* @param bufferZone - 반경
*
*/
public List<Coordinate> buffer(List<Coordinate> coordList, double bufferZone) {
List<Coordinate> bufferList = new ArrayList<>();
LineString line = geometryFactory.createLineString(coordList.toArray(new Coordinate[] {}));
Geometry geometry = geometryFactory.createGeometry(line);
// buffer
int nSegments = 10;
int cap = BufferParameters.CAP_SQUARE;
int join = BufferParameters.JOIN_ROUND;
BufferParameters bufferParam = new BufferParameters(nSegments, cap, join, join);
BufferOp ops = new BufferOp(geometry, bufferParam);
// Geometry bufTrans = ops.getResultGeometry((bufferZone/177763.63662580872)*2);
Geometry bufTrans = ops.getResultGeometry(bufferZone);
Coordinate[] coords = bufTrans.getCoordinates();
bufferList.addAll(Arrays.asList(coords));
return bufferList;
}
/**
* TODO 타원 생성
*
* @param CircleCoord
* @param BufferZone
* @return
*/
public List<Coordinate> createCircle(Coordinate CircleCoord, double BufferZone) {
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
double lng = CircleCoord.x;
double lat = CircleCoord.y;
double diameterInMeters = BufferZone;
shapeFactory.setCentre(new Coordinate(lng , lat));
shapeFactory.setHeight((diameterInMeters * 2) / 111320d);
shapeFactory.setWidth((diameterInMeters * 2) / (40075000 * Math.cos(Math.toRadians(lat)) / 360));
shapeFactory.setNumPoints(64);
final Polygon circle = shapeFactory.createCircle();
circle.setSRID(4326);
Geometry geometry = geometryFactory.createGeometry(circle);
Coordinate[] coords = geometry.getCoordinates();
List<Coordinate> coordList = new ArrayList<>();
coordList.addAll(Arrays.asList(coords));
return coordList;
}
/**
* TODO service model -> jts model mapping
*
* @param coordList
* @return
*/
public List<Coordinate> convertCoordinates(List<FlightPlanAreaCoordModel> coordList) {
List<Coordinate> coordinates = new ArrayList<>();
for(FlightPlanAreaCoordModel coord : coordList) {
Coordinate coordinate = new Coordinate(coord.getLon(), coord.getLat());
coordinates.add(coordinate);
}
return coordinates;
}
/**
* TODO jts model -> service model mapiing
*
* @param bufferList
* @return
*/
public List<FlightPlanAreaCoordModel> convertModel(List<Coordinate> bufferList) {
List<FlightPlanAreaCoordModel> bufferCoordList = new ArrayList<>();
for(Coordinate buffer : bufferList) {
FlightPlanAreaCoordModel bufferCoord = new FlightPlanAreaCoordModel();
bufferCoord.setLat(buffer.getY());
bufferCoord.setLon(buffer.getX());
bufferCoordList.add(bufferCoord);
}
return bufferCoordList;
}
// TODO 공역 데이터 생성
public void init() throws Exception {
// 1. file read
ClassPathResource resource = new ClassPathResource("air/airgeo.json");
InputStream jsonInputStream = resource.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(jsonInputStream, "UTF-8");
BufferedReader reader = new BufferedReader(inputStreamReader);
// 2. json parsing
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
List<JSONObject> features = (List<JSONObject>) jsonObject.get("features");
for(int i=0; i<features.size(); i++) {
JSONObject geometry = (JSONObject) features.get(i).get("geometry");
List<JSONArray> coordinates = (List<JSONArray>) geometry.get("coordinates");
String type = (String) geometry.get("type");
if("Polygon".equals(type)) {
for(JSONArray coordList : coordinates) {
List<Coordinate> polygonPaths = new ArrayList<>();
for(Object coord : coordList) {
Object y = ((JSONArray) coord).get(0);
Object x = ((JSONArray) coord).get(1);
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y);
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x);
Coordinate areaCoord = new Coordinate(lon, lat);
polygonPaths.add(areaCoord);
}
Polygon polygon = geometryFactory.createPolygon(polygonPaths.toArray(new Coordinate[] {}));
polygons.add(polygon);
}
}
if("LineString".equals(type)) {
List<Coordinate> lineStringPaths = new ArrayList<>();
for(JSONArray coordList : coordinates) {
Object y = coordList.get(0);
Object x = coordList.get(1);
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y);
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x);
Coordinate areaCoord = new Coordinate(lon, lat);
lineStringPaths.add(areaCoord);
}
Polygon polygon = geometryFactory.createPolygon(lineStringPaths.toArray(new Coordinate[] {}));
polygons.add(polygon);
}
if("Point".equals(type)) {
Object y = coordinates.get(0);
Object x = coordinates.get(1);
Double lon = y instanceof Double ? (Double) y : Double.valueOf((Long) y);
Double lat = x instanceof Double ? (Double) x : Double.valueOf((Long) x);
Coordinate areaCoord = new Coordinate(lon, lat);
Point point = geometryFactory.createPoint(areaCoord);
points.add(point);
}
}
}
public Geometry coordinateToGeometry(List<Coordinate> target) {
if (target == null || target.isEmpty()) return null;
log.info(">>> {}", target.get(0) != target.get(target.size() - 1));
if (target.get(0) != target.get(target.size() - 1)) {
target.add(target.get(0));
}
return geometryFactory.createPolygon(target.toArray(new Coordinate[]{}));
}
}

34
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/DateUtils.java

@ -0,0 +1,34 @@
package kr.co.palnet.kac.api.util;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateUtils {
private static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static String toDateString(LocalDate date){
return date.toString();
}
public static String toDateStringByFormat(LocalDate date, String format){
return date.format(DateTimeFormatter.ofPattern(format));
}
public static String toDateTimeString(LocalDateTime dateTime){
return dateTime.format(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_DATETIME_FORMAT));
}
public static String toDateTimeStringByFormat(LocalDateTime dateTime, String format){
return dateTime.format(DateTimeFormatter.ofPattern(format));
}
}

108
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/FileUtils.java

@ -0,0 +1,108 @@
package kr.co.palnet.kac.api.util;
import kr.co.palnet.kac.api.v1.flight.laanc.model.ComFileBasDTO;
import kr.co.palnet.kac.config.security.util.SessionHelper;
import kr.co.palnet.kac.api.util.constant.ExtensionConstant;
import kr.co.palnet.kac.api.util.model.LaancPdfModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
@Component
@RequiredArgsConstructor
@Slf4j
public class FileUtils {
private final PdfUtils pdfUtils;
private final String DOWNLOAD_URL = "/api/comn/file/download";
/**
* PDF 생성
*
* @param model
* @return
*/
public ComFileBasDTO makePdf(LaancPdfModel model) {
String airUser = model.getPilotName();
String etc = String.valueOf(System.currentTimeMillis()); // 동명이인 방지
String fileName = getLaancSaveName(ExtensionConstant.PDF, airUser, etc);
// TODO 추후 img tag의 src로 들어가는 이미지들을 base64로 변환하여 html에 넣어줘야함
// images 넣기(임시)
log.debug(">>> {}", model.getTemplate());
if ("laanc/official_document".equals(model.getTemplate())) {
System.out.println("!!!!! official_document.html");
String imgMlit = imagesToBase64ForSrc("templates/imgs/od-mlit.jpg");
model.setImgMlit(imgMlit);
String imgExpo = imagesToBase64ForSrc("templates/imgs/od-expo2030.png");
model.setImgExpo(imgExpo);
}
String htmlContent = pdfUtils.getHtmlToString(model);
// System.out.println(">>>" + htmlContent);
ComFileBasDTO comFileBasDto = pdfUtils.generatePDF(htmlContent, fileName);
String userId = SessionHelper.getUserId();
if (userId == null) userId = "NONE";
comFileBasDto.setCreateUserId(userId);
return comFileBasDto;
}
private String getLaancSaveName(ExtensionConstant extension, String... etcName) {
String date = DateUtils.toDateTimeStringByFormat(LocalDateTime.now(), "yyyyMMddHHmmss");
StringBuilder result = new StringBuilder();
result.append(date);
for (String name : etcName) {
result.append("-")
.append(name);
}
result.append(extension.extension);
return result.toString();
}
public String imagesToBase64ForSrc(String path) {
StringBuilder str = new StringBuilder();
ClassPathResource resource = new ClassPathResource(path);
String ext = "";
int lastIndex = path.lastIndexOf(".");
if (lastIndex >= 0) {
ext = path.substring(lastIndex + 1);
}
try (InputStream is = resource.getInputStream()) {
byte[] imageBytes = IOUtils.toByteArray(is);
String encodedString = java.util.Base64.getEncoder().encodeToString(imageBytes);
str
.append("data:image/")
.append(ext)
.append(";base64,")
.append(encodedString);
} catch (IOException e) {
throw new RuntimeException(e);
}
return str.toString();
}
public String getDownloadUrl(Long fileSno) {
if(fileSno == null) return null;
return this.DOWNLOAD_URL + "/" + fileSno;
}
}

35
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/HttpUtils.java

@ -0,0 +1,35 @@
package kr.co.palnet.kac.api.util;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Slf4j
public class HttpUtils {
/**
* 클라이언트 IP 가져온다
* @return 클라이언트 IP
*/
public static String getRequestIp() {
HttpServletRequest req = getCurrentRequest();
String[] HEADER_CLIENT_IP = { "NS-CLIENT-IP", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
for (String name : HEADER_CLIENT_IP) {
String clientIp = req.getHeader(name);
if(!StringUtils.isEmpty(clientIp) && !"unknown".equalsIgnoreCase(clientIp)) {
log.debug("{}={}", name, clientIp);
return clientIp;
}
}
return req.getRemoteAddr();
}
public static HttpServletRequest getCurrentRequest() {
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return sra.getRequest();
}
}

165
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/PdfUtils.java

@ -0,0 +1,165 @@
package kr.co.palnet.kac.api.util;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.font.FontProvider;
import kr.co.palnet.kac.api.v1.flight.laanc.model.ComFileBasDTO;
import kr.co.palnet.kac.api.util.constant.ExtensionConstant;
import kr.co.palnet.kac.api.util.model.PdfBaseModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
@Slf4j
@RequiredArgsConstructor
@Component
public class PdfUtils {
private final TemplateEngine templateEngine;
@Value("${url.base.file}")
private String BASE_PATH;
private final String PDF_FORDER_PATH = "od/";
/**
* Thymeleaf HTML 파일을 데이터 바인딩하여 String으로 변환
*
* @param <T>
* @param pdfDto
* @return
*/
public <T extends PdfBaseModel> String getHtmlToString(T pdfDto) {
Map<String, Object> param = pdfDto.getParam();
// Thymeleaf 방식 html에 입힐 데이터 바인딩
Context context = new Context();
for (Map.Entry<String, Object> entry : param.entrySet()) {
String key = entry.getKey();
context.setVariable(key, param.get(key));
}
// 앞 뒤 prefix, suffix는 yml에 정의해놓음
// html에 바인딩할 데이터 넣고 파싱이후 String형식으로 뽑아옴
String htmlContent = templateEngine.process(pdfDto.getTemplate(), context);
return htmlContent;
}
/**
* HTML 태그로 이루어진 String값을 PDF로 변환
*
* @param htmlContent
* @param fileName
* @return
*/
public ComFileBasDTO generatePDF(String htmlContent, String fileName) {
ComFileBasDTO result = new ComFileBasDTO();
String pdfPath = new StringBuilder()
.append(this.BASE_PATH)
.append(this.PDF_FORDER_PATH)
.append(LocalDate.now())
.append("/")
.toString();
String pdfFilePath = pdfPath + fileName;
File path = new File(pdfPath);
boolean mkdirs = path.mkdirs();
log.debug(">>> 폴더 생성여부 : {}", mkdirs);
// PDF 생성
try (FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath)) {
PdfWriter pdfWriter = new PdfWriter(fileOutputStream);
PdfDocument pdfDoc = new PdfDocument(pdfWriter);
ConverterProperties converterProperties = new ConverterProperties();
// FontProvider를 사용하여 한글 폰트 지정
FontProvider fontProvider = new FontProvider();
// NanumGothic은 한글 폰트
// fontProvider.addFont("templates/fonts/NanumGothic.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/NanumGothic-Bold.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/NanumGothic-ExtraBold.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/NanumGothic-Regular.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/hy-gothic.ttf", PdfEncodings.IDENTITY_H);
/*
fontName = "Dotum"
fullNameLowerCase = "dotum"
fontNameLowerCase = "dotum"
familyNameLowerCase = "dotum"
*/
fontProvider.addFont("templates/fonts/gulim003.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/gulim003.otf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/gulim003.woff", PdfEncodings.IDENTITY_H);
/*
fontName = "DotumChe"
fullNameLowerCase = "dotumche"
fontNameLowerCase = "dotumche"
familyNameLowerCase = "dotumche"
*/
fontProvider.addFont("templates/fonts/gulim004.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/gulim004.otf", PdfEncodings.IDENTITY_H);
/*
fontName = "H2gtrE"
fullNameLowerCase = "hygothic-extra"
fontNameLowerCase = "h2gtre"
familyNameLowerCase = "hygothic-extra"
*/
fontProvider.addFont("templates/fonts/H2GTRE.ttf", PdfEncodings.IDENTITY_H);
// fontProvider.addFont("templates/fonts/H2GTRE.otf", PdfEncodings.IDENTITY_H);
/*
fontName = "MalgunGothic"
fullNameLowerCase = "malgun gothic"
fontNameLowerCase = "malgungothic"
familyNameLowerCase = "malgun gothic"
*/
// fontProvider.addFont("templates/fonts/malgun.ttf", PdfEncodings.IDENTITY_H);
String defaultFontFamily = fontProvider.getDefaultFontFamily();
log.debug(">>> defaultFontFamily : {}", defaultFontFamily);
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(htmlContent, pdfDoc, converterProperties);
} catch (IOException e) {
throw new RuntimeException(e);
}
result.setFileGroupNo(0L);
result.setFilePath(pdfPath);
result.setFileExt(ExtensionConstant.PDF.extension);
result.setCreateDt(LocalDateTime.now());
result.setFileSaveNm(fileName);
result.setFileOriNm(fileName);
try {
String filePath = result.getFileOriNm();
long fileSize = Files.size(Paths.get(pdfPath + filePath)) / 1024;
if (fileSize >= 0) result.setFileSize(String.valueOf(fileSize));
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}

40
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/constant/ExtensionConstant.java

@ -0,0 +1,40 @@
package kr.co.palnet.kac.api.util.constant;
import java.util.HashSet;
public enum ExtensionConstant {
JPG(".jpg"),
PNG(".png"),
JPEG(".jpeg"),
PDF(".pdf"),
XLSX(".xlsx"),
XLS(".xls"),
HWPX(".hwpx"),
HWP(".hwp"),
;
public final String extension;
public HashSet<ExtensionConstant> hashExtension;
private ExtensionConstant(String extension) {
this.extension = extension;
}
public static ExtensionConstant fromExtension(String extension) {
try {
for (ExtensionConstant constant : ExtensionConstant.values()) {
if (constant.extension.equals(extension)) {
return constant;
}
}
} catch (Exception e) {
return null;
}
return null;
}
}

22
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/FlightPlanAreaCoordModel.java

@ -0,0 +1,22 @@
package kr.co.palnet.kac.api.util.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FlightPlanAreaCoordModel {
private Long planAreaCoordSno;
private Long planAreaSno;
@Schema(description = "x 좌표", example = "37.5208864")
private double lat;
@Schema(description = "y 좌표", example = "126.6071164")
private double lon;
@Schema(hidden = true)
private String createUserId;
@Schema(hidden = true)
private LocalDateTime createDt;
@Schema(hidden = true)
private String docState = "R";
}

61
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/LaancPdfModel.java

@ -0,0 +1,61 @@
package kr.co.palnet.kac.api.util.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.HashMap;
@Data
@Slf4j
@EqualsAndHashCode(callSuper = true)
public class LaancPdfModel extends PdfBaseModel {
private String pilotName; // 조종사 이름
private String birthDate; // 조종사 생년월일
private String schFltStDt; // 비행시작일시
private String schFltEndDt; // 비행종료일시
private String fltPurpose; // 비행목적
private String arcrftType; // 등록 종류
private String idntfNum; // 신고번호
private String address; // 주소
private String elev; // 고도
private String createDt; // 신청일자
// 정적 이미지
private String imgMlit;
private String imgExpo;
public LaancPdfModel(){
init();
}
public HashMap<String, Object> getParam(){
Field[] fields = getClass().getDeclaredFields();
HashMap<String, Object> result = new HashMap<>();
try {
for(Field field : fields){
Object value = field.get(this);
String key = field.getName();
result.put(key, value);
}
} catch (IllegalArgumentException | IllegalAccessException e) {
log.error("", e);
}
return result;
}
@Override
public void init() {
super.setTemplate("laanc/official_document");
}
}

16
web/api-flight/src/main/java/kr/co/palnet/kac/api/util/model/PdfBaseModel.java

@ -0,0 +1,16 @@
package kr.co.palnet.kac.api.util.model;
import lombok.Data;
import java.util.Map;
@Data
public abstract class PdfBaseModel {
private String template;
public abstract void init();
public abstract Map<String, Object> getParam();
}

104
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/controller/FlightLaancController.java

@ -0,0 +1,104 @@
package kr.co.palnet.kac.api.v1.flight.laanc.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CreateLaancPlanRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CreateLaancPlanRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.detail.SearchLaancAprvDetailRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.pliotvalid.PilotValidRs;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.SearchLaancAprvRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.SearchLaancAprvRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr.LaancTsQRcodeRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr.LaancTsQRcodeRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.valid.LaancAllowableElevationRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.valid.LaancAreaByAirspaceModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.valid.LaancAreaByElevModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.valid.LaancDuplicatedAirspaceRs;
import kr.co.palnet.kac.api.v1.flight.laanc.service.FlightLaancService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j
@RequestMapping("/v1/flight/laanc")
@RequiredArgsConstructor
@Tag(name = "비행 - Laanc", description = "Laanc 관련 API")
public class FlightLaancController {
private final FlightLaancService flightLaancService;
@PostMapping("/create/plan")
@Operation(summary = "비행계획서 생성", description = "비행계획서를 생성합니다.")
public ResponseEntity<CreateLaancPlanRS> createPlan(@RequestBody CreateLaancPlanRQ rq) {
CreateLaancPlanRS result = flightLaancService.createPlan(rq);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
}
@PostMapping("/ts/qr")
@Operation(summary = "TS QR 코드 생성", description = "조종사 자격증명 및 기체 보험 여부 등 조회하기 위한 QR 코드 생성합니다.")
public ResponseEntity<LaancTsQRcodeRS> createQRcode(LaancTsQRcodeRQ rq){
LaancTsQRcodeRS result = flightLaancService.createQRcode(rq);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
}
@GetMapping("/ts/qr/{confirmKey}")
@Operation(summary = "TS QR 코드 확인", description = "조종사 자격증명 및 기체 보험 여부 등 데이터를 받고 검증된 데이터인지 확인합니다.")
public ResponseEntity<PilotValidRs> checkQrcode(@PathVariable("confirmKey") String confirmKey) {
PilotValidRs result = flightLaancService.checkQrcode(confirmKey);
return ResponseEntity.ok().body(result);
}
@PostMapping("/valid/duplicated/airspace")
@Operation(summary = "공역(금지구역) 체크", description = "공역(금지구역)에 현좌표가 포함되어있는지 확인합니다.")
public ResponseEntity<List<LaancDuplicatedAirspaceRs>> getDuplicatedAirspace(@RequestBody List<LaancAreaByAirspaceModel> rq) {
List<LaancDuplicatedAirspaceRs> result = flightLaancService.getDuplicatedAirspace(rq);
return ResponseEntity.ok().body(result);
}
@PostMapping("/valid/elev")
@Operation(summary = "비행구역 허용고도 조회", description = "좌표에 해당하는 허용고도를 조회합니다.")
public ResponseEntity<LaancAllowableElevationRS> getAllowableElevation(@RequestBody List<LaancAreaByElevModel> rq){
LaancAllowableElevationRS result = flightLaancService.getAllowableElevation(rq);
return ResponseEntity.ok().body(result);
}
@GetMapping("/list")
@Operation(summary = "LAANC 승인 목록", description = "LAANC 승인 목록을 조회합니다.")
public ResponseEntity<List<SearchLaancAprvRS>> getLaancAprvList(SearchLaancAprvRQ rq){
List<SearchLaancAprvRS> result = flightLaancService.getLaancAprvList(rq);
return ResponseEntity.ok().body(result);
}
@GetMapping("/detail/{planSno}")
@Operation(summary = "LAANC 승인 상세 조회", description = "LAANC 승인 상세 조회합니다.")
@Parameter(name = "planSno", description = "LAANC 승인된 비행계획서 번호", required = true, example = "1")
public ResponseEntity<SearchLaancAprvDetailRS> getLaancAprvDetail(@PathVariable("planSno") Long planSno){
SearchLaancAprvDetailRS result = flightLaancService.getLaancAprvDetail(planSno);
return ResponseEntity.ok().body(result);
}
}

21
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/ComConfirmBasDTO.java

@ -0,0 +1,21 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ComConfirmBasDTO {
private Long confirmSno;
private String confirmKey; // 확인키
private String status; // 상태값 [ GENERATED, RECEIVED, CHECKED, FAILED, EXPIRED ]
private String targetType; // 대상구분
private String rqData; // RQ 데이터
private String rsData; // RS 데이터
private String rm; // 비고
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
private String updateUserId; // 수정사용자ID
private LocalDateTime updateDt; // 수정일시
}

45
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/ComFileBasDTO.java

@ -0,0 +1,45 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import kr.co.palnet.kac.data.com.domain.ComFileBas;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ComFileBasDTO {
private Long fileSno; // 파일일련번호
private Long fileGroupNo; // 파일그룹번호
private String fileSaveNm; // 저장된파일명
private String fileOriNm; // 실제파일명
private String filePath; // 파일저장경로
private String fileExt; // 파일확장명
private String fileSize; // 파일크기
private String delYn; // 삭제여부
private String delUserId; // 삭제사용자ID
private LocalDateTime delDt; // 삭제일시
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
public ComFileBas toEntity(){
return ComFileBas.builder()
.fileSno(this.getFileSno())
.fileGroupNo(this.getFileGroupNo())
.fileSaveNm(this.getFileSaveNm())
.fileOriNm(this.getFileOriNm())
.filePath(this.getFilePath())
.fileExt(this.getFileExt())
.fileSize(this.getFileSize())
.delYn(this.getDelYn())
.delUserId(this.getDelUserId())
.delDt(this.getDelDt())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.build();
}
}

113
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanArcrftDTO.java

@ -0,0 +1,113 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.ArcrftWghtCd;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancArcrftModel;
import kr.co.palnet.kac.data.flt.model.FltPlanArcrft;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class FltPlanArcrftDTO {
private Long planArcrftSno;
private Long planSno; // 비행계획서일련번호
private Long arcrftSno; // 기체일련번호
private String idntfNum; // 식별번호
private String groupNm; // 그룹명
private String prdctNum; // 제작번호
private String arcrftTypeCd; // 기체종류코드
private String arcrftModelNm; // 기체모델명
private String prdctCmpnNm; // 제작자
private LocalDate prdctDate; // 제작일자
private Double arcrftLngth; // 기체길이
private Double arcrftWdth; // 기체폭
private Double arcrftHght; // 기체높이
private Double arcrftWght; // 자체중량
private String arcrftWghtCd; // 자체중량코드
private String wghtTypeCd; // 중량구분코드
private String imageUrl; // 이미지URL
private Double takeoffWght; // 최대이륙중량
private String useYn; // 사용여부
private String cameraYn; // 카메라탑재여부
private String insrncYn; // 보험가입여부
private String acrftInsuranceYn; // 기체보험유무
private LocalDateTime insuranceExperiod; // 보험유효기간
private String corporationNm; // 법인명
private String ownerNm; // 소유자명
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
private String updateUserId; // 수정사용자ID
private LocalDateTime updateDt; // 수정일시
public static FltPlanArcrftDTO toDto(BasLaancArcrftModel model){
FltPlanArcrftDTO dto = new FltPlanArcrftDTO();
dto.setPlanArcrftSno(model.getPlanArcrftSno());
dto.setPlanSno(model.getPlanSno());
dto.setArcrftSno(model.getArcrftSno());
dto.setIdntfNum(model.getIdntfNum());
dto.setGroupNm(model.getGroupNm());
dto.setPrdctNum(model.getPrdctNum());
dto.setArcrftTypeCd(model.getArcrftTypeCd().getCode());
dto.setArcrftModelNm(model.getArcrftModelNm());
dto.setPrdctCmpnNm(model.getPrdctCmpnNm());
dto.setPrdctDate(model.getPrdctDate());
dto.setArcrftLngth(model.getArcrftLngth());
dto.setArcrftWdth(model.getArcrftWdth());
dto.setArcrftHght(model.getArcrftHght());
dto.setArcrftWght(model.getArcrftWght());
dto.setArcrftWghtCd(model.getArcrftWghtCd().getCode());
dto.setWghtTypeCd(model.getWghtTypeCd());
dto.setImageUrl(model.getImageUrl());
dto.setTakeoffWght(model.getTakeoffWght());
dto.setUseYn(model.getUseYn());
dto.setCameraYn(model.getCameraYn());
dto.setInsrncYn(model.getInsrncYn());
dto.setAcrftInsuranceYn(model.getAcrftInsuranceYn());
dto.setInsuranceExperiod(model.getInsuranceExperiod());
dto.setCorporationNm(model.getCorporationNm());
dto.setOwnerNm(model.getOwnerNm());
dto.setCreateUserId(model.getCreateUserId());
dto.setCreateDt(model.getCreateDt());
dto.setUpdateUserId(model.getUpdateUserId());
dto.setUpdateDt(model.getUpdateDt());
return dto;
}
public FltPlanArcrft toEntity(){
return FltPlanArcrft.builder()
.planArcrftSno(this.getPlanArcrftSno())
.planSno(this.getPlanSno())
.arcrftSno(this.getArcrftSno())
.idntfNum(this.getIdntfNum())
.groupNm(this.getGroupNm())
.prdctNum(this.getPrdctNum())
.arcrftTypeCd(this.getArcrftTypeCd())
.arcrftModelNm(this.getArcrftModelNm())
.prdctCmpnNm(this.getPrdctCmpnNm())
.prdctDate(this.getPrdctDate())
.arcrftLngth(this.getArcrftLngth())
.arcrftWdth(this.getArcrftWdth())
.arcrftHght(this.getArcrftHght())
.arcrftWght(this.getArcrftWght())
.arcrftWghtCd(this.getArcrftWghtCd())
.wghtTypeCd(this.getWghtTypeCd())
.imageUrl(this.getImageUrl())
.takeoffWght(this.getTakeoffWght())
.useYn(this.getUseYn())
.cameraYn(this.getCameraYn())
.insrncYn(this.getInsrncYn())
.acrftInsuranceYn(this.getAcrftInsuranceYn())
.insuranceExperiod(this.getInsuranceExperiod())
.corporationNm(this.getCorporationNm())
.ownerNm(this.getOwnerNm())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.updateUserId(this.getUpdateUserId())
.updateDt(this.getUpdateDt())
.build();
}
}

43
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanAreaCoordDTO.java

@ -0,0 +1,43 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancAreaCoordModel;
import kr.co.palnet.kac.data.flt.model.FltPlanAreaCoord;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FltPlanAreaCoordDTO {
private Long planAreaCoordSno;
private Long planAreaSno; // 비행계획비행구역일련번호
private Double lon; // 위도
private Double lat; // 경도
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
public static FltPlanAreaCoordDTO toDto(BasLaancAreaCoordModel model){
FltPlanAreaCoordDTO dto = new FltPlanAreaCoordDTO();
dto.setPlanAreaCoordSno(model.getPlanAreaCoordSno());
dto.setPlanAreaSno(model.getPlanAreaSno());
dto.setLon(model.getLon());
dto.setLat(model.getLat());
dto.setCreateUserId(model.getCreateUserId());
dto.setCreateDt(model.getCreateDt());
return dto;
}
public FltPlanAreaCoord toEntity(){
return FltPlanAreaCoord.builder()
.planAreaCoordSno(this.getPlanAreaCoordSno())
.planAreaSno(this.getPlanAreaSno())
.lon(this.getLon())
.lat(this.getLat())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.build();
}
}

60
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanAreaDTO.java

@ -0,0 +1,60 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltMethod;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancAreaModel;
import kr.co.palnet.kac.data.flt.model.FltPlanArea;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FltPlanAreaDTO {
private Long planAreaSno;
private Long planSno; // 비행계획서일련번호
private String areaType; // 구역종류
private FltMethod fltMethod; // 비행방식
private String fltMothoeRm; // 비행방식비고
private String fltAreaAddr; // 비행구역주소
private Integer bufferZone; // 버퍼존
private String fltElev; // 비행고도
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
private String updateUserId; // 수정사용자ID
private LocalDateTime updateDt; // 수정일시
public static FltPlanAreaDTO toDto(BasLaancAreaModel model){
FltPlanAreaDTO dto = new FltPlanAreaDTO();
dto.setPlanAreaSno(model.getPlanAreaSno());
dto.setPlanSno(model.getPlanSno());
dto.setAreaType(model.getAreaType());
dto.setFltMethod(model.getFltMethod());
dto.setFltMothoeRm(model.getFltMothoeRm());
dto.setFltAreaAddr(model.getFltAreaAddr());
dto.setBufferZone(model.getBufferZone());
dto.setFltElev(model.getFltElev());
dto.setCreateUserId(model.getCreateUserId());
dto.setCreateDt(model.getCreateDt());
dto.setUpdateUserId(model.getUpdateUserId());
dto.setUpdateDt(model.getUpdateDt());
return dto;
}
public FltPlanArea toEntity(){
return FltPlanArea.builder()
.planAreaSno(this.getPlanAreaSno())
.planSno(this.getPlanSno())
.areaType(this.getAreaType())
.fltMethod(this.getFltMethod().getCode())
.fltMothoeRm(this.getFltMothoeRm())
.fltAreaAddr(this.getFltAreaAddr())
.bufferZone(this.getBufferZone())
.fltElev(this.getFltElev())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.updateUserId(this.getUpdateUserId())
.updateDt(this.getUpdateDt())
.build();
}
}

119
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanBasDTO.java

@ -0,0 +1,119 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltPurpose;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltType;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CreateLaancPlanRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CstmrModel;
import kr.co.palnet.kac.data.flt.model.FltPlanBas;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FltPlanBasDTO {
private Long planSno;
private String groupId; // 그룹ID
private Long cstmrSno; // 고객일련번호
private String serviceType; // 서비스구분
private String memberName; // 회원이름
private String email; // 이메일
private String hpno; // 휴대폰번호
private String clncd; // 국가전화번호
private String addr; // 주소
private String addrDtlCn; // 주소상세내용
private String zip; // 우편번호
private LocalDateTime schFltStDt; // 예정비행시작시간
private LocalDateTime schFltEndDt; // 예정비행종료시간
private FltPurpose fltPurpose; // 비행목적
private FltType fltType; // 비행유형
private String corpRegYn; // 사업자여부
private String aprvlYn; // 승인여부
private LocalDateTime aprvlDt; // 승인일시
private String delYn; // 삭제여부
private Long fileGroupNo; // 파일그룹번호
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
private String updateUserId; // 수정사용자ID
private LocalDateTime updateDt; // 수정일시
public static FltPlanBasDTO toFltPlanBasDto(CstmrModel model, CreateLaancPlanRQ rq){
FltPlanBasDTO dto = new FltPlanBasDTO();
dto.setCstmrSno(model.getCstmrSno());
dto.setMemberName(model.getMemberName());
dto.setEmail(model.getEmail());
dto.setHpno(model.getHpno());
dto.setClncd(model.getClncd());
dto.setAddr(model.getAddr());
dto.setAddrDtlCn(model.getAddrDtlCn());
dto.setZip(model.getZip());
dto.setSchFltStDt(rq.getSchFltStDt());
dto.setSchFltEndDt(rq.getSchFltEndDt());
dto.setFltPurpose(rq.getFltPurpose());
dto.setFltType(rq.getFltType());
return dto;
}
public static FltPlanBasDTO toFltPlanBasDto(FltPlanBas entity){
FltPlanBasDTO dto = new FltPlanBasDTO();
dto.setPlanSno(entity.getPlanSno());
dto.setGroupId(entity.getGroupId());
dto.setCstmrSno(entity.getCstmrSno());
dto.setServiceType(entity.getServiceType());
dto.setMemberName(entity.getMemberName());
dto.setEmail(entity.getEmail());
dto.setHpno(entity.getHpno());
dto.setClncd(entity.getClncd());
dto.setAddr(entity.getAddr());
dto.setAddrDtlCn(entity.getAddrDtlCn());
dto.setZip(entity.getZip());
dto.setSchFltStDt(entity.getSchFltStDt());
dto.setSchFltEndDt(entity.getSchFltEndDt());
dto.setFltPurpose(FltPurpose.fromCode(entity.getFltPurpose()));
dto.setFltType(FltType.fromCode(entity.getFltType()));
dto.setCorpRegYn(entity.getCorpRegYn());
dto.setAprvlYn(entity.getAprvlYn());
dto.setAprvlDt(entity.getAprvlDt());
dto.setDelYn(entity.getDelYn());
dto.setFileGroupNo(entity.getFileGroupNo());
dto.setCreateUserId(entity.getCreateUserId());
dto.setCreateDt(entity.getCreateDt());
dto.setUpdateUserId(entity.getUpdateUserId());
dto.setUpdateDt(entity.getUpdateDt());
return dto;
}
public FltPlanBas toFltPlanEntity(){
return FltPlanBas.builder()
.planSno(this.getPlanSno())
.groupId(this.getGroupId())
.cstmrSno(this.getCstmrSno())
.serviceType(this.getServiceType())
.memberName(this.getMemberName())
.email(this.getEmail())
.hpno(this.getHpno())
.clncd(this.getClncd())
.addr(this.getAddr())
.addrDtlCn(this.getAddrDtlCn())
.zip(this.getZip())
.schFltStDt(this.getSchFltStDt())
.schFltEndDt(this.getSchFltEndDt())
.fltPurpose(this.getFltPurpose().getCode())
.fltType(this.getFltType().getCode())
.corpRegYn(this.getCorpRegYn())
.aprvlYn(this.getAprvlYn())
.aprvlDt(this.getAprvlDt())
.delYn(this.getDelYn())
.fileGroupNo(this.getFileGroupNo())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.updateUserId(this.getUpdateUserId())
.updateDt(this.getUpdateDt())
.build();
}
}

87
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/FltPlanPilotDTO.java

@ -0,0 +1,87 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CstmrModel;
import kr.co.palnet.kac.data.flt.model.FltPlanPilot;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class FltPlanPilotDTO {
private Long planPilotSno;
private Long planSno; // 비행계획서일련번호
private Long cstmrSno; // 고객일련번호
private String groupNm; // 그룹명
private String memberName; // 회원이름
private String email; // 이메일
private String hpno; // 휴대폰번호
private String clncd; // 국가전화번호
private String addr; // 주소
private String addrDtlCn; // 주소상세내용
private String zip; // 우편번호
private String qlfcNo; // 자격번호
private String carrer; // 경력
private String createUserId; // 생성사용자ID
private LocalDateTime createDt; // 생성일시
private String updateUserId; // 수정사용자ID
private LocalDateTime updateDt; // 수정일시
public static FltPlanPilotDTO toDto(CstmrModel model){
FltPlanPilotDTO dto = new FltPlanPilotDTO();
dto.setCstmrSno(model.getCstmrSno());
dto.setMemberName(model.getMemberName());
dto.setClncd(model.getClncd());
dto.setAddr(model.getAddr());
dto.setAddrDtlCn(model.getAddrDtlCn());
dto.setZip(model.getZip());
return dto;
}
public static FltPlanPilotDTO toDto(FltPlanPilot entity){
FltPlanPilotDTO dto = new FltPlanPilotDTO();
dto.setPlanPilotSno(entity.getPlanPilotSno());
dto.setPlanSno(entity.getPlanSno());
dto.setCstmrSno(entity.getCstmrSno());
dto.setGroupNm(entity.getGroupNm());
dto.setMemberName(entity.getMemberName());
dto.setEmail(entity.getEmail());
dto.setHpno(entity.getHpno());
dto.setClncd(entity.getClncd());
dto.setAddr(entity.getAddr());
dto.setAddrDtlCn(entity.getAddrDtlCn());
dto.setZip(entity.getZip());
dto.setQlfcNo(entity.getQlfcNo());
dto.setCarrer(entity.getCarrer());
dto.setCreateUserId(entity.getCreateUserId());
dto.setCreateDt(entity.getCreateDt());
dto.setUpdateUserId(entity.getUpdateUserId());
dto.setUpdateDt(entity.getUpdateDt());
return dto;
}
public FltPlanPilot toEntity(){
return FltPlanPilot.builder()
.planPilotSno(this.getPlanPilotSno())
.planSno(this.getPlanSno())
.cstmrSno(this.getCstmrSno())
.groupNm(this.getGroupNm())
.memberName(this.getMemberName())
.email(this.getEmail())
.hpno(this.getHpno())
.clncd(this.getClncd())
.addr(this.getAddr())
.addrDtlCn(this.getAddrDtlCn())
.zip(this.getZip())
.qlfcNo(this.getQlfcNo())
.carrer(this.getCarrer())
.createUserId(this.getCreateUserId())
.createDt(this.getCreateDt())
.updateUserId(this.getUpdateUserId())
.updateDt(this.getUpdateDt())
.build();
}
}

38
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/PtyTermsAgreeTxnDTO.java

@ -0,0 +1,38 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import kr.co.palnet.kac.data.pty.model.PtyTermsAgreeTxn;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class PtyTermsAgreeTxnDTO {
private Long agreeSno; // 동의일련번호
private Long termsSno; // 약관일련번호
private Long cstmrSno; // 고객일련번호
private String agreeYn; // 동의여부
private LocalDateTime agreeDt; // 동의일시
private String procIp; // 처리IP주소
private LocalDateTime updateDt; // 수정일시
private String updateUserId; // 수정사용자ID
public PtyTermsAgreeTxn toEntity(){
return PtyTermsAgreeTxn.builder()
.agreeSno(this.getAgreeSno())
.termsSno(this.getTermsSno())
.cstmrSno(this.getCstmrSno())
.agreeYn(this.getAgreeYn())
.agreeDt(this.getAgreeDt())
.procIp(this.getProcIp())
.updateDt(this.getUpdateDt())
.updateUserId(this.getUpdateUserId())
.build();
}
}

127
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/SuredataEntityDTO.java

@ -0,0 +1,127 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model;
import jakarta.persistence.*;
import kr.co.palnet.kac.data.other.model.SuredataEntity;
import lombok.Data;
import org.hibernate.annotations.ColumnDefault;
@Data
public class SuredataEntityDTO {
private Long seqno;
private String intime; // date_format(now(), '%y%m%d%H%i%s')
private String usercode;
private String deptcode;
private String biztype;
private String yellowidKey;
private String reqname;
private String reqphone;
private String callname;
private String country;
private String callphone;
private String subject;
private String msg;
private String reqtime;
private String senttime;
private String recvtime;
private String result;
private Integer errcode;
private String kind;
private Integer fkcontent;
private String imageUrl;
private Integer batchflag;
private Integer retry;
private String resend;
private String templatecode;
private String retext;
private String resentflag;
private String sentmedia;
private String mediatype;
private String btnType01;
private String btnNm01;
private String btn01Url01;
private String btn01Url02;
private String btnType02;
private String btnNm02;
private String btn02Url01;
private String btn02Url02;
private String btnType03;
private String btnNm03;
private String btn03Url01;
private String btn03Url02;
private String btnType04;
private String btnNm04;
private String btn04Url01;
private String btn04Url02;
private String btnType05;
private String btnNm05;
private String btn05Url01;
private String btn05Url02;
private String kakaoerrcode;
private String etc1;
private String etc2;
private String etc3;
private String etc4;
private String etc5;
public SuredataEntity toEntity(){
return SuredataEntity.builder()
.seqno(this.getSeqno())
.intime(this.getIntime())
.usercode(this.getUsercode())
.deptcode(this.getDeptcode())
.biztype(this.getBiztype())
.yellowidKey(this.getYellowidKey())
.reqname(this.getReqname())
.reqphone(this.getReqphone())
.callname(this.getCallname())
.country(this.getCountry())
.callphone(this.getCallphone())
.subject(this.getSubject())
.msg(this.getMsg())
.reqtime(this.getReqtime())
.senttime(this.getSenttime())
.recvtime(this.getRecvtime())
.result(this.getResult())
.errcode(this.getErrcode())
.kind(this.getKind())
.fkcontent(this.getFkcontent())
.imageUrl(this.getImageUrl())
.batchflag(this.getBatchflag())
.retry(this.getRetry())
.resend(this.getResend())
.templatecode(this.getTemplatecode())
.retext(this.getRetext())
.resentflag(this.getResentflag())
.sentmedia(this.getSentmedia())
.mediatype(this.getMediatype())
.btnType01(this.getBtnType01())
.btnNm01(this.getBtnNm01())
.btn02Url01(this.getBtn02Url01())
.btn02Url02(this.getBtn02Url02())
.btnType02(this.getBtnType02())
.btnNm02(this.getBtnNm02())
.btn02Url01(this.getBtn01Url01())
.btn02Url02(this.getBtn01Url02())
.btnType03(this.getBtnType03())
.btnNm03(this.getBtnNm03())
.btn03Url01(this.getBtn03Url01())
.btn03Url02(this.getBtn03Url02())
.btnType04(this.getBtnType04())
.btnNm04(this.getBtnNm04())
.btn04Url01(this.getBtn04Url01())
.btn04Url02(this.getBtn04Url02())
.btnType05(this.getBtnType05())
.btnNm05(this.getBtnNm05())
.btn05Url01(this.getBtn05Url01())
.btn05Url02(this.getBtn05Url02())
.kakaoerrcode(this.getKakaoerrcode())
.etc1(this.getEtc1())
.etc2(this.getEtc2())
.etc3(this.getEtc3())
.etc4(this.getEtc4())
.etc5(this.getEtc5())
.build();
}
}

31
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/ArcrftTypeCd.java

@ -0,0 +1,31 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.constant;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public enum ArcrftTypeCd {
UNMANNED_AIRCRAFT("11", "무인비행기"),
UNMANNED_HELICOPTER("12", "무인헬리콤터"),
UNMANNED_MULTICOPTER("13", "무인멀티콥터"),
UNMANNED_AIRSHIP("21", "무인비행선");
private final String code;
private final String value;
ArcrftTypeCd(String code, String value) {
this.code = code;
this.value = value;
}
@JsonCreator
public static ArcrftTypeCd fromCode(String node) {
for (ArcrftTypeCd arcrftTypeCd : ArcrftTypeCd.values()) {
if (arcrftTypeCd.getCode().equals(node)) {
return arcrftTypeCd;
}
}
return null;
}
}

34
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/ArcrftWghtCd.java

@ -0,0 +1,34 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.constant;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public enum ArcrftWghtCd {
W250G_LOE("7", "최대이륙중량 250g 이하"),
W250G_W2KG("8", "최대이륙중량 250g 초과 ~ 2kg 이하"),
W2KG_W7KG("9", "최대이륙중량 2kg 초과 ~ 7kg 이하"),
W7KG_W25KG("10", "최대이륙중량 7kg 초과 ~ 25kg 이하"),
W25KG_GO("11", "최대이륙중량 25kg 초과"),
W25KG_GO_TEST("12", "최대이륙중량 25kg 초과 (시험비행)"),
;
private final String code;
private final String value;
ArcrftWghtCd(String code, String value) {
this.code = code;
this.value = value;
}
@JsonCreator
public static ArcrftWghtCd fromCode(String node) {
for (ArcrftWghtCd arcrftWghtCd : ArcrftWghtCd.values()) {
if (arcrftWghtCd.getCode().equals(node)) {
return arcrftWghtCd;
}
}
return null;
}
}

38
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltMethod.java

@ -0,0 +1,38 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.constant;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public enum FltMethod {
CLOCK_FLIGHT("01", "시계비행"),
AUTOMATIC_FLIGHT("02", "자동비행"),
CIRCLING_FLIGHT("03", "선회비행"),
INSTRUMENTAL_FLIGHT("04", "계기비행"),
GRID_FLIGHT("05", "격자비행"),
VERTICAL_TAKEOFF_AND_LANDING_FLIGHT("06", "수직이착륙비행"),
VISIBLE_FLIGHT("07", "가시권비행"),
HAND_OPERATED_FLIGHT("08", "수동조종비행"),
FLIGHT_IN_PLACE("09", "제자리비행"),
CLUSTER_FLIGHT("10", "군집비행"),
DIRECT_INPUT("11", "직접입력");
private final String code;
private final String value;
FltMethod(String code, String value) {
this.code = code;
this.value = value;
}
@JsonCreator
public static FltMethod fromCode(String node) {
for (FltMethod fltMethod : FltMethod.values()) {
if (fltMethod.getCode().equals(node)) {
return fltMethod;
}
}
return null;
}
}

44
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltPurpose.java

@ -0,0 +1,44 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.constant;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public enum FltPurpose {
AIR_CONTROL("01","항공방제"),
TRAFFIC_MANAGEMENT("02","교통관리"),
LEISURE_FLIGHT("03","레저비행"),
TEST_FLIGHT("04","시험비행"),
AIR_ADVERTISING("05", "공중광고"),
EDUCATION_FLIGHT("06","교육비행"),
FLIGHT_DEMONSTRATION("07","비행시연"),
PESTICIDE_SPRAY("08","농약살포"),
FOREST_OBSERVATION("09","산림관측"),
TRANSPORTATION("10","수송"),
PHOTOGRAPHY_VIDEO_SHOOTING("11","사진/영상촬영"),
SEARCH_AND_RESCUE("12","수색구조"),
FLIGHT_TRAINING("13","비행훈련"),
FLIGHT_EDUCATION("14","비행교육"),
PILOT_FLIGHT("15","계도비행"),
AIR_SURVEYING("16","항공측량"),
FLIGHT_TEST("17","비행실기시험");
private final String code;
private final String value;
FltPurpose(String code, String value) {
this.code = code;
this.value = value;
}
@JsonCreator
public static FltPurpose fromCode(String node) {
for (FltPurpose fltPurpose : FltPurpose.values()) {
if (fltPurpose.getCode().equals(node)) {
return fltPurpose;
}
}
return null;
}
}

30
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/constant/FltType.java

@ -0,0 +1,30 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.constant;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public enum FltType {
COMMERCIAL("COMMERCIAL", "상업용"),
NON_COMMERCIAL("NON_COMMERCIAL", "비상업용");
private final String code;
private final String value;
FltType(String code, String value) {
this.code = code;
this.value = value;
}
@JsonCreator
public static FltType fromCode(String node) {
for (FltType fltType : FltType.values()) {
if (fltType.getCode().equals(node)) {
return fltType;
}
}
return null;
}
}

13
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/AnctCstmrTermsModel.java

@ -0,0 +1,13 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class AnctCstmrTermsModel {
@Schema(description = "약관 일련번호", example = "1")
private Long termsSno;
@Schema(description = "동의여부", example = "Y")
private String agreeYn;
}

144
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancArcrftModel.java

@ -0,0 +1,144 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.ArcrftTypeCd;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.ArcrftWghtCd;
import kr.co.palnet.kac.data.flt.model.FltPlanArcrft;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class BasLaancArcrftModel {
@Schema(description = "계획서 기체 일련번호", example = "1", hidden = true)
private Long planArcrftSno;
@Schema(description = "비행계획서 일련번호", example = "1", hidden = true)
private Long planSno;
@Schema(description = "기체 일련번호", example = "1", hidden = true)
private Long arcrftSno;
@Schema(description = "식별번호(기체번호)", example = "PA0001")
private String idntfNum;
@Schema(description = "그룹명", example = "한국공항공사", hidden = true)
private String groupNm;
@Schema(description = "제작번호", example = "123101-13", hidden = true)
private String prdctNum;
@Schema(description = "기체종류코드", example = "01", hidden = true)
private ArcrftTypeCd arcrftTypeCd;
@Schema(description = "기체모델명", example = "M-01", hidden = true)
private String arcrftModelNm;
@Schema(description = "제작자", example = "DJI", hidden = true)
private String prdctCmpnNm;
@Schema(description = "제작일자", example = "2022-01-01", hidden = true)
private LocalDate prdctDate;
@Schema(description = "기체길이", example = "1.0", hidden = true)
private double arcrftLngth;
@Schema(description = "길체폭", example = "1.1", hidden = true)
private double arcrftWdth;
@Schema(description = "기체높이", example = "1.0", hidden = true)
private double arcrftHght;
@Schema(description = "기체중량", example = "1.5", hidden = true)
private double arcrftWght;
@Schema(description = "중량구분코드", hidden = true)
private String wghtTypeCd;
@Schema(description = "이미지URL", example = "http://www.imageurl.co.kr/image/url", hidden = true)
private String imageUrl;
@Schema(description = "최대이륙중량", example = "10", hidden = true)
private double takeoffWght;
@Schema(description = "사용여부", hidden = true)
private String useYn;
@Schema(description = "카메라탑재여부", example = "N")
private String cameraYn;
@Schema(description = "보험가입여부", example = "Y")
private String insrncYn;
@Schema(description = "소유자명(법인명)", example = "팔네트웍스")
private String ownerNm;
@Schema(description = "생성자ID", hidden = true)
private String createUserId;
@Schema(description = "생성일시", hidden = true)
private LocalDateTime createDt;
@Schema(description = "수정자ID", hidden = true)
private String updateUserId;
@Schema(description = "수정일시", hidden = true)
private LocalDateTime updateDt;
@Schema(hidden = true)
private String docState = "R";
@Schema(description = "식별장치종류코드", example = "DRON", hidden = true)
private String idntfTypeCd;
// kac 추가 필드
@Schema(description = "기체보험유무", example = "Y")
private String acrftInsuranceYn;
@Schema(description = "보험유효기간", hidden = true)
private LocalDateTime insuranceExperiod;
@Schema(description = "법인명", hidden = true)
private String corporationNm;
@Schema(description = "자체중량코드", example = "10")
private ArcrftWghtCd arcrftWghtCd; // 기체 무게 코드 ----
public static BasLaancArcrftModel toModel(FltPlanArcrft entity){
BasLaancArcrftModel model = new BasLaancArcrftModel();
model.setPlanArcrftSno(entity.getPlanArcrftSno());
model.setPlanSno(entity.getPlanSno());
model.setArcrftSno(entity.getArcrftSno());
model.setIdntfNum(entity.getIdntfNum());
model.setGroupNm(entity.getGroupNm());
model.setPrdctNum(entity.getPrdctNum());
model.setArcrftTypeCd(ArcrftTypeCd.fromCode(entity.getArcrftTypeCd()));
model.setArcrftModelNm(entity.getArcrftModelNm());
model.setPrdctCmpnNm(entity.getPrdctCmpnNm());
model.setPrdctDate(entity.getPrdctDate());
model.setArcrftLngth(entity.getArcrftLngth());
model.setArcrftWdth(entity.getArcrftWdth());
model.setArcrftHght(entity.getArcrftHght());
model.setArcrftWght(entity.getArcrftWght());
model.setWghtTypeCd(entity.getWghtTypeCd());
model.setImageUrl(entity.getImageUrl());
model.setTakeoffWght(entity.getTakeoffWght());
model.setUseYn(entity.getUseYn());
model.setCameraYn(entity.getCameraYn());
model.setInsrncYn(entity.getInsrncYn());
model.setOwnerNm(entity.getOwnerNm());
model.setCreateUserId(entity.getCreateUserId());
model.setCreateDt(entity.getCreateDt());
model.setUpdateUserId(entity.getUpdateUserId());
model.setUpdateDt(entity.getUpdateDt());
model.setDocState(entity.getArcrftModelNm());
model.setAcrftInsuranceYn(entity.getAcrftInsuranceYn());
model.setInsuranceExperiod(entity.getInsuranceExperiod());
model.setCorporationNm(entity.getCorporationNm());
model.setArcrftWghtCd(ArcrftWghtCd.fromCode(entity.getArcrftWghtCd()));
return model;
}
}

44
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancAreaCoordModel.java

@ -0,0 +1,44 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.data.flt.model.FltPlanAreaCoord;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BasLaancAreaCoordModel {
@Schema(description = "비행구역좌표 일련번호", example = "1")
private Long planAreaCoordSno;
@Schema(description = "비행계획비행구역 일련번호", example = "1")
private Long planAreaSno;
@Schema(description = "위도", example = "127.33")
private double lat;
@Schema(description = "경도", example = "37.99")
private double lon;
@Schema(description = "생성자ID", hidden = true)
private String createUserId;
@Schema(description = "생성일시", hidden = true)
private LocalDateTime createDt;
@Schema(hidden = true)
private String docState = "R";
public static BasLaancAreaCoordModel toModel(FltPlanAreaCoord entity){
BasLaancAreaCoordModel model = new BasLaancAreaCoordModel();
model.setPlanAreaCoordSno(entity.getPlanAreaCoordSno());
model.setPlanAreaSno(entity.getPlanAreaSno());
model.setLat(entity.getLat());
model.setLon(entity.getLon());
model.setCreateUserId(entity.getCreateUserId());
model.setCreateDt(entity.getCreateDt());
return model;
}
}

76
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/BasLaancAreaModel.java

@ -0,0 +1,76 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltMethod;
import kr.co.palnet.kac.data.flt.model.FltPlanArea;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class BasLaancAreaModel {
@Schema(description = "비행구역 일련번호", example = "1", hidden = true)
private Long planAreaSno;
@Schema(description = "비행계획서 일련번호", example = "1", hidden = true)
private Long planSno;
@Schema(description = "구역종류", example = "CIRCLE")
private String areaType;
@Schema(description = "비행방식", example = "01")
private FltMethod fltMethod;
@Schema(description = "비행구역주소", example = "인천광역시 부평구 청천2동")
private String fltAreaAddr;
@Schema(description = "버퍼존", example = "100")
private Integer bufferZone;
@Schema(description = "고도", example = "110")
private String fltElev;
@Schema(description = "생성자ID", hidden = true)
private String createUserId;
@Schema(description = "생성일시", hidden = true)
private LocalDateTime createDt;
@Schema(description = "수정자ID", hidden = true)
private String updateUserId;
@Schema(description = "수정일시", hidden = true)
private LocalDateTime updateDt;
private String docState = "R";
private List<BasLaancAreaCoordModel> coordList;
@Schema(hidden = true)
private List<BasLaancAreaCoordModel> bufferCoordList;
// kac 추가 필드
@Schema(description = "비행방식(기타)")
private String fltMothoeRm;
public static BasLaancAreaModel toModel(FltPlanArea entity){
BasLaancAreaModel model = new BasLaancAreaModel();
model.setPlanAreaSno(entity.getPlanAreaSno());
model.setPlanSno(entity.getPlanSno());
model.setAreaType(entity.getAreaType());
model.setFltMethod(FltMethod.fromCode(entity.getFltMethod()));
model.setFltAreaAddr(entity.getFltAreaAddr());
model.setBufferZone(entity.getBufferZone());
model.setFltElev(entity.getFltElev());
model.setCreateUserId(entity.getCreateUserId());
model.setCreateDt(entity.getCreateDt());
model.setUpdateUserId(entity.getUpdateUserId());
model.setUpdateDt(entity.getUpdateDt());
model.setDocState(entity.getAreaType());
model.setFltMothoeRm(entity.getFltMothoeRm());
return model;
}
}

53
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CreateLaancPlanRQ.java

@ -0,0 +1,53 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltPurpose;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltType;
import kr.co.palnet.kac.api.v1.flight.laanc.model.pliotvalid.PilotValidRs;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class CreateLaancPlanRQ {
@Schema(description = "비행계획서 일련번호", example = "1", hidden = true)
private Long planSno;
@Schema(description = "사용자 일련번호", example = "1", hidden = true)
private Long cstmrSno;
@Schema(description = "이름", example = "조종사")
private String memberName;
@Schema(description = "비행유형", example = "COMMERCIAL")
private FltType fltType; // 비행유형 - 상업/비상업 ----
@Schema(description = "비행시작일시", example = "2024-02-12 09:00:00", implementation = String.class)
private LocalDateTime schFltStDt; // 시작일시
@Schema(description = "비행종료일시", example = "2024-02-12 10:00:00", implementation = String.class)
private LocalDateTime schFltEndDt; // 종료일시
@Schema(description = "비행목적", example = "17")
private FltPurpose fltPurpose; // 비행목적 -----
@Schema(description = "서비스구분", example = "KAC")
private String serviceType; // 고정
@Schema(hidden = true)
private String docState = "R";
private List<BasLaancAreaModel> areaList;
// private List<BasFlightPlanPilotModel> pilotList;
private List<BasLaancArcrftModel> arcrftList;
// 약관동의
private List<AnctCstmrTermsModel> terms;
// laanc 정보
// private BasLaancValidatedRs validatedRs;
private List<PilotValidRs> pilotValidRsList; // 자격여부
}

17
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CreateLaancPlanRS.java

@ -0,0 +1,17 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CreateLaancPlanRS {
private String pdfUrl;
private String address;
}

73
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/create/CstmrModel.java

@ -0,0 +1,73 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.create;
import kr.co.palnet.kac.data.pty.model.PtyCstmrBas;
import kr.co.palnet.kac.data.pty.model.PtyCstmrDtl;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class CstmrModel {
private Long cstmrSno;
private String authId;
private String cstmrDivCd;
private String cstmrStatusCd;
private LocalDateTime cstmrStatusCngDt;
private LocalDateTime joinDt;
private String joinIp;
private String memberDivCd;
private LocalDateTime pswdUpdtDt;
private String siteCode;
private String userId;
private String rfrshToken;
private String trmnlId;
private String addr;
private String addrDtlCn;
private LocalDate brthdyDate;
private String clncd;
private String cntryCd;
private String email;
private String genderCd;
private String hpno;
private String ipinCi;
private String ipinDi;
private String joinCrtfyCd;
private String memberName;
private LocalDateTime updateDt;
private String updateUserId;
private String zip;
public static CstmrModel toModel(PtyCstmrBas userEntity, PtyCstmrDtl userDeatilEntity){
CstmrModel model = new CstmrModel();
model.setCstmrSno(userEntity.getCstmrSno());
model.setAuthId(userEntity.getAuthId());
model.setCstmrDivCd(userEntity.getCstmrDivCd());
model.setCstmrStatusCd(userEntity.getCstmrStatusCd());
model.setJoinDt(userEntity.getJoinDt());
model.setJoinIp(userEntity.getJoinIp());
model.setMemberDivCd(userEntity.getMemberDivCd());
model.setPswdUpdtDt(userEntity.getPswdUpdtDt());
model.setSiteCode(userEntity.getSiteCode());
model.setTrmnlId(userEntity.getTrmnlId());
model.setAddr(userDeatilEntity.getAddr());
model.setAddrDtlCn(userDeatilEntity.getAddrDtlCn());
model.setBrthdyDate(userDeatilEntity.getBrthdyDate());
model.setClncd(userDeatilEntity.getClncd());
model.setEmail(userDeatilEntity.getEmail());
model.setGenderCd(userDeatilEntity.getGenderCd());
model.setHpno(userDeatilEntity.getHpno());
model.setIpinCi(userDeatilEntity.getIpinCi());
model.setIpinDi(userDeatilEntity.getIpinDi());
model.setJoinCrtfyCd(userDeatilEntity.getJoinCrtfyCd());
model.setMemberName(userDeatilEntity.getMemberName());
model.setUpdateDt(userDeatilEntity.getUpdateDt());
model.setUpdateUserId(userDeatilEntity.getUpdateUserId());
model.setZip(userDeatilEntity.getZip());
return model;
}
}

138
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/detail/SearchLaancAprvDetailRS.java

@ -0,0 +1,138 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.detail;
import kr.co.palnet.kac.api.v1.flight.laanc.model.FltPlanPilotDTO;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.ArcrftWghtCd;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltPurpose;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltType;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancArcrftModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancAreaModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.SearchLaancAprvRS;
import kr.co.palnet.kac.data.flt.model.FltPlanBas;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchLaancAprvDetailRS {
//비행계획서 일려번호
private Long planSno;
//그룹 아이디
private String groupId;
//작성자 일련번호
private Long cstmrSno;
//작성자 이름
private String memberName;
//작성자 이메일
private String email;
//작성자 연락처
private String hpno;
//작성자 국가번호(연락처)
private String clncd;
//작성자 주소
private String addr;
//작성자 상세주소
private String addrDtlCn;
//작성자 우편번호
private String zip;
//비행시작일시
private LocalDateTime schFltStDt;
//비행종료일시
private LocalDateTime schFltEndDt;
//비행목적
private FltPurpose fltPurpose;
//상업/비사업 구분
private FltType fltType;
//상업/비사업 구분 코드
private String fltTypeNm;
//승인여부
private String aprvlYn;
//승인일자
private LocalDateTime aprvlDt;
//삭제여부
// private String delYn;
// 파일그룹번호
private Long fileGroupNo;
//등록자ID
private String createUserId;
//등록일시
private LocalDateTime createDt;
//수정자ID
private String updateUserId;
//수정일시
private LocalDateTime updateDt;
//서비스유형
private String serviceType;
//기업여부
private String corpRegYn;
//공문URL
private String pdfUrl;
private List<BasLaancAreaModel> areaList;
private List<BasLaancArcrftModel> arcrftList;
private List<FltPlanPilotDTO> pilotList;
public static SearchLaancAprvDetailRS toModel(FltPlanBas entity){
SearchLaancAprvDetailRS model = new SearchLaancAprvDetailRS();
model.setPlanSno(entity.getPlanSno());
model.setGroupId(entity.getGroupId());
model.setCstmrSno(entity.getCstmrSno());
model.setServiceType(entity.getServiceType());
model.setMemberName(entity.getMemberName());
model.setEmail(entity.getEmail());
model.setHpno(entity.getHpno());
model.setClncd(entity.getClncd());
model.setAddr(entity.getAddr());
model.setAddrDtlCn(entity.getAddrDtlCn());
model.setZip(entity.getZip());
model.setSchFltStDt(entity.getSchFltStDt());
model.setSchFltEndDt(entity.getSchFltEndDt());
model.setFltPurpose(FltPurpose.fromCode(entity.getFltPurpose()));
model.setFltType(FltType.fromCode(entity.getFltType()));
model.setCorpRegYn(entity.getCorpRegYn());
model.setAprvlYn(entity.getAprvlYn());
model.setAprvlDt(entity.getAprvlDt());
model.setFileGroupNo(entity.getFileGroupNo());
model.setCreateUserId(entity.getCreateUserId());
model.setCreateDt(entity.getCreateDt());
model.setUpdateUserId(entity.getUpdateUserId());
model.setUpdateDt(entity.getUpdateDt());
return model;
}
// 하나의 필드로 묶어서 처리
//기체 무게
public String getArcrftWght() {
if (arcrftList == null || arcrftList.isEmpty()) return null;
List<ArcrftWghtCd> arcrftWghtCdList = arcrftList.stream().map(BasLaancArcrftModel::getArcrftWghtCd).distinct().filter(Objects::nonNull).collect(Collectors.toList());
String ArcrftWghtType = arcrftWghtCdList.stream().map(ArcrftWghtCd::getValue).collect(Collectors.joining(","));
return ArcrftWghtType;
}
//고도
public String getElev() {
if (areaList == null || areaList.isEmpty()) return null;
List<String> elevList = areaList.stream().map(BasLaancAreaModel::getFltElev).distinct().filter(Objects::nonNull).collect(Collectors.toList());
String elev = String.join(",", elevList);
return elev;
}
//조종사 성명
// public String getPilotName() {
// if (pilotList == null || pilotList.isEmpty()) return null;
// List<String> pilotNameList = pilotList.stream().map(BasLaancPilotModel::getMemberName).distinct().filter(Objects::nonNull).collect(Collectors.toList());
// String pilotName = String.join(",", pilotNameList);
// return pilotName;
// }
}

18
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/pliotvalid/PilotValidRq.java

@ -0,0 +1,18 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.pliotvalid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PilotValidRq {
@Schema(description = "조종사 ci - 본인인증", example = "dzT9zrm1JJRbrT1oRsUbvXYDfbAtXG5QOZjbIVHPaklSZ2PTw8ojYdJyeTrdQdtKIGFM5Z7xfrN/Crm6iGRLkA==")
private String pilotci;
@Schema(description = "기체신고번호", example = "C1CM0231251")
private String declarationnum;
}

29
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/pliotvalid/PilotValidRs.java

@ -0,0 +1,29 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.pliotvalid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PilotValidRs {
@Schema(description = "결과코드", example = "200")
private String rspCode;
@Schema(description = "결과메시지", example = "SUCCESS")
private String rspMessage;
@Schema(description = "조종사자격증명여부", example = "Y")
private String pilotcredentialyn;
@Schema(description = "기체보험가입여부", example = "Y")
private String arcrftinsuranceyn;
@Schema(description = "기체신고여부", example = "Y")
private String arcrftdeclaration;
@Schema(description = "사업자유무", example = "Y")
private String corpregyn;
private PilotValidRq rq;
}

17
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/FileModel.java

@ -0,0 +1,17 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.search;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FileModel {
private Long fileSno;
private Long fileGroupNo;
private String downloadUrl;
private String fileName;
}

28
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/SearchLaancAprvRQ.java

@ -0,0 +1,28 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.search;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchLaancAprvRQ {
@Schema(description = "작성자 이름", example = "팔")
private String memberName;
@Schema(description = "신청(등록)시작일자", example = "2023-12-12", implementation = String.class)
private LocalDate createStDate;
@Schema(description = "신청(등록)종료일자", example = "2023-12-12", implementation = String.class)
private LocalDate createEndDate;
}

140
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/search/SearchLaancAprvRS.java

@ -0,0 +1,140 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.search;
import kr.co.palnet.kac.api.v1.flight.laanc.model.FltPlanPilotDTO;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.ArcrftWghtCd;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltPurpose;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltType;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancArcrftModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancAreaModel;
import kr.co.palnet.kac.data.flt.model.FltPlanBas;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchLaancAprvRS {
//비행계획서 일련번호
private Long planSno;
//그룹 아이디
private String groupId;
//작성자 일련번호
private Long cstmrSno;
//작성자 이름
private String memberName;
//작성자 이메일
private String email;
//작성자 연락처
private String hpno;
//작성자 국가번호(연락처)
private String clncd;
//작성자 주소
private String addr;
//작성자 상세주소
private String addrDtlCn;
//작성자 우편번호
private String zip;
//비행시작일시
private LocalDateTime schFltStDt;
//비행종료일시
private LocalDateTime schFltEndDt;
//비행목적
private FltPurpose fltPurpose;
//상업/비사업 구분
private FltType fltType;
//상업/비사업 구분 코드
private String fltTypeNm;
//승인여부
private String aprvlYn;
//승인일자
private LocalDateTime aprvlDt;
//삭제여부
// private String delYn;
// 파일그룹번호
private Long fileGroupNo;
//등록자ID
private String createUserId;
//등록일시
private LocalDateTime createDt;
//수정자ID
private String updateUserId;
//수정일시
private LocalDateTime updateDt;
//서비스유형
private String serviceType;
//기업여부
private String corpRegYn;
//공문URL
private String pdfUrl;
private List<BasLaancAreaModel> areaList;
private List<BasLaancArcrftModel> arcrftList;
private List<FltPlanPilotDTO> pilotList;
public static SearchLaancAprvRS toModel(FltPlanBas entity){
SearchLaancAprvRS model = new SearchLaancAprvRS();
model.setPlanSno(entity.getPlanSno());
model.setGroupId(entity.getGroupId());
model.setCstmrSno(entity.getCstmrSno());
model.setServiceType(entity.getServiceType());
model.setMemberName(entity.getMemberName());
model.setEmail(entity.getEmail());
model.setHpno(entity.getHpno());
model.setClncd(entity.getClncd());
model.setAddr(entity.getAddr());
model.setAddrDtlCn(entity.getAddrDtlCn());
model.setZip(entity.getZip());
model.setSchFltStDt(entity.getSchFltStDt());
model.setSchFltEndDt(entity.getSchFltEndDt());
model.setFltPurpose(FltPurpose.fromCode(entity.getFltPurpose()));
model.setFltType(FltType.fromCode(entity.getFltType()));
model.setCorpRegYn(entity.getCorpRegYn());
model.setAprvlYn(entity.getAprvlYn());
model.setAprvlDt(entity.getAprvlDt());
model.setFileGroupNo(entity.getFileGroupNo());
model.setCreateUserId(entity.getCreateUserId());
model.setCreateDt(entity.getCreateDt());
model.setUpdateUserId(entity.getUpdateUserId());
model.setUpdateDt(entity.getUpdateDt());
return model;
}
// 하나의 필드로 묶어서 처리
//기체 무게
public String getArcrftWght() {
if (arcrftList == null || arcrftList.isEmpty()) return null;
List<ArcrftWghtCd> arcrftWghtCdList = arcrftList.stream().map(BasLaancArcrftModel::getArcrftWghtCd).distinct().filter(Objects::nonNull).collect(Collectors.toList());
String ArcrftWghtType = arcrftWghtCdList.stream().map(ArcrftWghtCd::getValue).collect(Collectors.joining(","));
return ArcrftWghtType;
}
//고도
public String getElev() {
if (areaList == null || areaList.isEmpty()) return null;
List<String> elevList = areaList.stream().map(BasLaancAreaModel::getFltElev).distinct().filter(Objects::nonNull).collect(Collectors.toList());
String elev = String.join(",", elevList);
return elev;
}
//조종사 성명
// public String getPilotName() {
// if (pilotList == null || pilotList.isEmpty()) return null;
// List<String> pilotNameList = pilotList.stream().map(BasLaancPilotModel::getMemberName).distinct().filter(Objects::nonNull).collect(Collectors.toList());
// String pilotName = String.join(",", pilotNameList);
// return pilotName;
// }
}

18
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/tsqr/LaancTsQRcodeRQ.java

@ -0,0 +1,18 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LaancTsQRcodeRQ {
@Schema(description = "기체신고번호", example = "C1CM0231251")
private String idntfNum; // 기체신고번호
}

17
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/tsqr/LaancTsQRcodeRS.java

@ -0,0 +1,17 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LaancTsQRcodeRS {
private byte[] qrcode; // qr코드
private String confirmKey; // 인증번호
}

11
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAllowableElevationRS.java

@ -0,0 +1,11 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid;
import lombok.Data;
import java.util.List;
@Data
public class LaancAllowableElevationRS {
private List<Integer> allowableElevation;
}

21
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaByAirspaceModel.java

@ -0,0 +1,21 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class LaancAreaByAirspaceModel {
@Schema(description = "구역종류", example = "CIRCLE")
private String areaType;
@Schema(description = "버퍼존", example = "100")
private Integer bufferZone;
@Schema(description = "고도", example = "110")
private String fltElev;
private List<LaancAreaCoordModel> coordList;
}

19
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaByElevModel.java

@ -0,0 +1,19 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class LaancAreaByElevModel {
@Schema(description = "구역종류", example = "CIRCLE")
private String areaType;
@Schema(description = "버퍼존", example = "100")
private Integer bufferZone;
private List<LaancAreaCoordModel> coordList;
}

14
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancAreaCoordModel.java

@ -0,0 +1,14 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class LaancAreaCoordModel {
@Schema(description = "위도", example = "127.33")
private double lat;
@Schema(description = "경도", example = "37.99")
private double lon;
}

15
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/model/valid/LaancDuplicatedAirspaceRs.java

@ -0,0 +1,15 @@
package kr.co.palnet.kac.api.v1.flight.laanc.model.valid;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LaancDuplicatedAirspaceRs {
private boolean isDuplicated;
private LaancAreaByAirspaceModel rq;
}

681
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/laanc/service/FlightLaancService.java

@ -0,0 +1,681 @@
package kr.co.palnet.kac.api.v1.flight.laanc.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import kr.co.palnet.kac.api.external.model.TsQRcodeRQ;
import kr.co.palnet.kac.api.external.service.CtrTrnsLctnService;
import kr.co.palnet.kac.api.external.service.TsService;
import kr.co.palnet.kac.api.util.*;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.CstmrModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.*;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.*;
import kr.co.palnet.kac.api.v1.flight.laanc.model.detail.SearchLaancAprvDetailRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.FileModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.SearchLaancAprvRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.search.SearchLaancAprvRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr.LaancTsQRcodeRQ;
import kr.co.palnet.kac.api.v1.flight.laanc.model.tsqr.LaancTsQRcodeRS;
import kr.co.palnet.kac.api.v1.flight.laanc.model.valid.*;
import kr.co.palnet.kac.data.com.domain.ComConfirmBas;
import kr.co.palnet.kac.data.com.domain.ComFileBas;
import kr.co.palnet.kac.data.com.service.ComConfirmDomainService;
import kr.co.palnet.kac.data.flt.model.*;
import kr.co.palnet.kac.data.other.service.OtherDomainService;
import kr.co.palnet.kac.api.external.model.ComnSmsLaancAprovModel;
import kr.co.palnet.kac.api.external.model.CtrTrnsLctnModel;
import kr.co.palnet.kac.api.v1.flight.laanc.model.pliotvalid.PilotValidRs;
import kr.co.palnet.kac.config.security.util.SessionHelper;
import kr.co.palnet.kac.core.exception.BaseErrorCode;
import kr.co.palnet.kac.core.exception.BaseException;
import kr.co.palnet.kac.data.com.service.ComFileDomainService;
import kr.co.palnet.kac.data.flt.service.FltPlanDomainService;
import kr.co.palnet.kac.data.pty.model.PtyCstmrBas;
import kr.co.palnet.kac.data.pty.model.PtyCstmrDtl;
import kr.co.palnet.kac.data.pty.model.PtyGroupBas;
import kr.co.palnet.kac.data.pty.service.PtyCstmrDomainService;
import kr.co.palnet.kac.data.pty.service.PtyGroupDomainService;
import kr.co.palnet.kac.data.pty.service.PtyTermsDomainService;
import kr.co.palnet.kac.api.external.service.ComnSmsService;
import kr.co.palnet.kac.api.util.model.LaancPdfModel;
import kr.co.palnet.kac.util.EncryptUtil;
import kr.co.palnet.kac.util.ObjectMapperUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.zxing.WriterException;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class FlightLaancService {
private final PtyCstmrDomainService ptyCstmrDomainService;
private final PtyTermsDomainService ptyTermsDomainService;
private final PtyGroupDomainService ptyGroupDomainService;
private final FltPlanDomainService fltPlanDomainService;
private final ComFileDomainService comFileDomainService;
private final ComConfirmDomainService comConfirmDomainService;
private final OtherDomainService otherDomainService;
private final CtrTrnsLctnService ctrTrnsLctnService;
private final ComnSmsService comnSmsService;
private final TsService tsService;
//
private final FileUtils fileUtils;
private final AreaUtils areaUtils;
@Value("${app.host}")
private String APP_HOST;
@Value("${external.ts.return.uri}")
private String TS_RETURN_URI;
@Transactional
public CreateLaancPlanRS createPlan(CreateLaancPlanRQ rq) {
Long cstmrSno = SessionHelper.getCstmrSno();
String userId = SessionHelper.getUserId();
// 비행계획서 INSERT
Optional<PtyCstmrBas> userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno);
Optional<PtyCstmrDtl> userDetailEntityData = ptyCstmrDomainService.findPtyCstmrDtlById(cstmrSno);
if(userEntityData.isEmpty() || userDetailEntityData.isEmpty()) throw new BaseException(BaseErrorCode.DATA_EMPTY);
CstmrModel cstmrInfo = CstmrModel.toModel(userEntityData.get(), userDetailEntityData.get());
FltPlanBasDTO fltPlanBasDto = FltPlanBasDTO.toFltPlanBasDto(cstmrInfo, rq);
fltPlanBasDto.setDelYn("N");
fltPlanBasDto.setAprvlYn("Y");
fltPlanBasDto.setAprvlDt(LocalDateTime.now());
fltPlanBasDto.setCreateUserId(userId);
fltPlanBasDto.setCreateDt(LocalDateTime.now());
fltPlanBasDto.setUpdateUserId(userId);
fltPlanBasDto.setUpdateDt(LocalDateTime.now());
// KAC 그룹 ID - LAANC에서는 KAC 그룹으로만 보여주도록 함.
String groupId = "";
String groupNm = "";
// Optional<List<PtyGroupBas>> kacData = ptyGroupDomainService.findPtyGroupBasByGroupNm(rq.getServiceType());
// TODO :: 현재 모듈에서는 KAC 그룹이 생성되는 코드가 없기에 "" 값만 들어갈 예정임
Optional<List<PtyGroupBas>> kacData = ptyGroupDomainService.findPtyGroupBasByGroupNm("KAC");
if (kacData.isPresent() && !kacData.get().isEmpty()) {
List<PtyGroupBas> kac = kacData.get();
groupId = kac.get(0).getGroupId();
groupNm = kac.get(0).getGroupNm();
}
fltPlanBasDto.setGroupId(groupId);
String corpRegYn = "N";
if (rq.getPilotValidRsList() != null && !rq.getPilotValidRsList().isEmpty()) {
boolean isCorpReg = rq.getPilotValidRsList().stream().anyMatch(pilotValidRs -> "Y".equals(pilotValidRs.getCorpregyn()));
corpRegYn = isCorpReg ? "Y" : "N";
}
fltPlanBasDto.setCorpRegYn(corpRegYn); // 사업자유무
fltPlanBasDto.setServiceType("F0002");
FltPlanBas fltPlanBas = fltPlanDomainService.saveFltPlanBas(fltPlanBasDto.toFltPlanEntity());
Long planSno = fltPlanBas.getPlanSno();
// 비행구역 INSERT
List<BasLaancAreaModel> basLaancAreaModelList = rq.getAreaList();
if (basLaancAreaModelList != null && !basLaancAreaModelList.isEmpty()) {
List<FltPlanArea> fltPlanAreaList = new ArrayList<>();
for (BasLaancAreaModel laancAreaModel : basLaancAreaModelList) {
// 주소 가져오기
try {
double firstLat = laancAreaModel.getCoordList().get(0).getLat();
double firstLon = laancAreaModel.getCoordList().get(0).getLon();
CtrTrnsLctnModel ctrTrnsLctnModel = ctrTrnsLctnService.convertLatlonToAddress(firstLat, firstLon);
String address = ctrTrnsLctnModel.getArea1() + " " +
ctrTrnsLctnModel.getArea2() + " " +
ctrTrnsLctnModel.getLandNm() + " " +
ctrTrnsLctnModel.getLandNum();
laancAreaModel.setFltAreaAddr(address);
} catch (Exception e) {
log.error("get first coords to address fail. : ", e);
}
FltPlanAreaDTO fltPlanAreaDto = FltPlanAreaDTO.toDto(laancAreaModel);
fltPlanAreaDto.setPlanSno(planSno);
fltPlanAreaDto.setCreateUserId(userId);
fltPlanAreaDto.setUpdateUserId(userId);
FltPlanArea fltPlanArea = fltPlanDomainService.saveFltPlanArea(fltPlanAreaDto.toEntity());
Long planAreaSno = fltPlanArea.getPlanAreaSno();
List<BasLaancAreaCoordModel> laancAreaModelCoordList = laancAreaModel.getCoordList();
if (laancAreaModelCoordList != null && !laancAreaModelCoordList.isEmpty()) {
// double lat = laancAreaModelCoordList.get(0).getLat();
// double lon = laancAreaModelCoordList.get(0).getLon();
List<FltPlanAreaCoord> fltPlanAreaCoordList = new ArrayList<>();
for (BasLaancAreaCoordModel basLaancAreaCoordModel : laancAreaModelCoordList) {
FltPlanAreaCoordDTO coordEntityDto = FltPlanAreaCoordDTO.toDto(basLaancAreaCoordModel);
coordEntityDto.setPlanAreaSno(planAreaSno);
coordEntityDto.setCreateUserId(userId);
FltPlanAreaCoord fltPlanAreaCoord = coordEntityDto.toEntity();
fltPlanAreaCoordList.add(fltPlanAreaCoord);
}
fltPlanArea.setFltPlanAreaCoordList(fltPlanAreaCoordList);
}
fltPlanAreaList.add(fltPlanArea);
}
fltPlanBas.setFltPlanAreaList(fltPlanAreaList);
}
// 조종사 - 사용자 정보로 저장
FltPlanPilotDTO planPilotDto = FltPlanPilotDTO.toDto(cstmrInfo);
planPilotDto.setEmail(EncryptUtil.decrypt(cstmrInfo.getEmail()));
planPilotDto.setHpno(EncryptUtil.decrypt(cstmrInfo.getHpno()));
planPilotDto.setPlanSno(planSno);
planPilotDto.setGroupNm(groupNm);
planPilotDto.setCreateUserId(userId);
planPilotDto.setCreateDt(LocalDateTime.now());
planPilotDto.setUpdateUserId(userId);
planPilotDto.setUpdateDt(LocalDateTime.now());
fltPlanBas.setFltPlanPilotList(Arrays.asList(planPilotDto.toEntity()));
// 기체정보 INSERT
List<BasLaancArcrftModel> basLaancArcrftModelList = rq.getArcrftList();
List<FltPlanArcrft> fltPlanArcrftList = new ArrayList<>();
if (basLaancArcrftModelList != null && !basLaancArcrftModelList.isEmpty()) {
for (BasLaancArcrftModel basLaancArcrftModel : basLaancArcrftModelList) {
FltPlanArcrftDTO arcrftEntityDto = FltPlanArcrftDTO.toDto(basLaancArcrftModel);
arcrftEntityDto.setPlanSno(planSno);
arcrftEntityDto.setCreateUserId(userId);
arcrftEntityDto.setCreateDt(LocalDateTime.now());
arcrftEntityDto.setUpdateUserId(userId);
arcrftEntityDto.setUpdateDt(LocalDateTime.now());
String arcrftInsuranceYn = "N";
// 추가 필드
if (rq.getPilotValidRsList() != null && !rq.getPilotValidRsList().isEmpty() && basLaancArcrftModel.getIdntfNum() != null) {
PilotValidRs pilotValidRs = rq.getPilotValidRsList().stream().filter(pilotValid -> pilotValid.getRq().getDeclarationnum().equals(arcrftEntityDto.getIdntfNum())).findFirst().orElse(null);
if (pilotValidRs != null) {
String arcrftinsuranceyn = pilotValidRs.getArcrftinsuranceyn();
arcrftInsuranceYn = "Y".equals(arcrftinsuranceyn) ? "Y" : "N";
}
}
arcrftEntityDto.setAcrftInsuranceYn(arcrftInsuranceYn); // 보험여부
// arcrftEntity.setInsuranceExperiod(null); // 보헌 유효기간
// arcrftEntity.setCorporationNm(null); // 법인명
fltPlanArcrftList.add(arcrftEntityDto.toEntity());
}
}
fltPlanBas.setFltPlanArcrftList(fltPlanArcrftList);
if (rq.getTerms() != null && !rq.getTerms().isEmpty()) {
for (AnctCstmrTermsModel agree : rq.getTerms()) {
PtyTermsAgreeTxnDTO agreeEntityDto = new PtyTermsAgreeTxnDTO();
agreeEntityDto.setCstmrSno(fltPlanBas.getCstmrSno());
agreeEntityDto.setProcIp(HttpUtils.getRequestIp()); // TODO :: 현시점에는 HttpUtil Util이 없으므로 임시로 FLT 모듈 자체에서 Util을 만들어서 사용, 추후 모든 모듈 완성 되었을 시 Common모듈 코드 사용
agreeEntityDto.setTermsSno(agree.getTermsSno());
agreeEntityDto.setUpdateDt(LocalDateTime.now());
agreeEntityDto.setUpdateUserId(userId);
agreeEntityDto.setAgreeYn(agree.getAgreeYn());
if (agree.getAgreeYn().equals("Y")) {
agreeEntityDto.setAgreeDt(LocalDateTime.now());
}
try{
ptyTermsDomainService.savePtyTermsAgreeTxn(agreeEntityDto.toEntity());
}catch (Exception e){
// TODO :: 임시로 코드 변경, 추후 약관 있을시 본래 코드인 else문으로 Exception던질것임
throw new BaseException(BaseErrorCode.FAILED, "약관등록 실패");
}
}
}
String address = "";
// PDF 생성 후 URL 가져오기
LaancPdfModel laancPdfModel = new LaancPdfModel();
laancPdfModel.setPilotName(cstmrInfo.getMemberName());
if (rq.getAreaList() != null && !rq.getAreaList().isEmpty()) {
address = rq.getAreaList().get(0).getFltAreaAddr() == null ? "" : rq.getAreaList().get(0).getFltAreaAddr();
laancPdfModel.setAddress(address);
laancPdfModel.setElev(rq.getAreaList().get(0).getFltElev());
}
if (rq.getArcrftList() != null && !rq.getArcrftList().isEmpty()) {
if (rq.getArcrftList().get(0).getArcrftTypeCd() != null) {
laancPdfModel.setArcrftType(rq.getArcrftList().get(0).getArcrftTypeCd().getValue());
}
if (StringUtils.hasText(rq.getArcrftList().get(0).getIdntfNum())) {
laancPdfModel.setIdntfNum(rq.getArcrftList().get(0).getIdntfNum());
}
}
laancPdfModel.setBirthDate(cstmrInfo.getBrthdyDate().toString());
laancPdfModel.setSchFltStDt(DateUtils.toDateTimeStringByFormat(rq.getSchFltStDt(), "yyyy.MM.dd HH:mm"));
laancPdfModel.setSchFltEndDt(DateUtils.toDateTimeStringByFormat(rq.getSchFltEndDt(), "yyyy.MM.dd HH:mm"));
laancPdfModel.setCreateDt(DateUtils.toDateTimeStringByFormat(LocalDateTime.now(), "yyyy.MM.dd HH:mm"));
laancPdfModel.setFltPurpose(rq.getFltPurpose().getValue());
// TODO :: 현시점에는 파일 Util이 없으므로 임시로 FLT 모듈 자체에서 Util을 만들어서 사용, 추후 모든 모듈 완성 되었을 시 Common모듈 코드 사용
ComFileBasDTO comFileBasDto = fileUtils.makePdf(laancPdfModel);
comFileBasDto.setDelYn("N");
if(comFileBasDto.getFileGroupNo() == null || comFileBasDto.getFileGroupNo() == 0){
Long fileGroupNo = comFileDomainService.findFirstByOrderByFileGroupNoDesc();
comFileBasDto.setFileGroupNo(fileGroupNo);
}
comFileDomainService.saveComFileBas(comFileBasDto.toEntity());
fltPlanBas.setFileGroupNo(comFileBasDto.getFileGroupNo());
// fltPlanDomainService.saveFltPlanBas(fltPlanBas);
String downloadUrl = fileUtils.getDownloadUrl(comFileBasDto.getFileSno());
// SMS 전송
try {
ComnSmsLaancAprovModel comnSmsLaancAprovModel = new ComnSmsLaancAprovModel();
comnSmsLaancAprovModel.setPilotName(cstmrInfo.getMemberName());
comnSmsLaancAprovModel.setCallphone(EncryptUtil.decrypt(cstmrInfo.getHpno()));
comnSmsLaancAprovModel.setSchFltStDt(DateUtils.toDateTimeStringByFormat(rq.getSchFltStDt(), "yyyy년 MM월 dd일 HH시 mm분"));
comnSmsLaancAprovModel.setSchFltEndDt(DateUtils.toDateTimeStringByFormat(rq.getSchFltEndDt(), "yyyy년 MM월 dd일 HH시 mm분"));
comnSmsLaancAprovModel.setFltPurpose(rq.getFltPurpose().getValue());
comnSmsLaancAprovModel.setAddress(address);
if (rq.getAreaList() != null && !rq.getAreaList().isEmpty()) {
comnSmsLaancAprovModel.setElev(rq.getAreaList().get(0).getFltElev());
}
SuredataEntityDTO sureDateEntityDto = comnSmsService.sendLaancAprovSms(comnSmsLaancAprovModel);
otherDomainService.saveSuredate(sureDateEntityDto.toEntity());
} catch (Exception e) {
log.error("ERROR: ", e);
}
return CreateLaancPlanRS.builder()
.pdfUrl(downloadUrl)
.address(address)
.build();
}
@Transactional
public LaancTsQRcodeRS createQRcode(LaancTsQRcodeRQ rq) {
Long cstmrSno = SessionHelper.getCstmrSno();
String userId = SessionHelper.getUserId();
Optional<PtyCstmrBas> userEntityData = ptyCstmrDomainService.findPtyCstmrBasById(cstmrSno);
Optional<PtyCstmrDtl> userDetailEntityData = ptyCstmrDomainService.findPtyCstmrDtlById(cstmrSno);
if(userEntityData.isEmpty() || userDetailEntityData.isEmpty()) throw new BaseException(BaseErrorCode.DATA_EMPTY);
CstmrModel cstmrInfo = CstmrModel.toModel(userEntityData.get(), userDetailEntityData.get());
String userCi = cstmrInfo.getIpinCi();
String idntfNum = null;
if (rq != null && rq.getIdntfNum() != null && !rq.getIdntfNum().isEmpty()) {
idntfNum = rq.getIdntfNum();
}
String confirmKey = UUID.randomUUID().toString();
String params = null;
byte[] qr = null;
try {
TsQRcodeRQ tsRq = TsQRcodeRQ.builder()
.rtnUrl(this.APP_HOST + this.TS_RETURN_URI)
.reqId(confirmKey)
.submittype(idntfNum)
.applyUser(userCi)
.build();
// params = JsonUtils.toJson(tsRq);
/*
tsdronewallet://kotsa.or.kr
? type=5
& rtnUrl= http://121.190.193.50:6081/api/external/laanc/vc/callback
& reqId=0b42b0af-3875-4a21-b57b-bb93ffcb3cfc
& submittype=C1CM0231251
& applyUser=dzT9zrm1JJRbrT1oRsUbvXYDfbAtXG5QOZjbIVHPaklSZ2PTw8ojYdJyeTrdQdtKIGFM5Z7xfrN/Crm6iGRLkA==
*/
params = UriComponentsBuilder
.fromUriString("tsdronewallet://kotsa.or.kr")
.queryParam("type", tsRq.getType())
.queryParam("rtnUrl", tsRq.getRtnUrl())
.queryParam("reqId", tsRq.getReqId())
.queryParam("submittype", tsRq.getSubmittype())
.queryParam("applyUser", tsRq.getApplyUser())
.build()
.toUriString();
qr = tsService.createQrcode(params);
} catch (WriterException | IOException e) {
log.error("ERROR: ", e);
throw new BaseException(BaseErrorCode.FAILED, "QR코드 생성 실패");
}
// db 저장 - confirmKey(uuid)
ComConfirmBas comConfirmBas = ComConfirmBas.builder()
.confirmKey(confirmKey)
.status("GENERATED")
.targetType("TS_QRCODE")
.rqData(params)
.createUserId(userId)
.createDt(LocalDateTime.now())
.updateUserId(userId)
.updateDt(LocalDateTime.now())
.build();
comConfirmDomainService.saveComConfirmBas(comConfirmBas);
log.info(">>> confirmKey [GENERATED] ", confirmKey);
return LaancTsQRcodeRS.builder()
.qrcode(qr)
.confirmKey(confirmKey)
.build();
}
public PilotValidRs checkQrcode(String confirmKey) {
log.info(">>> confirmKey : {}", confirmKey);
String userId = SessionHelper.getUserId();
Optional<ComConfirmBas> entityData = comConfirmDomainService.findFirstByConfirmKeyOrderByCreateDtDesc(confirmKey);
if(entityData.isEmpty()) throw new BaseException(BaseErrorCode.DATA_EMPTY, "QR코드 조회 실패");
ComConfirmBas entity = entityData.get();
if (!"RECEIVED".equals(entity.getStatus())){
Map<String, String> errorParam = new HashMap<>();
errorParam.put("status", entity.getStatus());
throw new BaseException(BaseErrorCode.DATA_EMPTY, errorParam.toString());
}
// TODO 일자 검증 - 3분 초과
LocalDateTime createDt = entity.getCreateDt().plusMinutes(3);
boolean flag = !createDt.isBefore(LocalDateTime.now());
if (!flag) {
entity.setStatus("EXPIRED");
entity.setUpdateUserId(userId);
comConfirmDomainService.saveComConfirmBas(entity);
comConfirmDomainService.flush();
throw new BaseException(BaseErrorCode.QR_EXPIRED, "QR 기간 만료");
}
PilotValidRs rs = null;
String rsData = entity.getRsData();
if(rsData != null && !rsData.isEmpty()){
try{
rs = ObjectMapperUtils.getObjectMapper().readValue(rsData, PilotValidRs.class);
} catch (JsonProcessingException e){
log.error("",e);
}
}
return rs;
}
public List<LaancDuplicatedAirspaceRs> getDuplicatedAirspace(List<LaancAreaByAirspaceModel> rq) {
// TODO :: 임시로 모듈안에 Util 만들어서 사용, 추후 만들어진 것으로 사용할 것
AirspaceUtils airspaceUtils = AirspaceUtils.getInstance();
List<LaancDuplicatedAirspaceRs> rs = new ArrayList<>();
for (LaancAreaByAirspaceModel area : rq) {
//rq로 들어온 좌표로 버퍼좌표 생성
List<Coordinate> targetCoord = new ArrayList<>();
List<Coordinate> targetCoordBufferList = new ArrayList<>();
for (LaancAreaCoordModel basLaancAreaCoordModel : area.getCoordList()) {
Coordinate coords = new Coordinate(basLaancAreaCoordModel.getLon(), basLaancAreaCoordModel.getLat());
targetCoord.add(coords);
}
if ("LINE".equals(area.getAreaType())) {
List<Coordinate> trans = areaUtils.transform(targetCoord, "EPSG:4326", "EPSG:5181");
List<Coordinate> bufferList = areaUtils.buffer(trans, area.getBufferZone());
targetCoordBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326");
} else if ("POLYGON".equals(area.getAreaType())) {
targetCoordBufferList.addAll(targetCoord);
} else if ("CIRCLE".equals(area.getAreaType())) {
targetCoordBufferList = areaUtils.createCircle(targetCoord.get(0), area.getBufferZone());
}
Geometry targetGeometry = airspaceUtils.createGeometryByCoordinate(targetCoordBufferList);
Integer fltElev = area.getFltElev() != null ? Integer.parseInt(area.getFltElev()) : 0;
AirspaceUtils.FeatureInfo targetFeatureInfo = new AirspaceUtils.FeatureInfo(null, null, 0, fltElev, targetGeometry);
boolean duplicatedAirspace = airspaceUtils.isDuplicatedAirspace(targetFeatureInfo);
LaancDuplicatedAirspaceRs duplicatedAirspaceRs = LaancDuplicatedAirspaceRs.builder()
.isDuplicated(duplicatedAirspace)
.rq(area)
.build();
rs.add(duplicatedAirspaceRs);
}
return rs;
}
public LaancAllowableElevationRS getAllowableElevation(List<LaancAreaByElevModel> rq) {
AirspaceUtils airspaceUtils = AirspaceUtils.getInstance();
List<Integer> allowElevationList = new ArrayList<>();
for (LaancAreaByElevModel area : rq) {
//rq로 들어온 좌표로 버퍼좌표 생성
List<Coordinate> targetCoord = new ArrayList<>();
List<Coordinate> targetCoordBufferList = new ArrayList<>();
for (LaancAreaCoordModel coord : area.getCoordList()) {
Coordinate coords = new Coordinate(coord.getLon(), coord.getLat());
targetCoord.add(coords);
}
if ("LINE".equals(area.getAreaType())) {
List<Coordinate> trans = areaUtils.transform(targetCoord, "EPSG:4326", "EPSG:5181");
List<Coordinate> bufferList = areaUtils.buffer(trans, area.getBufferZone());
targetCoordBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326");
} else if ("POLYGON".equals(area.getAreaType())) {
targetCoordBufferList.addAll(targetCoord);
} else if ("CIRCLE".equals(area.getAreaType())) {
targetCoordBufferList = areaUtils.createCircle(targetCoord.get(0), area.getBufferZone());
}
Geometry targetGeometry = airspaceUtils.createGeometryByCoordinate(targetCoordBufferList);
// Integer fltElev = area.getFltElev() != null ? Integer.parseInt(area.getFltElev()) : 0;
// AirspaceUtils.FeatureInfo featureInfo = new AirspaceUtils.FeatureInfo(null, null, 0, fltElev, rqGeometry);
Integer allowElevation = airspaceUtils.getAllowElevation(targetGeometry);
allowElevationList.add(allowElevation);
}
LaancAllowableElevationRS result = new LaancAllowableElevationRS();
result.setAllowableElevation(allowElevationList);
return result;
}
@Transactional
public List<SearchLaancAprvRS> getLaancAprvList(SearchLaancAprvRQ rq) {
LocalDateTime createStDate = rq.getCreateStDate().atStartOfDay();
LocalDateTime createEndDate = rq.getCreateEndDate().plusDays(1).atStartOfDay().minusSeconds(1);
Optional<List<FltPlanBas>> fltPlanBasListData = fltPlanDomainService.findAllFltPlanBasBySearch(rq.getMemberName(), createStDate, createEndDate);
List<SearchLaancAprvRS> result = new ArrayList<>();
if(fltPlanBasListData.isPresent() && !fltPlanBasListData.get().isEmpty()){
List<FltPlanBas> fltPlanBasList = fltPlanBasListData.get();
for(FltPlanBas fltPlanBas : fltPlanBasList){
SearchLaancAprvRS node = SearchLaancAprvRS.toModel(fltPlanBas);
node.setHpno(EncryptUtil.decrypt(node.getHpno()));
node.setEmail(EncryptUtil.decrypt(node.getEmail()));
node.setFltTypeNm(node.getFltType().getValue());
Long planSno = node.getPlanSno();
Optional<List<FltPlanArea>> fltPlanAreaListData = fltPlanDomainService.findFltPlanAreaByPlanSno(planSno);
Optional<List<FltPlanArcrft>> fltPlanArcrftListData = fltPlanDomainService.findFltPlanArcrftByPlanSno(planSno);
if(fltPlanAreaListData.isPresent()){
List<FltPlanArea> fltPlanAreaList = fltPlanAreaListData.get();
List<BasLaancAreaModel> areaList = fltPlanAreaList.stream().map(BasLaancAreaModel::toModel).toList();
node.setAreaList(areaList);
}
if(fltPlanArcrftListData.isPresent()){
List<FltPlanArcrft> fltPlanArcrftList = fltPlanArcrftListData.get();
List<BasLaancArcrftModel> arcrftList = fltPlanArcrftList.stream().map(BasLaancArcrftModel::toModel).toList();
node.setArcrftList(arcrftList);
}
result.add(node);
}
}
List<Long> fileGroupNoList = result.stream().map(SearchLaancAprvRS::getFileGroupNo).filter(Objects::nonNull).collect(Collectors.toList());
Optional<List<ComFileBas>> filesData = comFileDomainService.findByFileGroupNoInAndDelYnOrderByCreateDtDesc(fileGroupNoList, "N");
List<FileModel> fileModels = new ArrayList<>();
if(filesData.isPresent() && !filesData.get().isEmpty()){
List<ComFileBas> files = filesData.get();
for (ComFileBas file : files) {
fileModels.add(FileModel.builder()
.fileGroupNo(file.getFileGroupNo())
.fileSno(file.getFileSno())
.fileName(file.getFileOriNm())
.downloadUrl(fileUtils.getDownloadUrl(file.getFileSno()))
.build());
}
}
result.forEach(dto -> {
if (dto.getFileGroupNo() != null) {
fileModels.stream()
.filter(file -> Objects.equals(file.getFileGroupNo(), dto.getFileGroupNo()))
.findFirst()
.ifPresent(file -> dto.setPdfUrl(file.getDownloadUrl()));
}
});
return result;
}
public SearchLaancAprvDetailRS getLaancAprvDetail(Long planSno) {
if(planSno == null) throw new BaseException(BaseErrorCode.WEB_PARAM_INVALID);
Optional<FltPlanBas> fltPlanBasData = fltPlanDomainService.findById(planSno);
if(fltPlanBasData.isPresent()){
FltPlanBas fltPlanBas = fltPlanBasData.get();
SearchLaancAprvDetailRS result = SearchLaancAprvDetailRS.toModel(fltPlanBas);
result.setHpno(EncryptUtil.decrypt(result.getHpno()));
result.setEmail(EncryptUtil.decrypt(result.getEmail()));
result.setFltTypeNm(result.getFltType().getValue());
List<FltPlanArea> fltPlanAreaList = fltPlanBas.getFltPlanAreaList();
List<FltPlanArcrft> fltPlanArcrftList = fltPlanBas.getFltPlanArcrftList();
List<FltPlanPilot> fltPlanPilotList = fltPlanBas.getFltPlanPilotList();
if(fltPlanAreaList != null && !fltPlanAreaList.isEmpty()){
List<BasLaancAreaModel> areaList = new ArrayList<>();
for(FltPlanArea fltPlanArea : fltPlanAreaList){
List<BasLaancAreaCoordModel> fltPlanAreaCoordList = fltPlanArea.getFltPlanAreaCoordList().stream().map(BasLaancAreaCoordModel::toModel).toList();
BasLaancAreaModel node = BasLaancAreaModel.toModel(fltPlanArea);
node.setCoordList(fltPlanAreaCoordList);
areaList.add(node);
}
result.setAreaList(areaList);
}
if(fltPlanArcrftList != null && !fltPlanArcrftList.isEmpty()){
List<BasLaancArcrftModel> arcrftList = fltPlanArcrftList.stream().map(BasLaancArcrftModel::toModel).toList();
result.setArcrftList(arcrftList);
}
if(fltPlanPilotList != null && !fltPlanPilotList.isEmpty()){
List<FltPlanPilotDTO> fltPlanPilotDTOList = fltPlanPilotList.stream().map(FltPlanPilotDTO::toDto).toList();
result.setPilotList(fltPlanPilotDTOList);
}
Optional<ComFileBas> comFileBasData = comFileDomainService.findFirstByFileGroupNoAndDelYnOrderByCreateDtDesc(fltPlanBas.getFileGroupNo());
// PDF URL 추출
if (comFileBasData.isPresent()) {
ComFileBas comFileBas = comFileBasData.get();
result.setPdfUrl(fileUtils.getDownloadUrl(comFileBas.getFileSno()));
}
return result;
} else {
throw new BaseException(BaseErrorCode.DATA_EMPTY);
}
}
public void testCreateQRCode(String confirmKey, String userId){
ComConfirmBas comConfirmBas = ComConfirmBas.builder()
.confirmKey(confirmKey)
.status("RECEIVED")
.targetType("TS_QRCODE")
.rsData("""
{"rspCode":"200","rspMessage":"success","rqID":"%s","pilotcredentialyn":"Y","arcrftinsuranceyn":"Y","arcrftdeclaration":"Y","corpregyn":"Y"}
""".formatted(confirmKey))
.createUserId(userId)
.createDt(LocalDateTime.now())
.updateUserId(userId)
.updateDt(LocalDateTime.now())
.build();
comConfirmDomainService.saveComConfirmBas(comConfirmBas);
}
public FltPlanBasDTO testDescPlanSno(){
return FltPlanBasDTO.toFltPlanBasDto(fltPlanDomainService.findByOrderByPlanSnoDesc());
}
}

42
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/controller/FlightPlanController.java

@ -0,0 +1,42 @@
package kr.co.palnet.kac.api.v1.flight.plan.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import kr.co.palnet.kac.api.v1.flight.plan.model.buffer.CreateBufferModel;
import kr.co.palnet.kac.api.v1.flight.plan.model.schedule.SearchPlanScheduleRS;
import kr.co.palnet.kac.api.v1.flight.plan.service.FlightPlanService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j
@RequestMapping("/v1/flight/plan")
@RequiredArgsConstructor
public class FlightPlanController {
private final FlightPlanService flightPlanService;
@PostMapping("/area/buffer")
@Operation(summary = "비행 계획서 작성 - 버퍼존 생성", description = "비행 계획서 작성 시 특정 좌표를 이은 선분에 대한 버퍼존을 생성하는 API 입니다.")
public ResponseEntity<List<CreateBufferModel>> createBuffer(@RequestBody List<CreateBufferModel> rq){
List<CreateBufferModel> result = flightPlanService.createBuffer(rq);
return ResponseEntity.ok().body(result);
}
@GetMapping("/schedule")
@Operation(summary = "비행 운항 스케줄 조회", description = "비행 현황 스케줄 정보를 조회하는 API 입니다.")
public ResponseEntity<List<SearchPlanScheduleRS>> getPlanSchedule(@Parameter(name="searchDate", description = "검색 날짜", in = ParameterIn.QUERY, example = "2023-11-15") @RequestParam("searchDate") String searchDate){
List<SearchPlanScheduleRS> result = flightPlanService.getPlanSchedule(searchDate);
return ResponseEntity.ok().body(result);
}
}

55
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/CtrCntrlBasDTO.java

@ -0,0 +1,55 @@
package kr.co.palnet.kac.api.v1.flight.plan.model;
import kr.co.palnet.kac.data.ctr.model.CtrCntrlBas;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class CtrCntrlBasDTO {
private String cntrlId; // 관제ID
private String idntfNum; // 식별번호
private String statusCd; // 상태코드
private String procStatusYn; // 처리상태여부
private String objectTypeCd; // 물체타입코드
private LocalDateTime flghtStDt; // 비행시작일시
private LocalDateTime flghtEndDt; // 비행종료일시
private LocalDateTime cntrlStDt; // 관제시작일시
private LocalDateTime cntrlEndDt; // 관제종료일시
private Double ttlTime; // 총비행시간
private String ttlTimeType; // 총비행시간단위
private Double ttlDstnc; // 총비행거리
private String ttlDstncType; // 총비행거리단위
private Double avrgSpeed; // 평균속도
private String avrgSpeedType; // 평균속도단위
private Double bttrCnsmptn; // 배터리소모량
private String endTypeCd; // 종료타입코드
private LocalDateTime createDt; // 생성일시
private LocalDateTime updateDt; // 수정일시
public CtrCntrlBas toEntity(){
return CtrCntrlBas.builder()
.cntrlId(this.cntrlId)
.idntfNum(this.idntfNum)
.statusCd(this.statusCd)
.procStatusYn(this.procStatusYn)
.objectTypeCd(this.objectTypeCd)
.flghtStDt(this.flghtStDt)
.flghtEndDt(this.flghtEndDt)
.cntrlStDt(this.cntrlStDt)
.cntrlEndDt(this.cntrlEndDt)
.ttlTime(this.ttlTime)
.ttlTimeType(this.ttlTimeType)
.ttlDstnc(this.ttlDstnc)
.ttlDstncType(this.ttlDstncType)
.avrgSpeed(this.avrgSpeed)
.avrgSpeedType(this.avrgSpeedType)
.bttrCnsmptn(this.bttrCnsmptn)
.endTypeCd(this.endTypeCd)
.createDt(this.createDt)
.updateDt(this.updateDt)
.build();
}
}

57
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/buffer/BufferAreaCoordModel.java

@ -0,0 +1,57 @@
package kr.co.palnet.kac.api.v1.flight.plan.model.buffer;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.api.util.model.FlightPlanAreaCoordModel;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BufferAreaCoordModel {
@Schema(description = "비행구역좌표 일련번호", example = "1")
private Long planAreaCoordSno;
@Schema(description = "비행계획비행구역 일련번호", example = "1")
private Long planAreaSno;
@Schema(description = "위도", example = "127.33")
private double lat;
@Schema(description = "경도", example = "37.99")
private double lon;
@Schema(description = "생성자ID", hidden = true)
private String createUserId;
@Schema(description = "생성일시", hidden = true)
private LocalDateTime createDt;
@Schema(hidden = true)
private String docState = "R";
public static FlightPlanAreaCoordModel toCoordModel(BufferAreaCoordModel model){
FlightPlanAreaCoordModel coordModel = new FlightPlanAreaCoordModel();
coordModel.setPlanAreaCoordSno(model.getPlanAreaCoordSno());
coordModel.setPlanAreaSno(model.getPlanAreaSno());
coordModel.setLat(model.getLat());
coordModel.setLon(model.getLon());
coordModel.setCreateUserId(model.getCreateUserId());
coordModel.setCreateDt(model.getCreateDt());
coordModel.setDocState(model.getDocState());
return coordModel;
}
public static BufferAreaCoordModel toModel(FlightPlanAreaCoordModel model){
BufferAreaCoordModel coordModel = new BufferAreaCoordModel();
coordModel.setPlanAreaCoordSno(model.getPlanAreaCoordSno());
coordModel.setPlanAreaSno(model.getPlanAreaSno());
coordModel.setLat(model.getLat());
coordModel.setLon(model.getLon());
coordModel.setCreateUserId(model.getCreateUserId());
coordModel.setCreateDt(model.getCreateDt());
coordModel.setDocState(model.getDocState());
return coordModel;
}
}

58
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/buffer/CreateBufferModel.java

@ -0,0 +1,58 @@
package kr.co.palnet.kac.api.v1.flight.plan.model.buffer;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.palnet.kac.api.v1.flight.laanc.model.constant.FltMethod;
import kr.co.palnet.kac.api.v1.flight.laanc.model.create.BasLaancAreaCoordModel;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class CreateBufferModel {
@Schema(description = "비행구역 일련번호", example = "1", hidden = true)
private Long planAreaSno;
@Schema(description = "비행계획서 일련번호", example = "1", hidden = true)
private Long planSno;
@Schema(description = "구역종류", example = "CIRCLE")
private String areaType;
@Schema(description = "비행방식", example = "01")
private FltMethod fltMethod;
@Schema(description = "비행구역주소", example = "인천광역시 부평구 청천2동")
private String fltAreaAddr;
@Schema(description = "버퍼존", example = "100")
private Integer bufferZone;
@Schema(description = "고도", example = "110")
private String fltElev;
@Schema(description = "생성자ID", hidden = true)
private String createUserId;
@Schema(description = "생성일시", hidden = true)
private LocalDateTime createDt;
@Schema(description = "수정자ID", hidden = true)
private String updateUserId;
@Schema(description = "수정일시", hidden = true)
private LocalDateTime updateDt;
private String docState = "R";
private List<BufferAreaCoordModel> coordList;
@Schema(hidden = true)
private List<BufferAreaCoordModel> bufferCoordList;
// kac 추가 필드
@Schema(description = "비행방식(기타)")
private String fltMothoeRm;
}

23
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/model/schedule/SearchPlanScheduleRS.java

@ -0,0 +1,23 @@
package kr.co.palnet.kac.api.v1.flight.plan.model.schedule;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class SearchPlanScheduleRS {
private String groupId;
private String groupNm;
private String ownerNm;
private String idntfNum;
private String startAddress;
private String endAddress;
private LocalDateTime schFltStDt;
private LocalDateTime schFltEndDt;
private String cntrlId;
private LocalDateTime cntrlStDt;
private LocalDateTime cntrlEndDt;
// BEFORE (B) : 비행 전, FLYING (F) : 비행 중, SUCCESS (S) : 비행 완료
private String statusCd;
}

109
web/api-flight/src/main/java/kr/co/palnet/kac/api/v1/flight/plan/service/FlightPlanService.java

@ -0,0 +1,109 @@
package kr.co.palnet.kac.api.v1.flight.plan.service;
import kr.co.palnet.kac.api.util.AreaUtils;
import kr.co.palnet.kac.api.util.model.FlightPlanAreaCoordModel;
import kr.co.palnet.kac.api.v1.flight.plan.model.CtrCntrlBasDTO;
import kr.co.palnet.kac.api.v1.flight.plan.model.buffer.BufferAreaCoordModel;
import kr.co.palnet.kac.api.v1.flight.plan.model.buffer.CreateBufferModel;
import kr.co.palnet.kac.api.v1.flight.plan.model.schedule.SearchPlanScheduleRS;
import kr.co.palnet.kac.data.ctr.model.CtrCntrlBas;
import kr.co.palnet.kac.data.ctr.model.join.CntrlJoinHstryAreaModel;
import kr.co.palnet.kac.data.ctr.service.CtrCntrlDomainService;
import kr.co.palnet.kac.data.flt.model.join.FltPlanBasJoinAreaModel;
import kr.co.palnet.kac.data.flt.service.FltPlanDomainService;
import kr.co.palnet.kac.data.pty.model.PtyGroupBas;
import kr.co.palnet.kac.data.pty.service.PtyGroupDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
@RequiredArgsConstructor
public class FlightPlanService {
private final FltPlanDomainService fltPlanDomainService;
private final PtyGroupDomainService ptyGroupDomainService;
private final CtrCntrlDomainService ctrCntrlDomainService;
private final AreaUtils areaUtils;
public List<CreateBufferModel> createBuffer(List<CreateBufferModel> rq) {
for (CreateBufferModel area : rq) {
if ("LINE".equals(area.getAreaType())) {
List<FlightPlanAreaCoordModel> coordList = area.getCoordList().stream().map(BufferAreaCoordModel::toCoordModel).toList();
List<Coordinate> convertCoordinates = areaUtils.convertCoordinates(coordList); // 객체 타입 변환
List<Coordinate> transCoordList = areaUtils.transform(convertCoordinates, "EPSG:4326", "EPSG:5181");
List<Coordinate> bufferList = areaUtils.buffer(transCoordList, area.getBufferZone()); // buffer 영역 생성
List<Coordinate> transBufferList = areaUtils.transform(bufferList, "EPSG:5181", "EPSG:4326"); // buffer 영역 좌표계 변환
List<BufferAreaCoordModel> bufferCoordList = areaUtils.convertModel(transBufferList).stream().map(BufferAreaCoordModel::toModel).toList();
area.setBufferCoordList(bufferCoordList);
}
}
return rq;
}
public List<SearchPlanScheduleRS> getPlanSchedule(String searchDate) {
Optional<List<FltPlanBasJoinAreaModel>> fltPlanBasJoinAreaData = fltPlanDomainService.findAllFltPlanBasBySearch(searchDate);
List<SearchPlanScheduleRS> result = new ArrayList<>();
if(fltPlanBasJoinAreaData.isPresent()){
List<FltPlanBasJoinAreaModel> planJoinArea = fltPlanBasJoinAreaData.get();
for(FltPlanBasJoinAreaModel model : planJoinArea){
Optional<List<CntrlJoinHstryAreaModel>> ctrJoinHstryAreaData = ctrCntrlDomainService.findCntrlJoinHstryAreaByIdntfNumAndSearchDate(model.getIdntfNum(), model.getSchFltStDt(), model.getSchFltEndDt());
SearchPlanScheduleRS node = new SearchPlanScheduleRS();
if(ctrJoinHstryAreaData.isPresent() && !ctrJoinHstryAreaData.get().isEmpty()){
CntrlJoinHstryAreaModel cntrlJoinHstryAreaModel = ctrJoinHstryAreaData.get().get(0);
node.setCntrlId(cntrlJoinHstryAreaModel.getCntrlId());
node.setStartAddress(cntrlJoinHstryAreaModel.getStartAddress());
node.setEndAddress(cntrlJoinHstryAreaModel.getEndAddress());
node.setCntrlStDt(cntrlJoinHstryAreaModel.getCntrlStDt());
node.setCntrlEndDt(cntrlJoinHstryAreaModel.getCntrlEndDt());
node.setStatusCd(cntrlJoinHstryAreaModel.getStatusCd());
} else {
continue;
}
PtyGroupBas ptyGroupBas = ptyGroupDomainService.findPtyGroupBasById(model.getGroupId());
node.setOwnerNm(model.getOwnerNm());
node.setIdntfNum(model.getIdntfNum());
node.setGroupId(model.getGroupId());
node.setSchFltStDt(model.getSchFltStDt());
node.setSchFltEndDt(model.getSchFltEndDt());
// node.setGroupId(ptyGroupBas.getGroupNm());
// TODO :: FLT모듈 추가시에는 그룹을 추가하는 코드가 없어 ""으로 대체 추후 그룹 추가시 주석은 풀고 아래코드는 삭제할것임
node.setGroupNm(ptyGroupBas == null ? "" : ptyGroupBas.getGroupNm());
result.add(node);
}
}
return result;
}
public void testCreateCtrCntrlBas(CtrCntrlBasDTO createData){
CtrCntrlBas ctrCntrlBas = ctrCntrlDomainService.saveCtrCntrlBas(createData.toEntity());
}
}

12524
web/api-flight/src/main/resources/air/airgeo.json

File diff suppressed because it is too large Load Diff

25326
web/api-flight/src/main/resources/air/elev2d/airgeo-elev.json

File diff suppressed because it is too large Load Diff

5547
web/api-flight/src/main/resources/air/elev2d/gimpo-airport-2d-elev.json

File diff suppressed because it is too large Load Diff

5891
web/api-flight/src/main/resources/air/elev2d/gimpo-airport-2d-elev.json.bak

File diff suppressed because it is too large Load Diff

5
web/api-flight/src/main/resources/air/sample/airgeo-3d.json

@ -0,0 +1,5 @@
{
"type": "FeatureCollection",
"features": [
]
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save