From 9f4f77fcc74c6d7f554c6747b7127155cb814e7e Mon Sep 17 00:00:00 2001 From: lulz1 Date: Thu, 1 Feb 2024 13:53:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 33 ++ .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 62547 bytes .mvn/wrapper/maven-wrapper.properties | 2 + mvnw | 308 ++++++++++++++++++ mvnw.cmd | 205 ++++++++++++ pom.xml | 96 ++++++ src/main/java/com/chint/RouteApplication.java | 13 + .../domain/aggregates/base/BaseEntity.java | 40 +++ .../chint/domain/aggregates/order/Leg.java | 109 +++++++ .../domain/aggregates/order/LegEvent.java | 32 ++ .../domain/aggregates/order/Location.java | 21 ++ .../domain/aggregates/order/RouteOrder.java | 106 ++++++ .../chint/domain/aggregates/user/User.java | 65 ++++ .../chint/domain/factoriy/OrderFactory.java | 8 + .../domain/factoriy/RouteOrderFactory.java | 11 + .../repositories/LegEventRepository.java | 12 + .../domain/repositories/LegRepository.java | 13 + .../repositories/LocationRepository.java | 8 + .../domain/repositories/RouteRepository.java | 11 + .../domain/repositories/UserRepository.java | 8 + .../domain/value_object/OrderCreateData.java | 4 + .../infrastructure/constant/Constant.java | 145 +++++++++ .../infrastructure/util/BaseContext.java | 20 ++ .../util/BigDecimalCalculator.java | 62 ++++ .../chint/infrastructure/util/JWTUtil.java | 44 +++ .../chint/infrastructure/util/PageResult.java | 25 ++ .../com/chint/infrastructure/util/Result.java | 52 +++ .../com/chint/infrastructure/util/Token.java | 13 + .../webconfig/JwtTokenAdminInterceptor.java | 41 +++ .../infrastructure/webconfig/WebConfig.java | 34 ++ .../interfaces/rest/base/PostRequest.java | 38 +++ .../rest/ctrip/CTripApprovalRequest.java | 29 ++ .../rest/ctrip/CTripEstimateRequest.java | 61 ++++ .../rest/ctrip/CTripLocationHttpRequest.java | 45 +++ .../rest/ctrip/CTripTicketRequest.java | 55 ++++ .../rest/ctrip/CTripTokenRequest.java | 27 ++ .../rest/ctrip/CTripUserSaveRequest.java | 57 ++++ .../rest/ctrip/LocationHttpRequest.java | 5 + .../rest/ctrip/dto/Authentication.java | 16 + .../ctrip/dto/AuthenticationResponseList.java | 11 + .../rest/ctrip/dto/Authentification.java | 17 + .../rest/ctrip/dto/ErrorMessage.java | 11 + .../rest/ctrip/dto/ResponseStatus.java | 12 + .../rest/ctrip/dto/ResponseSuccess.java | 13 + .../ctrip/dto/approval/ApprovalRequest.java | 125 +++++++ .../ctrip/dto/approval/ApprovalResult.java | 10 + .../rest/ctrip/dto/approval/CurrencyType.java | 17 + .../rest/ctrip/dto/approval/ExtendField.java | 8 + .../ctrip/dto/approval/PassengerDetail.java | 65 ++++ .../ctrip/dto/approval/ResponseStatus.java | 10 + .../approval/air/FlightEndorsementDetail.java | 100 ++++++ .../approval/air/FlightPreVerifyFields.java | 16 + .../dto/approval/air/FlightSkipFields.java | 20 ++ .../ctrip/dto/approval/air/FlightWayType.java | 14 + .../dto/approval/air/ProductTypeEnum.java | 11 + .../ctrip/dto/approval/air/SeatClassType.java | 17 + .../charter/CarCharterEndorsementDetail.java | 48 +++ .../charter/CarCharterPreVerifyFieldType.java | 16 + .../charter/CarCharterSkipFieldType.java | 18 + .../approval/endor/BusEndorsementDetail.java | 36 ++ .../dto/approval/endor/BusSkipFields.java | 13 + .../hotel/HotelEndorsementDetail.java | 71 ++++ .../approval/hotel/HotelPreVerifyFields.java | 13 + .../approval/hotel/HotelProductTypeEnum.java | 15 + .../dto/approval/hotel/HotelSkipFields.java | 20 ++ .../pick/CarPickUpEndorsementDetail.java | 36 ++ .../approval/pick/CarPickUpSkipFields.java | 19 ++ .../plan/TravelPlanEndorsementDetail.java | 31 ++ .../quick/CarQuickEndorsementDetail.java | 42 +++ .../approval/quick/CarQuickSkipFields.java | 16 + .../approval/quick/CompanyAddressDetail.java | 17 + .../ctrip/dto/approval/quick/RankInfo.java | 12 + .../ctrip/dto/approval/quick/RankStatus.java | 20 ++ .../dto/approval/quick/UseTimeDetail.java | 15 + .../rental/CarRentalEndorsementDetail.java | 44 +++ .../rental/CarRentalSkipFieldType.java | 15 + .../dto/approval/train/SeatTypeEnum.java | 17 + .../train/TrainEndorsementDetail.java | 69 ++++ .../approval/train/TrainPreVerifyFields.java | 14 + .../approval/train/TrainProductTypeEnum.java | 14 + .../dto/approval/train/TrainSkipFields.java | 17 + .../dto/approval/train/TripTypeEnum.java | 12 + .../ctrip/dto/estimate/request/AuthInfo.java | 20 ++ .../request/BookingRelatedApiRequest.java | 21 ++ .../BookingRelatedApiRequestBuilder.java | 272 ++++++++++++++++ .../estimate/request/FlightProductInfo.java | 18 + .../dto/estimate/request/LanguagesEnum.java | 5 + .../ctrip/dto/estimate/request/RouteInfo.java | 17 + .../estimate/request/TrainProductInfo.java | 14 + .../request/ValuateBudgetRequestType.java | 18 + .../estimate/request/ValuationBaseInfo.java | 16 + .../request/ValuationProductInfo.java | 14 + .../dto/estimate/response/AirlineInfo.java | 21 ++ .../response/AvailableProductEnum.java | 5 + .../response/BookingRelatedApiResponse.java | 18 + .../response/FlightValuationResult.java | 29 ++ .../response/HotelValuationResult.java | 18 + .../estimate/response/SeatMaxPriceInfo.java | 15 + .../response/TrainTypeDurationMinute.java | 13 + .../dto/estimate/response/TrainTypeEnum.java | 9 + .../response/TrainValuationResult.java | 22 ++ .../response/ValuateBudgetResponseType.java | 19 ++ .../response/ValuateBudgetResult.java | 14 + .../rest/ctrip/dto/location/City.java | 21 ++ .../rest/ctrip/dto/location/CityResponse.java | 14 + .../rest/ctrip/dto/location/Country.java | 13 + .../ctrip/dto/location/CountryResponse.java | 13 + .../rest/ctrip/dto/location/GetCountry.java | 16 + .../dto/location/GetCountryCityExtend.java | 19 ++ .../ctrip/dto/search/CarOrderInfoEntity.java | 4 + .../dto/search/CarQuickOrderInfoEntity.java | 4 + .../search/DomCharterCarOrderInfoEntity.java | 4 + .../search/DomPickUpCarOrderInfoEntity.java | 4 + .../dto/search/FlightOrderInfoEntity.java | 4 + .../dto/search/HotelOrderInfoEntity.java | 7 + .../dto/search/IntlTrainOrderInfoEntity.java | 4 + .../ctrip/dto/search/ItineraryEntity.java | 30 ++ .../ctrip/dto/search/SearchOrderRequest.java | 38 +++ .../ctrip/dto/search/SearchOrderResponse.java | 17 + .../dto/search/TrainOrderInfoEntity.java | 4 + .../rest/ctrip/dto/ticket/TicketParam.java | 16 + .../rest/ctrip/dto/ticket/TicketResponse.java | 12 + .../dto/token/GetUnionAccessTokenRequest.java | 35 ++ .../token/GetUnionAccessTokenResponse.java | 14 + .../ctrip/dto/user/AuthenticationEntity.java | 12 + .../ctrip/dto/user/AuthenticationInfo.java | 11 + .../dto/user/AuthenticationListRequest.java | 14 + .../interfaces/rest/ly/LYPostRequest.java | 53 +++ .../interfaces/rest/ly/LYTokenRequest.java | 33 ++ .../interfaces/rest/ly/LYUserRequest.java | 73 +++++ .../interfaces/rest/ly/dto/LYBaseRequest.java | 11 + .../rest/ly/dto/token/TokenParam.java | 42 +++ .../rest/ly/dto/token/TokenRequest.java | 13 + .../rest/ly/dto/token/TokenResponse.java | 84 +++++ .../rest/ly/dto/user/CostCenter.java | 10 + .../rest/ly/dto/user/EmployeeEntity.java | 36 ++ .../rest/ly/dto/user/EmployeeRequest.java | 15 + .../rest/ly/dto/user/PreTravelPolicy.java | 8 + .../rest/ly/dto/user/UserResponse.java | 68 ++++ .../interfaces/rest/ly/dto/user/UserSave.java | 4 + .../interfaces/rest/user/UserHttpRequest.java | 7 + .../rest/user/UserHttpRequestImpl.java | 101 ++++++ .../rest/user/dto/AccessKeyDTO.java | 8 + .../rest/user/dto/TravelRankDTO.java | 12 + .../rest/user/dto/TravelRankParam.java | 14 + .../rest/user/dto/TravelRankResponseDTO.java | 10 + .../interfaces/rest/user/dto/UserDataDTO.java | 148 +++++++++ src/main/resources/application-dev.yml | 11 + src/main/resources/application-prod.yml | 12 + src/main/resources/application.yml | 9 + src/test/java/com/chint/CTripTest.java | 38 +++ src/test/java/com/chint/LTTest.java | 34 ++ .../java/com/chint/RouteApplicationTests.java | 25 ++ 153 files changed, 4818 insertions(+) create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/com/chint/RouteApplication.java create mode 100644 src/main/java/com/chint/domain/aggregates/base/BaseEntity.java create mode 100644 src/main/java/com/chint/domain/aggregates/order/Leg.java create mode 100644 src/main/java/com/chint/domain/aggregates/order/LegEvent.java create mode 100644 src/main/java/com/chint/domain/aggregates/order/Location.java create mode 100644 src/main/java/com/chint/domain/aggregates/order/RouteOrder.java create mode 100644 src/main/java/com/chint/domain/aggregates/user/User.java create mode 100644 src/main/java/com/chint/domain/factoriy/OrderFactory.java create mode 100644 src/main/java/com/chint/domain/factoriy/RouteOrderFactory.java create mode 100644 src/main/java/com/chint/domain/repositories/LegEventRepository.java create mode 100644 src/main/java/com/chint/domain/repositories/LegRepository.java create mode 100644 src/main/java/com/chint/domain/repositories/LocationRepository.java create mode 100644 src/main/java/com/chint/domain/repositories/RouteRepository.java create mode 100644 src/main/java/com/chint/domain/repositories/UserRepository.java create mode 100644 src/main/java/com/chint/domain/value_object/OrderCreateData.java create mode 100644 src/main/java/com/chint/infrastructure/constant/Constant.java create mode 100644 src/main/java/com/chint/infrastructure/util/BaseContext.java create mode 100644 src/main/java/com/chint/infrastructure/util/BigDecimalCalculator.java create mode 100644 src/main/java/com/chint/infrastructure/util/JWTUtil.java create mode 100644 src/main/java/com/chint/infrastructure/util/PageResult.java create mode 100644 src/main/java/com/chint/infrastructure/util/Result.java create mode 100644 src/main/java/com/chint/infrastructure/util/Token.java create mode 100644 src/main/java/com/chint/infrastructure/webconfig/JwtTokenAdminInterceptor.java create mode 100644 src/main/java/com/chint/infrastructure/webconfig/WebConfig.java create mode 100644 src/main/java/com/chint/interfaces/rest/base/PostRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripApprovalRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripEstimateRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripLocationHttpRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripTicketRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripTokenRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/CTripUserSaveRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/LocationHttpRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentication.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/AuthenticationResponseList.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentification.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/ErrorMessage.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseStatus.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseSuccess.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalResult.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/CurrencyType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ExtendField.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/PassengerDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ResponseStatus.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightPreVerifyFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightWayType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/ProductTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/SeatClassType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterPreVerifyFieldType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterSkipFieldType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelPreVerifyFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelProductTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/plan/TravelPlanEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CompanyAddressDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankStatus.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/UseTimeDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalSkipFieldType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/SeatTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainEndorsementDetail.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainPreVerifyFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainProductTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainSkipFields.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TripTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/AuthInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequestBuilder.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/FlightProductInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/LanguagesEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/RouteInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/TrainProductInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuateBudgetRequestType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationBaseInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationProductInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AirlineInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AvailableProductEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/BookingRelatedApiResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/FlightValuationResult.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/HotelValuationResult.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/SeatMaxPriceInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeDurationMinute.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeEnum.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainValuationResult.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResponseType.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResult.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/City.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CityResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/Country.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CountryResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountry.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountryCityExtend.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarQuickOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomCharterCarOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomPickUpCarOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/FlightOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/HotelOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/IntlTrainOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/ItineraryEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/search/TrainOrderInfoEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketParam.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationInfo.java create mode 100644 src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationListRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/LYPostRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/LYTokenRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/LYUserRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/LYBaseRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenParam.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/CostCenter.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeEntity.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/PreTravelPolicy.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/UserResponse.java create mode 100644 src/main/java/com/chint/interfaces/rest/ly/dto/user/UserSave.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/UserHttpRequest.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/UserHttpRequestImpl.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/dto/AccessKeyDTO.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/dto/TravelRankDTO.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/dto/TravelRankParam.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/dto/TravelRankResponseDTO.java create mode 100644 src/main/java/com/chint/interfaces/rest/user/dto/UserDataDTO.java create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/test/java/com/chint/CTripTest.java create mode 100644 src/test/java/com/chint/LTTest.java create mode 100644 src/test/java/com/chint/RouteApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..cb28b0e37c7d206feb564310fdeec0927af4123a GIT binary patch literal 62547 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 A?*IS* literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..5f0536eb --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/mvnw b/mvnw new file mode 100644 index 00000000..66df2854 --- /dev/null +++ b/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 00000000..95ba6f54 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..acc5545a --- /dev/null +++ b/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.8 + + + com.chint + Route + 0.0.1-SNAPSHOT + Route + Route + + 17 + + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + org.springframework.boot + spring-boot-starter-web + + + + com.mysql + mysql-connector-j + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + com.google.code.gson + gson + 2.10.1 + + + com.chint.dc + common-api-sdk + 2.4.0 + + + com.auth0 + java-jwt + 4.4.0 + + + cn.hutool + hutool-all + 5.7.22 + + + com.github.xiaoymin + knife4j-spring-boot-starter + 3.0.3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + paketobuildpacks/builder-jammy-base:latest + + + + org.projectlombok + lombok + + + + + + + + diff --git a/src/main/java/com/chint/RouteApplication.java b/src/main/java/com/chint/RouteApplication.java new file mode 100644 index 00000000..dc12049d --- /dev/null +++ b/src/main/java/com/chint/RouteApplication.java @@ -0,0 +1,13 @@ +package com.chint; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RouteApplication { + + public static void main(String[] args) { + SpringApplication.run(RouteApplication.class, args); + } + +} diff --git a/src/main/java/com/chint/domain/aggregates/base/BaseEntity.java b/src/main/java/com/chint/domain/aggregates/base/BaseEntity.java new file mode 100644 index 00000000..73ed081e --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/base/BaseEntity.java @@ -0,0 +1,40 @@ +package com.chint.domain.aggregates.base; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; + +import java.time.LocalDateTime; + +@Data +public class BaseEntity { + + @ApiModelProperty("启用状态,1启动,0禁用") + public Integer status = 1; + + @ApiModelProperty("排序字段") + public Integer sort = 0; + + @CreatedBy + @ApiModelProperty("创建人标识") + public String createUser; + + @CreatedDate + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8") + public LocalDateTime createTime; + + @LastModifiedBy + @ApiModelProperty("最后更新人标识") + public String updateUser; + + @LastModifiedDate + @ApiModelProperty("最后更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8") + public LocalDateTime updateTime; +} diff --git a/src/main/java/com/chint/domain/aggregates/order/Leg.java b/src/main/java/com/chint/domain/aggregates/order/Leg.java new file mode 100644 index 00000000..c8e71014 --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/order/Leg.java @@ -0,0 +1,109 @@ +package com.chint.domain.aggregates.order; + + +import com.chint.domain.aggregates.base.BaseEntity; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import static com.chint.infrastructure.constant.Constant.*; + + +@Data +public class Leg extends BaseEntity { + + public Long legId; + public Integer legType; + + public LocalDateTime startTime; + public LocalDateTime endTime; + + public Integer sequence = 0; + + public Location origin; + + public Location destination; + + public Long routeId; + + public String amount; + + public String legTypeName; + + public Integer legStatus; + + public String legStatusName; + + private List eventList; + + + + public Leg reloadStatus() { + int eventLength = eventList.size() - 1; + this.legStatus = eventLength < 0 ? LEG_STATUS_PREPARE : eventLength; + if (legStatus > 1) { + Optional legEvent = this.eventList + .stream() + .filter(event -> event.getEventType().equals(LEG_EVENT_ORDERED)) + .findFirst(); + if (legEvent.isPresent()) { + LegEvent event = legEvent.get(); + this.amount = event.getOrderAmount(); + } + } + this.legStatusName = translateLegStatus(this.legStatus); + if (legType != null) { + this.legTypeName = translateLegType(this.legType); + } + return this; + } + + private String translateLegStatus(int status) { + return switch (status) { + case LEG_STATUS_PREPARE -> LEG_STATUS_PREPARE_NAME; + case LEG_STATUS_ORDERED -> LEG_STATUS_ORDERED_NAME; + case LEG_STATUS_PAYED -> LEG_STATUS_PAYED_NAME; + case LEG_STATUS_FINISH -> LEG_STATUS_FINISH_NAME; + default -> "未知状态"; + }; + } + + public String translateLegType(int type) { + return switch (type) { + case LEG_TYPE_TRAIN -> LEG_TYPE_TRAIN_NAME; + case LEG_TYPE_AIRPLANE -> LEG_TYPE_AIRPLANE_NAME; + case LEG_TYPE_HOTEL -> LEG_TYPE_HOTEL_NAME; + case LEG_TYPE_TAXI -> LEG_TYPE_TAXI_NAME; + case LEG_TYPE_OTHER -> LEG_TYPE_OTHER_NAME; + default -> "未知类型"; + }; + } + + private Optional getLatestEventType() { + return eventList.stream() + .map(LegEvent::getEventType) + .max(Integer::compareTo); + } + +// public void handleEvent(EventDTO eventDTO) { +// switch (this.legStatus) { +// case LEG_EVENT_PREPARE: +// handlePrepareEvent(legEventRepository); +// break; +// case LEG_EVENT_ORDERED: +// handleOrderedEvent(legEventRepository, eventDTO.orderDetail, eventDTO.orderAmount); +// break; +// case LEG_EVENT_PAYED: +// handlePayedEvent(legEventRepository, eventDTO.orderAmount); +// break; +// case LEG_EVENT_FINISH: +// handleFinishEvent(legEventRepository); +// break; +// default: +// // 处理未知事件类型或记录错误 +// break; +// } +// } +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/aggregates/order/LegEvent.java b/src/main/java/com/chint/domain/aggregates/order/LegEvent.java new file mode 100644 index 00000000..ca7d7d8c --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/order/LegEvent.java @@ -0,0 +1,32 @@ +package com.chint.domain.aggregates.order; + +import com.chint.domain.aggregates.base.BaseEntity; +import lombok.Data; + +import static com.chint.infrastructure.constant.Constant.*; + +@Data +public class LegEvent extends BaseEntity { + private Long legEventId; + + private Long legId; + + private Leg leg; + + private Integer eventType; + + private String eventName; + + private String orderAmount; + + + public String translateLegEvent(int event) { + return switch (event) { + case LEG_EVENT_PREPARE -> LEG_EVENT_PREPARE_NAME; + case LEG_EVENT_ORDERED -> LEG_EVENT_ORDERED_NAME; + case LEG_EVENT_PAYED -> LEG_EVENT_PAYED_NAME; + case LEG_EVENT_FINISH -> LEG_EVENT_FINISH_NAME; + default -> "未知事件"; + }; + } +} diff --git a/src/main/java/com/chint/domain/aggregates/order/Location.java b/src/main/java/com/chint/domain/aggregates/order/Location.java new file mode 100644 index 00000000..905fc87c --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/order/Location.java @@ -0,0 +1,21 @@ +package com.chint.domain.aggregates.order; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Location { + + private Long locationId; + private String locationPath; + private String locationPathName; + private String locationName; + private String locationShortName; + private Long parentLocationId; + private Integer level; + +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/aggregates/order/RouteOrder.java b/src/main/java/com/chint/domain/aggregates/order/RouteOrder.java new file mode 100644 index 00000000..73703229 --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/order/RouteOrder.java @@ -0,0 +1,106 @@ +package com.chint.domain.aggregates.order; + + +import com.chint.domain.aggregates.base.BaseEntity; +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BigDecimalCalculator; +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Table; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.chint.infrastructure.constant.Constant.*; + +@Data +@Table("route_order") +public class RouteOrder extends BaseEntity { + @Id + public Long routeId; + + private LocalDateTime bookingTime; + + private String amount; + + private Integer orderStatus; + + private String orderStatusName; + + private User user; + + public List legItems; + + + + public void addItemAtPosition(Leg newItem) { + Integer position = newItem.getSequence(); + if (position == null) { + position = this.legItems.size() + 1; + newItem.setSequence(position); + } + if (position < 0 || position > this.legItems.size() + 1) { + throw new IllegalArgumentException(PARAM_ERROR); + } + Integer streamPosition = position; + this.legItems.stream() + .filter(item -> item.getSequence() >= streamPosition) + .forEach(item -> item.setSequence(item.getSequence() + 1)); + newItem.setRouteId(this.routeId); + newItem.legId = newItem.getLegId(); + newItem.reloadStatus(); + } + + public List legOrdered() { + return this.legItems.stream() + .sorted(Comparator.comparingInt(Leg::getSequence)) + .collect(Collectors.toList()); + } + + public RouteOrder reloadStatus() { + this.amount = this.legItems + .stream() + .filter(leg -> leg.amount != null) + .map(Leg::getAmount) + .reduce(BigDecimalCalculator::add) + .orElse(KEEP_TWO_DECIMAL_ZERO); + this.updateStatus(); + this.orderStatusName = translateOrderStatus(this.orderStatus); + return this; + } + + public void updateStatus() { + if (allItemsInStatus(3)) { + this.orderStatus = 3; + } else if (allItemsInStatus(2)) { + this.orderStatus = 2; + } else if (allItemsInStatus(1)) { + this.orderStatus = 1; + } else { + this.orderStatus = 0; // 或其他适当的默认状态 + } + } + + private boolean allItemsInStatus(int targetStatus) { + for (Leg item : this.legItems) { + if (item.getLegStatus() < targetStatus) { + return false; + } + } + return true; + } + + private String translateOrderStatus(int status) { + return switch (status) { + case ORDER_STATUS_PREPARE -> ORDER_STATUS_PREPARE_NAME; + case ORDER_STATUS_ORDERED -> ORDER_STATUS_ORDERED_NAME; + case ORDER_STATUS_PAYED -> ORDER_STATUS_PAYED_NAME; + case ORDER_STATUS_FINISH -> ORDER_STATUS_FINISH_NAME; + default -> "未知状态"; + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/aggregates/user/User.java b/src/main/java/com/chint/domain/aggregates/user/User.java new file mode 100644 index 00000000..adb467b9 --- /dev/null +++ b/src/main/java/com/chint/domain/aggregates/user/User.java @@ -0,0 +1,65 @@ +package com.chint.domain.aggregates.user; + +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.chint.domain.aggregates.order.RouteOrder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +import static com.chint.infrastructure.constant.Constant.*; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class User { + + public Long userId; + public Long employeeNo; + public Integer employeeLevel; + public String name; + public String email; + public String gender; + public String phoneNumber; + public String password; + public String rankCode; + public String companyCode; + public String workStatus; + private List orders; + + public User(Long employeeNo) { + this.employeeNo = employeeNo; + } + + public User(Long userId, Long employeeNo, Integer employeeLevel, String name, String email, String phoneNumber) { + this.userId = userId; + this.employeeNo = employeeNo; + this.employeeLevel = employeeLevel; + this.name = name; + this.email = email; + this.phoneNumber = phoneNumber; + } + + public static User withEmployeeNo(Long employeeNo) { + return new User(employeeNo); + } + + public static User withJwt(DecodedJWT jwt) { + Map claims = jwt.getClaims(); + Claim userId = claims.get(USER_ID); + Claim phoneNumber = claims.get(USER_PHONE); + Claim email = claims.get(USER_EMAIL); + Claim employeeNo = claims.get(USER_EMPLOYEE_NO); + Claim name = claims.get(USER_NAME); + Claim employeeLevel = claims.get(USER_EMPLOYEE_LEVEL); + return new User(userId.asLong(), + employeeNo.asLong(), + employeeLevel.asInt(), + name.asString(), + email.asString(), + phoneNumber.asString()); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/factoriy/OrderFactory.java b/src/main/java/com/chint/domain/factoriy/OrderFactory.java new file mode 100644 index 00000000..ce62da84 --- /dev/null +++ b/src/main/java/com/chint/domain/factoriy/OrderFactory.java @@ -0,0 +1,8 @@ +package com.chint.domain.factoriy; + +import com.chint.domain.aggregates.order.RouteOrder; +import com.chint.domain.value_object.OrderCreateData; + +public interface OrderFactory { + RouteOrder createOrder(OrderCreateData orderData); +} diff --git a/src/main/java/com/chint/domain/factoriy/RouteOrderFactory.java b/src/main/java/com/chint/domain/factoriy/RouteOrderFactory.java new file mode 100644 index 00000000..cc3ea8e5 --- /dev/null +++ b/src/main/java/com/chint/domain/factoriy/RouteOrderFactory.java @@ -0,0 +1,11 @@ +package com.chint.domain.factoriy; + +import com.chint.domain.aggregates.order.RouteOrder; +import com.chint.domain.value_object.OrderCreateData; + +public class RouteOrderFactory implements OrderFactory{ + @Override + public RouteOrder createOrder(OrderCreateData orderData) { + return null; + } +} diff --git a/src/main/java/com/chint/domain/repositories/LegEventRepository.java b/src/main/java/com/chint/domain/repositories/LegEventRepository.java new file mode 100644 index 00000000..a18f55f2 --- /dev/null +++ b/src/main/java/com/chint/domain/repositories/LegEventRepository.java @@ -0,0 +1,12 @@ +package com.chint.domain.repositories; + +import com.chint.domain.aggregates.order.Leg; +import com.chint.domain.aggregates.order.LegEvent; + +import java.util.List; + +public interface LegEventRepository { + void deleteByLegId(Leg leg); + List findAllByLegId(Long id); + LegEvent save(LegEvent legEvent); +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/repositories/LegRepository.java b/src/main/java/com/chint/domain/repositories/LegRepository.java new file mode 100644 index 00000000..f93f8739 --- /dev/null +++ b/src/main/java/com/chint/domain/repositories/LegRepository.java @@ -0,0 +1,13 @@ +package com.chint.domain.repositories; + +import com.chint.domain.aggregates.order.Leg; +import com.chint.domain.aggregates.order.RouteOrder; + +import java.util.List; + +public interface LegRepository { + Leg save(Leg bookingItem); + void deleteById(Long id); + List findByOrder(RouteOrder order); + void saveAll(List bookingItems); +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/repositories/LocationRepository.java b/src/main/java/com/chint/domain/repositories/LocationRepository.java new file mode 100644 index 00000000..286ea099 --- /dev/null +++ b/src/main/java/com/chint/domain/repositories/LocationRepository.java @@ -0,0 +1,8 @@ +package com.chint.domain.repositories; + +import com.chint.domain.aggregates.order.Location; + +public interface LocationRepository { +// List findByHot(List locationHots); + Location findByLocationId(Long locationId); +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/repositories/RouteRepository.java b/src/main/java/com/chint/domain/repositories/RouteRepository.java new file mode 100644 index 00000000..617b0388 --- /dev/null +++ b/src/main/java/com/chint/domain/repositories/RouteRepository.java @@ -0,0 +1,11 @@ +package com.chint.domain.repositories; + +import com.chint.domain.aggregates.order.RouteOrder; +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.PageResult; + +public interface RouteRepository { + RouteOrder queryById(Long orderId); + RouteOrder save(RouteOrder routeOrder); + PageResult pageQuery(User user); +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/repositories/UserRepository.java b/src/main/java/com/chint/domain/repositories/UserRepository.java new file mode 100644 index 00000000..0da5be81 --- /dev/null +++ b/src/main/java/com/chint/domain/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.chint.domain.repositories; + +import com.chint.domain.aggregates.user.User; + +public interface UserRepository { + User findById(Long id); + User findByUserEmployeeNo(Long employeeNo); +} \ No newline at end of file diff --git a/src/main/java/com/chint/domain/value_object/OrderCreateData.java b/src/main/java/com/chint/domain/value_object/OrderCreateData.java new file mode 100644 index 00000000..fcc06c74 --- /dev/null +++ b/src/main/java/com/chint/domain/value_object/OrderCreateData.java @@ -0,0 +1,4 @@ +package com.chint.domain.value_object; + +public class OrderCreateData { +} diff --git a/src/main/java/com/chint/infrastructure/constant/Constant.java b/src/main/java/com/chint/infrastructure/constant/Constant.java new file mode 100644 index 00000000..342648fc --- /dev/null +++ b/src/main/java/com/chint/infrastructure/constant/Constant.java @@ -0,0 +1,145 @@ +package com.chint.infrastructure.constant; + +public class Constant { + // 通用消息 + // 通用消息 + public static final String SUCCESS = "操作成功"; + public static final String FAILURE = "操作失败"; + public static final String NOT_FOUND = "未找到相关数据"; + public static final String INVALID_REQUEST = "无效的请求"; + public static final String ACCESS_DENIED = "访问被拒绝"; + public static final String SERVER_ERROR = "服务器错误"; + + // 数据相关消息 + public static final String DATA_ALREADY_EXISTS = "数据已存在"; + public static final String DATA_UPDATE_SUCCESS = "数据更新成功"; + public static final String DATA_CREATION_SUCCESS = "数据创建成功"; + public static final String DATA_DELETION_SUCCESS = "数据删除成功"; + public static final String DATA_NOT_FOUND = "未找到数据"; + public static final String DATA_INVALID = "数据不合法"; + + // JWT 验证消息 + public static final String JWT_INVALID = "无效的 JWT 令牌"; + public static final String JWT_EXPIRED = "JWT 令牌已过期"; + public static final String JWT_REQUIRED = "需要 JWT 令牌"; + public static final String JWT_ACCESS_DENIED = "JWT 令牌不足以访问此资源"; + + // 用户认证消息 + public static final String AUTHENTICATION_FAILED = "认证失败"; + public static final String LOGIN_SUCCESS = "登录成功"; + public static final String LOGIN_FAILURE = "登录失败"; + public static final String LOGOUT_SUCCESS = "成功登出"; + + // 系统消息 + public static final String SYSTEM_MAINTENANCE = "系统维护中"; + public static final String SYSTEM_UPGRADE = "系统升级中"; + + // Param + public static final String PARAM_ERROR = "参数错误"; + + // 订单状态 + public static final int ORDER_STATUS_PREPARE = 0; + public static final String ORDER_STATUS_PREPARE_NAME = "规划中"; + public static final int ORDER_STATUS_ORDERED = 1; + public static final String ORDER_STATUS_ORDERED_NAME = "已下单"; + public static final int ORDER_STATUS_PAYED = 2; + public static final String ORDER_STATUS_PAYED_NAME = "已付款"; + public static final int ORDER_STATUS_FINISH = 3; + public static final String ORDER_STATUS_FINISH_NAME = "已结束"; + + // 规划节点状态 + public static final int LEG_STATUS_PREPARE = 0; + public static final String LEG_STATUS_PREPARE_NAME = "规划中"; + public static final int LEG_STATUS_ORDERED = 1; + public static final String LEG_STATUS_ORDERED_NAME = "已下单"; + public static final int LEG_STATUS_PAYED = 2; + public static final String LEG_STATUS_PAYED_NAME = "已付款"; + public static final int LEG_STATUS_FINISH = 3; + public static final String LEG_STATUS_FINISH_NAME = "已结束"; + + // 规划节点运输方式 + public static final int LEG_TYPE_TRAIN = 0; + public static final String LEG_TYPE_TRAIN_NAME = "火车"; + public static final int LEG_TYPE_AIRPLANE = 1; + public static final String LEG_TYPE_AIRPLANE_NAME = "飞机"; + public static final int LEG_TYPE_HOTEL = 2; + public static final String LEG_TYPE_HOTEL_NAME = "酒店"; + public static final int LEG_TYPE_TAXI = 3; + public static final String LEG_TYPE_TAXI_NAME = "出租车"; + public static final int LEG_TYPE_OTHER = 4; + public static final String LEG_TYPE_OTHER_NAME = "其他"; + + // 规划节点事件 + public static final int LEG_EVENT_PREPARE = 0; + public static final String LEG_EVENT_PREPARE_NAME = "初始事件"; + public static final int LEG_EVENT_ORDERED = 1; + public static final String LEG_EVENT_ORDERED_NAME = "下单事件"; + public static final int LEG_EVENT_PAYED = 2; + public static final String LEG_EVENT_PAYED_NAME = "付款事件"; + public static final int LEG_EVENT_FINISH = 3; + public static final String LEG_EVENT_FINISH_NAME = "结束事件"; + + // 金额 + public static final String KEEP_TWO_DECIMAL_ZERO = "0.00"; + + // 登录信息 + public static final String USER_ID = "userId"; + public static final String USER_PHONE = "phoneNumber"; + public static final String USER_EMAIL = "email"; + public static final String USER_EMPLOYEE_NO = "employeeNo"; + public static final String USER_NAME = "name"; + public static final String USER_EMPLOYEE_LEVEL = "employeeLevel"; + public static final String USER_RANK_CODE = "rankCode"; + public static final String USER_COMPANY_CODE = "companyCode"; + + // JWT + public static final String SECRET = "Superdandan"; // 替换为你自己的密钥 + public static final String SUBJECT = "EmployeeNo"; + public static final long EXPIRATION_TIME_MS = 3600000L; // 1小时过期时间 + public static final String HEADER_TOKEN = "token"; + + // URL + public static final String AK_BASE_URL = "http://10.10.100.184:7052"; + public static final String GET_AK_URL = "/api/DataCenter/GetKey"; + public static final String UPDATE_AK_PATH = "/api/DataCenter/UpdataKey"; + public static final String ADD_AK_URL = "/api/DataCenter/AddKey"; + public static final String SYSTEM_ID = "e72991a531a340b8a017139a6b51db3d"; + public static final String OPENAI_BASE_URL = "https://openapi.chintcloud.net"; + public static final String USER_DATA_PATH = "/open/HR/commonuserlist"; + public static final String TRAVEL_RANK_BASE_URL = "http://10.10.14.178:8080"; + public static final String TRAVEL_RANK_PATH = "/fssc/queryBill/queryTravelLevelByRank"; + + // 携程 + public static final String C_TRIP_BASE_URL = "https://ct.ctrip.com"; + public static final String TICKET_PATH = "/SwitchAPI/Order/Ticket"; + public static final String C_TRIP_APP_KEY = "obk_zhengtai"; // 测试appkey + public static final String C_TRIP_APP_SECURITY = "obk_zhengtai"; // 测试app秘钥 + public static final String USER_SAVE_PATH = "/corpservice/CorpCustService/SaveCorpCustInfoList"; + public static final String HOTEL_CITY_PATH = "/corpopenapi/HotelCity/GetCountryCityExtend"; + public static final String HOTEL_COUNTRY_PATH = "/corpopenapi/HotelCity/GetCountry"; + public static final String AIR_AIRPORT_PATH = "/flightBaseData/queryAirPort"; + public static final String AIR_CITY_PATH = "/flightBaseData/queryCity"; + public static final String AIR_PROVINCE_PATH = "/flightBaseData/queryProvince"; + public static final String AIR_COUNTRY_PATH = "/flightBaseData/queryCountry"; + public static final String TRAIN_CITY_PATH = "/dataapi/train/inter/searchBizLocationList"; + public static final String LANGUAGE_CN = "zh-CN"; + public static final String C_TRIP_USER_SAVE_PATH = "/corpservice/CorpCustService/SaveCorpCustInfoList"; + public static final String C_TRIP_APPROVAL_PATH = "/switchapi/approval.svc/rest/setapproval"; + public static final String C_TRIP_ESTIMATE_PATH = "/bookingrelatedservice/bookingrelatedopenapi"; + public static final String C_TRIP_TOKEN_PATH = "/dataservice/token/getAccessToken"; + public static final String C_TRIP_ORDER_SEARCH_PATH = "/switchapi/Order/SearchOrder"; + + + //同程 + public static final String L_Y_BASE_URL = "https://api.qa.dttrip.cn"; + public static final String L_Y_TOKEN_PATH = "/openapi/api/OAuth/v2/GetAccessToken"; + public static final String L_Y_USER_PATH = "/openapi/api/Employee/SyncEmployeeInfo"; + public static final String L_Y_ACCOUNT = "4f9cb1080b564dd0a94aa95f7a19c8b5"; // 测试appkey + public static final String L_Y_PASSWORD = "1fD3SutgzfS48qznYQiq"; // 测试app秘钥 + public static final String L_Y_SECRET = "WOHzCMvHd823iHgH"; // 测试app秘钥 + + + + // status + public static final int STATUS_DISABLED = 0; +} diff --git a/src/main/java/com/chint/infrastructure/util/BaseContext.java b/src/main/java/com/chint/infrastructure/util/BaseContext.java new file mode 100644 index 00000000..c4dbc4fd --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/BaseContext.java @@ -0,0 +1,20 @@ +package com.chint.infrastructure.util; + +import com.chint.domain.aggregates.user.User; + +public class BaseContext { + + private static final ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void setCurrentUser(User user) { + threadLocal.set(user); + } + + public static User getCurrentUser() { + return threadLocal.get(); + } + + public static void removeCurrentUser() { + threadLocal.remove(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/util/BigDecimalCalculator.java b/src/main/java/com/chint/infrastructure/util/BigDecimalCalculator.java new file mode 100644 index 00000000..3fc08730 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/BigDecimalCalculator.java @@ -0,0 +1,62 @@ +package com.chint.infrastructure.util; + +import java.math.BigDecimal; + +import static com.chint.infrastructure.constant.Constant.KEEP_TWO_DECIMAL_ZERO; + +public class BigDecimalCalculator { + + public static String add(String operand1, String operand2) { + try { + BigDecimal decimal1 = new BigDecimal(operand1).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal decimal2 = new BigDecimal(operand2).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal result = decimal1.add(decimal2).setScale(2, BigDecimal.ROUND_HALF_UP); + return result.toString(); + } catch (Exception e) { + return KEEP_TWO_DECIMAL_ZERO; + } + } + + public static String subtract(String operand1, String operand2) { + try { + BigDecimal decimal1 = new BigDecimal(operand1).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal decimal2 = new BigDecimal(operand2).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal result = decimal1.subtract(decimal2).setScale(2, BigDecimal.ROUND_HALF_UP); + return result.toString(); + } catch (Exception e) { + return KEEP_TWO_DECIMAL_ZERO; + } + } + + public static String multiply(String operand1, String operand2) { + try { + BigDecimal decimal1 = new BigDecimal(operand1).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal decimal2 = new BigDecimal(operand2).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal result = decimal1.multiply(decimal2).setScale(2, BigDecimal.ROUND_HALF_UP); + return result.toString(); + } catch (Exception e) { + return KEEP_TWO_DECIMAL_ZERO; + } + } + + public static String divide(String operand1, String operand2) { + try { + BigDecimal decimal1 = new BigDecimal(operand1).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal decimal2 = new BigDecimal(operand2).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal result = decimal1.divide(decimal2, 2, BigDecimal.ROUND_HALF_UP); + return result.toString(); + } catch (Exception e) { + return KEEP_TWO_DECIMAL_ZERO; + } + } + + public static String negateBigDecimal(String value) { + try { + BigDecimal original = new BigDecimal(value).setScale(2, BigDecimal.ROUND_HALF_UP); + BigDecimal negated = original.negate().setScale(2, BigDecimal.ROUND_HALF_UP); + return negated.toString(); + } catch (Exception e) { + return KEEP_TWO_DECIMAL_ZERO; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/util/JWTUtil.java b/src/main/java/com/chint/infrastructure/util/JWTUtil.java new file mode 100644 index 00000000..eb66e9a1 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/JWTUtil.java @@ -0,0 +1,44 @@ +package com.chint.infrastructure.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Date; +import java.util.Map; + +import static com.chint.infrastructure.constant.Constant.EXPIRATION_TIME_MS; +import static com.chint.infrastructure.constant.Constant.SECRET; + +public class JWTUtil { + + public static String createJWT(String SECRET, long EXPIRATION_TIME_MS, String subject, Map claims) { + Date issuedAt = new Date(); + Date expiresAt = new Date(issuedAt.getTime() + EXPIRATION_TIME_MS); + return JWT.create() + .withSubject(subject) + .withIssuedAt(issuedAt) + .withExpiresAt(expiresAt) + .withPayload(claims) + .sign(Algorithm.HMAC256(SECRET)); + } + + public static String createJWT(String subject, Map claims) { + return createJWT(SECRET, EXPIRATION_TIME_MS, subject, claims); + } + + public static DecodedJWT parseJWT(String SECRET, String token) { + return JWT.require(Algorithm.HMAC256(SECRET)) + .build() + .verify(token); + } + + public static boolean verifyJWT(String SECRET, String token) { + try { + parseJWT(SECRET, token); + return true; + } catch (Exception ex) { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/util/PageResult.java b/src/main/java/com/chint/infrastructure/util/PageResult.java new file mode 100644 index 00000000..69bca8ba --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/PageResult.java @@ -0,0 +1,25 @@ +package com.chint.infrastructure.util; + +import java.util.List; + +public class PageResult { + private long total; + private List records; + + public PageResult(long total, List records) { + this.total = total; + this.records = records; + } + + public static PageResult page(List res) { + return new PageResult<>(res.size(), res); + } + + public static PageResult totalPageNum(long totalNum, List res) { + return new PageResult<>(totalNum, res); + } + + public static PageResult empty() { + return new PageResult<>(0, List.of()); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/util/Result.java b/src/main/java/com/chint/infrastructure/util/Result.java new file mode 100644 index 00000000..0453c688 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/Result.java @@ -0,0 +1,52 @@ +package com.chint.infrastructure.util; + +import java.io.Serializable; +import java.util.Objects; + +public class Result implements Serializable { + private String msg; + private String code; + private T data; + + public Result() {} + + public Result(String msg, String code, T data) { + this.msg = msg; + this.code = code; + this.data = data; + } + + public Result(String msg, String code) { + this.msg = msg; + this.code = code; + } + + // Getter and Setter methods + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Result result = (Result) o; + return Objects.equals(msg, result.msg) && + Objects.equals(code, result.code) && + Objects.equals(data, result.data); + } + + @Override + public int hashCode() { + return Objects.hash(msg, code, data); + } + + public static Result success(String msg, T data) { + return new Result<>(msg, "1", data); + } + + public static Result success(String msg) { + return new Result<>(msg, "1"); + } + + public static Result error(String msg) { + return new Result<>(msg, "0"); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/util/Token.java b/src/main/java/com/chint/infrastructure/util/Token.java new file mode 100644 index 00000000..4d0cce40 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/util/Token.java @@ -0,0 +1,13 @@ +package com.chint.infrastructure.util; + +public class Token { + private String token; + + private Token(String token) { + this.token = token; + } + + public static Token of(String token) { + return new Token(token); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/webconfig/JwtTokenAdminInterceptor.java b/src/main/java/com/chint/infrastructure/webconfig/JwtTokenAdminInterceptor.java new file mode 100644 index 00000000..976af752 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/webconfig/JwtTokenAdminInterceptor.java @@ -0,0 +1,41 @@ +package com.chint.infrastructure.webconfig; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.infrastructure.util.JWTUtil; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.servlet.HandlerInterceptor; + +import static com.chint.infrastructure.constant.Constant.*; + + +public class JwtTokenAdminInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = request.getHeader(HEADER_TOKEN); + + if (request.getRequestURI().endsWith("/login")) { + return true; + } + + if (token == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().write(JWT_REQUIRED); + return false; + } + + try { + JWTUtil.verifyJWT(SECRET, token); + var parseJWT = JWTUtil.parseJWT(SECRET, token); + var withJwt = User.withJwt(parseJWT); + BaseContext.setCurrentUser(withJwt); + return true; // If verification succeeds, continue processing the request + } catch (Exception e) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().write(JWT_INVALID); + return false; // Verification failed, deny request + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/webconfig/WebConfig.java b/src/main/java/com/chint/infrastructure/webconfig/WebConfig.java new file mode 100644 index 00000000..5bdd1252 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/webconfig/WebConfig.java @@ -0,0 +1,34 @@ +package com.chint.infrastructure.webconfig; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + +// @Bean +// public JwtTokenAdminInterceptor JwtTokenAdminInterceptor() { +// return new JwtTokenAdminInterceptor(); +// } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new JwtTokenAdminInterceptor()) + .addPathPatterns("/**") + .excludePathPatterns("/public/**", "/login"); + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true) + .maxAge(3600); + } +} diff --git a/src/main/java/com/chint/interfaces/rest/base/PostRequest.java b/src/main/java/com/chint/interfaces/rest/base/PostRequest.java new file mode 100644 index 00000000..e3979607 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/base/PostRequest.java @@ -0,0 +1,38 @@ +package com.chint.interfaces.rest.base; + +import com.google.gson.Gson; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class PostRequest { + private final Gson gson = new Gson(); + private final HttpClient client = HttpClients.createDefault(); + + public T post(String url, Object jsonRequest, Class responseType) { + HttpPost post = new HttpPost(url); + post.setEntity(new StringEntity(gson.toJson(jsonRequest), ContentType.APPLICATION_JSON)); + String responseBody = null; + try { + HttpResponse response = client.execute(post); + HttpEntity responseEntity = response.getEntity(); + responseBody = EntityUtils.toString(responseEntity, "UTF-8"); + } catch (IOException e) { + throw new RuntimeException(e); + } + return gson.fromJson(responseBody, responseType); + } + + public Gson gson() { + return gson; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripApprovalRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripApprovalRequest.java new file mode 100644 index 00000000..418e73b8 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripApprovalRequest.java @@ -0,0 +1,29 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.approval.ApprovalRequest; +import com.chint.interfaces.rest.ctrip.dto.approval.ApprovalResult; +import com.chint.interfaces.rest.ctrip.dto.Authentication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import static com.chint.infrastructure.constant.Constant.*; + +@Service +public class CTripApprovalRequest { + + private String approvalUrl = C_TRIP_BASE_URL + C_TRIP_APPROVAL_PATH; + + @Autowired + private CTripTicketRequest ticketRequest; + + @Autowired + private PostRequest postRequest; + + public ApprovalResult approval(ApprovalRequest approvalRequest) { + String ticket = ticketRequest.loadTicket(); + approvalRequest.setStatus(0); + approvalRequest.setAuth(Authentication.of(C_TRIP_APP_KEY, ticket)); + return postRequest.post(approvalUrl, approvalRequest, ApprovalResult.class); + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripEstimateRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripEstimateRequest.java new file mode 100644 index 00000000..21b60a99 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripEstimateRequest.java @@ -0,0 +1,61 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.estimate.request.AuthInfo; +import com.chint.interfaces.rest.ctrip.dto.estimate.request.BookingRelatedApiRequest; +import com.chint.interfaces.rest.ctrip.dto.estimate.request.FlightProductInfo; +import com.chint.interfaces.rest.ctrip.dto.estimate.request.TrainProductInfo; +import com.chint.interfaces.rest.ctrip.dto.estimate.response.BookingRelatedApiResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import static com.chint.infrastructure.constant.Constant.*; + +@Component +public class CTripEstimateRequest { + + private String apiName = "bookingRelatedOpenApi.valuateBudget"; + + private String estimateUrl = C_TRIP_BASE_URL + C_TRIP_ESTIMATE_PATH; + + @Autowired + private CTripTokenRequest tokenRequest; + + @Autowired + private PostRequest postRequest; + + public BookingRelatedApiResponse estimate(BookingRelatedApiRequest bookingRelatedApiRequest) { + return postRequest.post(estimateUrl, bookingRelatedApiRequest, BookingRelatedApiResponse.class); + } + + public BookingRelatedApiRequest generateBaseRequest(FlightProductInfo flightProductInfo, TrainProductInfo trainProductInfo) { + BookingRelatedApiRequest bookingRelatedApiRequest = new BookingRelatedApiRequest(); + String token = tokenRequest.getToken(); + bookingRelatedApiRequest.setApiName(apiName); + bookingRelatedApiRequest.setLanguage(LANGUAGE_CN); + bookingRelatedApiRequest.setAuthInfo(AuthInfo.of(C_TRIP_APP_KEY, token)); + User user = BaseContext.getCurrentUser(); + return BookingRelatedApiRequest.builder() + .language(LANGUAGE_CN) + .apiName(apiName) + .authInfo() + .details(C_TRIP_APP_KEY, token) + .done() + .requestContent() + .valuationBaseInfo() + .eID(user.employeeNo.toString()) + .corpID("zhengtai") + .rankName(user.getRankCode()) + .done() + .valuationProductInfo() + .addFlightProductInfo(flightProductInfo) + .addTrainProductInfo(trainProductInfo) + .done() + .done() + .build(); + } + + +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripLocationHttpRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripLocationHttpRequest.java new file mode 100644 index 00000000..64c8ea93 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripLocationHttpRequest.java @@ -0,0 +1,45 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.*; +import com.chint.interfaces.rest.ctrip.dto.location.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static com.chint.infrastructure.constant.Constant.*; + +@Service +public class CTripLocationHttpRequest implements LocationHttpRequest { + + + @Autowired + private PostRequest postRequest; + + @Autowired + private CTripTicketRequest ticketRequest; + + private static final String locationCityUrl = C_TRIP_BASE_URL + HOTEL_CITY_PATH; + private static final String locationCountryUrl = C_TRIP_BASE_URL + HOTEL_COUNTRY_PATH; + + + @Override + public void syncLocation() { +// cityRepository.saveAll(syncCity()); +// countryRepository.saveAll(syncCountry()); + } + + public List syncCountry() { + Object jsonRequest = new GetCountry(new Authentification(C_TRIP_APP_KEY, ticketRequest.loadTicket()), LANGUAGE_CN); + CountryResponse response = postRequest.post(locationCountryUrl, jsonRequest, CountryResponse.class); + return response.getData(); + } + + public List syncCity() { + Authentification authentification = new Authentification(C_TRIP_APP_KEY, ticketRequest.loadTicket()); + GetCountryCityExtend getCountryCityExtend = new GetCountryCityExtend(authentification, LANGUAGE_CN, 2); + CityResponse response = postRequest.post(locationCityUrl, getCountryCityExtend, CityResponse.class); + return response.getData(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripTicketRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripTicketRequest.java new file mode 100644 index 00000000..c3b31520 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripTicketRequest.java @@ -0,0 +1,55 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.ticket.TicketParam; +import com.chint.interfaces.rest.ctrip.dto.ticket.TicketResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +import static com.chint.infrastructure.constant.Constant.*; + +@Component +public class CTripTicketRequest { + + @Autowired + private PostRequest postRequest; + + private final String ticketUrl = C_TRIP_BASE_URL + TICKET_PATH; + private final TicketParam ticketParam = new TicketParam(C_TRIP_APP_KEY, C_TRIP_APP_SECURITY); + + // Data class to store ticket and expiry time + public static class CachedTicket { + private final String ticket; + private final LocalDateTime expiryTime; + + public CachedTicket(String ticket, LocalDateTime expiryTime) { + this.ticket = ticket; + this.expiryTime = expiryTime; + } + + public String getTicket() { + return ticket; + } + + public LocalDateTime getExpiryTime() { + return expiryTime; + } + } + + // Cached ticket instance + private CachedTicket cachedTicket = null; + + public String loadTicket() { + // Check if the cached ticket exists and is valid + if (cachedTicket != null && cachedTicket.getExpiryTime().isAfter(LocalDateTime.now())) { + return cachedTicket.getTicket(); + } + System.out.println(ticketParam); + TicketResponse ticket = postRequest.post(ticketUrl, ticketParam, TicketResponse.class); + // Update the cache with an expiry time of 2 hours from the current time + cachedTicket = new CachedTicket(ticket.getTicket(), LocalDateTime.now().plusHours(2)); + return ticket.getTicket(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripTokenRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripTokenRequest.java new file mode 100644 index 00000000..5d97243d --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripTokenRequest.java @@ -0,0 +1,27 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.token.GetUnionAccessTokenRequest; +import com.chint.interfaces.rest.ctrip.dto.token.GetUnionAccessTokenResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import static com.chint.infrastructure.constant.Constant.*; + +@Service +public class CTripTokenRequest { + + private String tokenUrl = C_TRIP_BASE_URL + C_TRIP_TOKEN_PATH; + + + @Autowired + private PostRequest postRequest; + + public String getToken() { + GetUnionAccessTokenRequest getUnionAccessTokenRequest = + GetUnionAccessTokenRequest.of(C_TRIP_APP_KEY, C_TRIP_APP_SECURITY, 1); + return postRequest + .post(tokenUrl, getUnionAccessTokenRequest, GetUnionAccessTokenResponse.class) + .getAccessToken(); + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/CTripUserSaveRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/CTripUserSaveRequest.java new file mode 100644 index 00000000..ea46ecd2 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/CTripUserSaveRequest.java @@ -0,0 +1,57 @@ +package com.chint.interfaces.rest.ctrip; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ctrip.dto.user.AuthenticationEntity; +import com.chint.interfaces.rest.ctrip.dto.user.AuthenticationInfo; +import com.chint.interfaces.rest.ctrip.dto.user.AuthenticationListRequest; +import com.chint.interfaces.rest.user.UserHttpRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.chint.interfaces.rest.ctrip.dto.AuthenticationResponseList; +import java.util.List; + +import static com.chint.infrastructure.constant.Constant.*; + +@Service +public class CTripUserSaveRequest { + @Autowired + private PostRequest postRequest; + + @Autowired + private UserHttpRequest userHttpRequest; + + @Autowired + private CTripTicketRequest ticketRequest; + + private final String userUrl = C_TRIP_BASE_URL + C_TRIP_USER_SAVE_PATH; + + public void saveUserToCTrip() { + User currentUser = BaseContext.getCurrentUser(); + User user = userHttpRequest.loadUserInfo(currentUser); + String ticket = ticketRequest.loadTicket(); + AuthenticationEntity authenticationEntity = buildAuthenticationEntityWithUser(user); + AuthenticationListRequest authenticationListRequest = new AuthenticationListRequest(); + authenticationListRequest.setAppkey(C_TRIP_APP_KEY); + authenticationListRequest.setTicket(ticket); + authenticationListRequest.setCorporationID("zhengtai"); + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + authenticationInfo.setSequence("0"); + authenticationInfo.setAuthentication(authenticationEntity); + authenticationListRequest.setAuthenticationInfoList(List.of(authenticationInfo)); + AuthenticationResponseList post = postRequest.post(userUrl, authenticationInfo, AuthenticationResponseList.class); + System.out.println(post); + } + + + public AuthenticationEntity buildAuthenticationEntityWithUser(User user) { + AuthenticationEntity authenticationEntity = new AuthenticationEntity(); + authenticationEntity.setName(user.getName()); + authenticationEntity.setEmployeeID(user.getEmployeeNo().toString()); + authenticationEntity.setRankName(user.getRankCode()); + authenticationEntity.setValid(user.getWorkStatus()); + authenticationEntity.setSubAccountName("zhengtai_提前审批测试"); + return authenticationEntity; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/LocationHttpRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/LocationHttpRequest.java new file mode 100644 index 00000000..2efcdfdf --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/LocationHttpRequest.java @@ -0,0 +1,5 @@ +package com.chint.interfaces.rest.ctrip; + +public interface LocationHttpRequest { + void syncLocation(); +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentication.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentication.java new file mode 100644 index 00000000..e03351ba --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentication.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Authentication { + private String appKey; + private String ticket; + // Getters and setters... + + public static Authentication of(String appKey, String ticket) { + return new Authentication(appKey, ticket); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/AuthenticationResponseList.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/AuthenticationResponseList.java new file mode 100644 index 00000000..5af22998 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/AuthenticationResponseList.java @@ -0,0 +1,11 @@ +package com.chint.interfaces.rest.ctrip.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class AuthenticationResponseList { + private String Result; + private List ErrorMessageList; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentification.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentification.java new file mode 100644 index 00000000..4d94b60e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/Authentification.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +public class Authentification { + private String AppKey; + private String Ticket; + + public Authentification(String appKey, String ticket) { + AppKey = appKey; + Ticket = ticket; + } + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/ErrorMessage.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ErrorMessage.java new file mode 100644 index 00000000..0d1dde5c --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ErrorMessage.java @@ -0,0 +1,11 @@ +package com.chint.interfaces.rest.ctrip.dto; + +import lombok.Data; + +@Data +public class ErrorMessage { + private int Sequence; + private String ErrorCode; + private String Message; + private String EmployeeID; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseStatus.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseStatus.java new file mode 100644 index 00000000..4f72ab89 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseStatus.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.ctrip.dto; + +import lombok.Data; + +@Data +public class ResponseStatus { + private Boolean Success; + private int ErrorCode; + private String Message; + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseSuccess.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseSuccess.java new file mode 100644 index 00000000..4aeb3134 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ResponseSuccess.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto; + +public class ResponseSuccess { + + // 是否成功 + private boolean success; + // 消息内容 + private String message; + // 错误代码 + private int errorCode; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalRequest.java new file mode 100644 index 00000000..134b9e03 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalRequest.java @@ -0,0 +1,125 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +import com.chint.interfaces.rest.ctrip.dto.Authentication; +import com.chint.interfaces.rest.ctrip.dto.approval.air.FlightEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.charter.CarCharterEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.endor.BusEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.hotel.HotelEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.pick.CarPickUpEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.plan.TravelPlanEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.quick.CarQuickEndorsementDetail; +import com.chint.interfaces.rest.ctrip.dto.approval.quick.RankInfo; +import com.chint.interfaces.rest.ctrip.dto.approval.train.TrainEndorsementDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class ApprovalRequest { + // 审批单号 - 必填 + // OA审批通过时生成,同步审批单编号,用于标识审批单 + private String approvalNumber; + + // 状态 - 必填 + // 0为审批中,1为审批通过,2为审批拒绝 + private int status; + + // 携程卡号 - 非必填 + // N表示非必填,多个携程卡号以逗号隔开,长度不能超过500个字符且不重复。 + private String ctripCardNO; + + // 员工编号 - 非必填 + // N表示非必填,多个员工编号以逗号隔开,长度不能超过500个字符且不重复。 + private String employeeID; + + // 机票背书信息详情列表 - 必填 + // Y表示必填项,用于记录一条审批单中的一条或多条航班信息,详细信息格式见3.3.2节的JSON数据交互格式详细说明。 + private List flightEndorsementDetails; + + // 酒店背书信息详情列表 - 必填 + // Y表示必填项。 + private List hotelEndorsementDetails; + + // 火车背书信息详情列表 - 必填 + // Y表示必填项。 + private List trainEndorsementDetails; + + // 租车背书信息详情列表 - 必填 + // Y表示必填项。 + private List carQuickEndorsementDetails; + + // 接送车背书信息详情列表 - 必填 + // Y表示必填项。 + private List carPickUpEndorsementDetails; + + // 包车背书信息详情列表 - 必填 + // Y表示必填项。 + private List carCharterEndorsementDetails; + + // 巴士背书信息详情列表 - 必填 + // Y表示必填项。 + private List busEndorsementDetails; + + // 出差计划背书信息详情列表 - 必填 + // Y表示必填项。 + private List travelPlanEndorsementDetails; + + // 有效期 - 非必填 + // 有效期格式为日期时间,起始时间从2017-01-01开始。 + private String expiredTime; + + // 认证信息 - 非必填 + // 携程分配给客户公司,具体见下表描述。 + private Authentication auth; + + // 成本中心等扩展字段列表,非必填,如无该需求则不需要传 + // Y表示必填项。 + private List extendFieldList; + + // 备注 - 必填 + // Y表示必填项。 + private String remark; + + // 职级信息 - 非必填 + // 职级信息(仅限于职级信息的前20) + private RankInfo rankInfo; + + public ApprovalRequest(String approvalNumber, String employeeID, RankInfo rankInfo) { + this.approvalNumber = approvalNumber; + this.employeeID = employeeID; + this.rankInfo = rankInfo; + } + + public static ApprovalRequest buildApproval(String employeeID, String approvalNumber, RankInfo rankInfo) { + return new ApprovalRequest(employeeID, approvalNumber, rankInfo); + } + + public ApprovalRequest withAir(List flightEndorsementDetails) { + this.flightEndorsementDetails = flightEndorsementDetails; + return this; + } + + public ApprovalRequest withTrain(List hotelEndorsementDetails) { + this.hotelEndorsementDetails = hotelEndorsementDetails; + return this; + } + + public ApprovalRequest withBus(List busEndorsementDetails) { + this.busEndorsementDetails = busEndorsementDetails; + return this; + } + + public ApprovalRequest withPickCar(List carPickUpEndorsementDetails) { + this.carPickUpEndorsementDetails = carPickUpEndorsementDetails; + return this; + } + + public ApprovalRequest withQuickCar(List carQuickEndorsementDetails) { + this.carQuickEndorsementDetails = carQuickEndorsementDetails; + return this; + } + public ApprovalRequest withHotel(List hotelEndorsementDetails) { + this.hotelEndorsementDetails = hotelEndorsementDetails; + return this; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalResult.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalResult.java new file mode 100644 index 00000000..84d55944 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ApprovalResult.java @@ -0,0 +1,10 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +import lombok.Data; + +@Data +public class ApprovalResult { + + private ResponseStatus Status; + +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/CurrencyType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/CurrencyType.java new file mode 100644 index 00000000..b6c46cd7 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/CurrencyType.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +public class CurrencyType { + public final static Integer UnKnow = 0; + public final static Integer RMB = 1; + public final static Integer CNY = 2; + public final static Integer HKD = 3; + public final static Integer USD = 4; + public final static Integer EUR = 5; + public final static Integer SGD = 6; + public final static Integer MOP = 7; + public final static Integer JPY = 8; + public final static Integer THB = 9; + public final static Integer AUD = 10; + public final static Integer GBP = 11; + +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ExtendField.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ExtendField.java new file mode 100644 index 00000000..45eece79 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ExtendField.java @@ -0,0 +1,8 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +public class ExtendField { + private String fieldName; + private String fieldValue; + private String fieldType; + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/PassengerDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/PassengerDetail.java new file mode 100644 index 00000000..ac04c051 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/PassengerDetail.java @@ -0,0 +1,65 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +import java.util.List; + +public class PassengerDetail { + + // 姓名 - 必填 + // 中文姓名,例如,张三 - 中文姓名最后人员填写必选项,通用汉字集合。 + // (外籍名例如泰国人员NameEn代入) + // 由三部分组成的姓名字段(Name/EID/NameEn 选择其中一) + private String name; + + // 证件类型 - 必填 + // 证件类型列举证件类型编码请详看附件,类型编码数字不下发 + private String credentialsType; + + // 证件号码 - 必填 + // 如果是证件号码,则用于后续证件件号码合理性检查, + // 可包含数字和字母,用于检查合理性;如果是证件证 + // 号,判断所证件证件号码与实际填写情况。 + private String credentialsNumber; + + // 出行人EID - 必填 + // 出行人员信息(Name/EID/NameEn 选择其中一) + // 出行人员信息不会涉及隐私泄露: + // AveragePrice>policyid>rankname>eid + private String EID; + + // 英文姓名 - 必填 + // 英文姓名,例如,中文张三对应英文名字Zhang/San + // (英文名不区分大小写) 中美英姓名填写指导原则如外籍人员人名, + // 可包含英文字母,用于国际航空运输。 + // 通用国际音标对照lastname/firstname + // 可容纳姓名人数最多限制数据 + // 由三部分组成的姓名字段(Name/EID/NameEn 选择其中一) + private String nameEn; + + // 职级名称 - 必填 + // 出行人员信息不会涉及隐私泄露: + // AveragePrice>policyid>rankname>eid + private String rankName; + + // 政策规则EID - 必填 + // 出行人员信息不会涉及隐私泄露: + // AveragePrice>policyid>rankname>eid + private String policyEID; + + // 国家代码 - 必填 + // 如果手机号为空,国外为空,则默认填写为中国大陆区号 + private String countryCode; + + // 手机号码 - 必填 + // 手机中心存储的手机号码,非必填,如无法检索则不下发数据; + // 支持境外、港澳,文件有国际区号为准。一、二、 + // 四、五、六(酒店方在出行人员中心同一字段使用,机票 + // 和火车票方面) + private String mobilePhone; + + // 扩展字段列表 - 可选 + // 不支持新增扩展 + private List extendFieldList; + + // Getters and setters for each field would be included below... + +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ResponseStatus.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ResponseStatus.java new file mode 100644 index 00000000..7c1cb0d4 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/ResponseStatus.java @@ -0,0 +1,10 @@ +package com.chint.interfaces.rest.ctrip.dto.approval; + +import lombok.Data; + +@Data +public class ResponseStatus { + private Boolean Success; + private String Message; + private Integer ErrorCode; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightEndorsementDetail.java new file mode 100644 index 00000000..3c81f3d8 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightEndorsementDetail.java @@ -0,0 +1,100 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class FlightEndorsementDetail { + + // 订票类型列表 - 1张, 2张, 3张, 超过3张 + private List bookingTypeList; + + // 订单ID列表 - 最多20个 + private List orderIDList; + + // 航空公司名称 - 不可为空字符串 + private String airline; + + // 货币类型 - 默认CNY + private CurrencyType currency; + + // 航班类型 - 单程(1) or 往返(2) + private FlightWayType flightWay; + + // 起飞日期开始时间 - 格式: yyyy-MM-dd + private String departDateBegin; + + // 起飞日期结束时间 - 格式: yyyy-MM-dd + private String departDateEnd; + + // 返回日期开始时间 - 格式: yyyy-MM-dd + private String returnDateBegin; + + // 返回日期结束时间 - 格式: yyyy-MM-dd + private String returnDateEnd; + + // 起飞时间开始时间 - 格式: HH:mm + private String takeOffBeginTime; + + // 起飞时间结束时间 - 格式: HH:mm + private String takeOffEndTime; + + // 到达时间开始时间 - 格式: HH:mm + private String arrivalBeginTime; + + // 到达时间结束时间 - 格式: HH:mm + private String arrivalEndTime; + + // 折扣率 - 0.1到1.0, 0代表无折扣 + private float discount; + + // 出发国家ID列表 - 最多1000个 + private List departCountryIds; + + // 出发国家代码列表 - 最多1000个 + private List departCountryCodes; + + // 出发城市代码列表 - 最多1000个 + private List departCityCodes; + + // 到达国家ID列表 - 最多1000个 + private List arrivalCountryIds; + + // 到达城市代码列表 - 最多1000个 + private List arrivalCityCodes; + + // 出发城市ID列表 - 最多1000个 + private List departCityIds; + + // 到达城市ID列表 - 最多1000个 + private List arrivalCityIds; + + // 乘客列表 - 无数量限制 + private List passengerList; + + // 价格 - 可为负数, 默认为0 + private float price; + + // 产品类型 - 1代表经济舱, 2代表商务舱 + private ProductTypeEnum productType; + + // 座位等级 - 经济舱(3), 商务舱(2), 头等舱(1) + private SeatClassType seatClass; + + // 跳过的字段位 - 用于标记不包含的字段 + private long skipFields; + + // 旅客数量 - 无限制 + private int travelerCount; + + // 总旅客数量 - 用于统计 + private int totalTravelerCount; + + // 预验证字段位 - 用于标记需要预验证的字段 + private long preVerifyFields; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightPreVerifyFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightPreVerifyFields.java new file mode 100644 index 00000000..29b8f70e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightPreVerifyFields.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +// Additional FlightPreVerifyFields constants based on the new image provided +public class FlightPreVerifyFields { + public static final long Airline = 1; // 航空公司字段 + public static final long DepartDateBegin = 2; // 起飞日期开始字段 + public static final long DepartDateEnd = 4; // 起飞日期结束字段 + public static final long DepartCityCodes = 16; // 出发城市代码字段 + public static final long PassengerList = 32; // 乘客列表字段 + public static final long ReturnDateBegin = 128; // 返回日期开始字段 + public static final long ReturnDateEnd = 256; // 返回日期结束字段 + public static final long SeatClass = 512; // 座位等级字段 + public static final long ArrivalCityCodes = 1024; // 到达城市代码字段 + public static final long FlightWay = 65536; // 航班类型字段 + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightSkipFields.java new file mode 100644 index 00000000..b00371ac --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightSkipFields.java @@ -0,0 +1,20 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +import lombok.Data; + +@Data +public class FlightSkipFields { + public static final long Airline = 1; // 航空公司字段 + public static final long DepartDateBegin = 2; // 起飞日期开始字段 + public static final long DepartDateEnd = 4; // 起飞日期结束字段 + public static final long Discount = 8; // 折扣字段 + public static final long DepartCityCodes = 16; // 出发城市代码字段 + public static final long PassengerList = 32; // 乘客列表字段 + public static final long Price = 64; // 价格字段 + public static final long ReturnDateBegin = 128; // 返回日期开始字段 + public static final long ReturnDateEnd = 256; // 返回日期结束字段 + public static final long SeatClass = 512; // 座位等级字段 + public static final long ArrivalCityCodes = 1024; // 到达城市代码字段 + // ... Other fields follow with their corresponding bit values + // Note that this is not an exhaustive list due to the image being cut off. +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightWayType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightWayType.java new file mode 100644 index 00000000..3ce1efad --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/FlightWayType.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +public enum FlightWayType { + SingleTrip(1), // 单程 + RoundTrip(2); // 往返 + + private final int value; + + FlightWayType(int value) { + this.value = value; + } + + // Getter... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/ProductTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/ProductTypeEnum.java new file mode 100644 index 00000000..57fee95f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/ProductTypeEnum.java @@ -0,0 +1,11 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +public enum ProductTypeEnum { + IN(1), // 单程 + OUT(2); // 往返 + private final int value; + + ProductTypeEnum(int value) { + this.value = value; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/SeatClassType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/SeatClassType.java new file mode 100644 index 00000000..ab5e584c --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/air/SeatClassType.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.air; + +public enum SeatClassType { + UnKnown(0), // 未知 + SaloonCabin(1), // 沙龙舱 + BusinessClass(2), // 商务舱 + SuperTouristClass(4), // 超级旅游舱 + TouristClass(3); // 旅游舱 + + private final int value; + + SeatClassType(int value) { + this.value = value; + } + + // Getter... +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterEndorsementDetail.java new file mode 100644 index 00000000..db0ae027 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterEndorsementDetail.java @@ -0,0 +1,48 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.charter; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; + +import java.util.List; + +public class CarCharterEndorsementDetail { + + // 产品类型 + private int productType; + // 乘客列表, 最多100名 + private List passengerList; + // 出发城市代码 + private String departCities; + // 到达城市代码 + private String arriveCities; + // 开始使用日期 + private String beginUseDate; + // 结束使用日期 + private String endUseDate; + // 开始使用时间 + private String beginUseTime; + // 结束使用时间 + private String endUseTime; + // 使用天数 + private int useDays; + // 货币类型, 默认CNY + private CurrencyType currency; + // 价格,默认为0 + private float price; + // 车辆组 + private String vehicleGroup; + // 跳过的字段位 + private long skipFields; + // 预验证字段位 + private long preVerifyFields; + // 座位数 + private int seatsNum; + // 组合ID + private String comboID; + // 版本号 + private int version; + // 总旅客数 + private int totalTravelerCount; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterPreVerifyFieldType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterPreVerifyFieldType.java new file mode 100644 index 00000000..d679bd89 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterPreVerifyFieldType.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.charter; + +public class CarCharterPreVerifyFieldType { + public static final long BeginUseDate = 1; // 开始使用日期字段预验证标志 + public static final long EndUseDate = 2; // 结束使用日期字段预验证标志 + public static final long BeginUseTime = 4; // 开始使用时间字段预验证标志 + public static final long EndUseTime = 8; // 结束使用时间字段预验证标志 + public static final long DepartCities = 16; // 出发城市字段预验证标志 + public static final long ArriveCities = 32; // 到达城市字段预验证标志 + public static final long VehicleGroup = 64; // 车辆组字段预验证标志 + public static final long SeatsNum = 128; // 座位数字段预验证标志 + public static final long ComboID = 256; // 组合ID字段预验证标志 + public static final long PassengerList = 512; // 乘客列表字段预验证标志 + public static final long UseDays = 1024; // 使用天数字段预验证标志 + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterSkipFieldType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterSkipFieldType.java new file mode 100644 index 00000000..1ae64883 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/charter/CarCharterSkipFieldType.java @@ -0,0 +1,18 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.charter; + +public class CarCharterSkipFieldType { + public static final long BeginUseDate = 1; // 开始使用日期字段跳过标志 + public static final long EndUseDate = 2; // 结束使用日期字段跳过标志 + public static final long BeginUseTime = 4; // 开始使用时间字段跳过标志 + public static final long EndUseTime = 8; // 结束使用时间字段跳过标志 + public static final long DepartCities = 16; // 出发城市字段跳过标志 + public static final long ArriveCities = 32; // 到达城市字段跳过标志 + public static final long VehicleGroup = 64; // 车辆组字段跳过标志 + public static final long SeatsNum = 128; // 座位数字段跳过标志 + public static final long ComboID = 256; // 组合ID字段跳过标志 + public static final long PassengerList = 512; // 乘客列表字段跳过标志 + public static final long UseDays = 1024; // 使用天数字段跳过标志 + public static final long Price = 2048; // 价格字段跳过标志 + public static final long Currency = 4096; // 货币字段跳过标志 + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusEndorsementDetail.java new file mode 100644 index 00000000..f0d437b3 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusEndorsementDetail.java @@ -0,0 +1,36 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.endor; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class BusEndorsementDetail { + + // 产品类型 + private int productType; + // 乘客列表,最多100名 + private List passengerList; + // 出发城市代码 + private List departCityCodes; + // 到达城市代码 + private List arrivalCityCodes; + // 出发开始日期 + private String departBeginDate; + // 出发结束日期 + private String departEndDate; + // 货币类型,默认CNY + private CurrencyType currency; + // 价格,默认为0 + private float price; + // 跳过的字段位 + private long skipFields; + // 预验证字段位 + private long preVerifyFields; + // 总旅客数 + private int totalTravelerCount; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusSkipFields.java new file mode 100644 index 00000000..f9201f5f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/endor/BusSkipFields.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.endor; + +public class BusSkipFields { + public static final long TripWay = 1; + public static final long DepartBeginDate = 2; + public static final long DepartEndDate = 4; + public static final long PassengerList = 8; + public static final long DepartCityCodeList = 16; + public static final long ArrivalCityCodeList = 32; + public static final long Price = 64; + public static final long Currency = 128; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelEndorsementDetail.java new file mode 100644 index 00000000..2451991e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelEndorsementDetail.java @@ -0,0 +1,71 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.hotel; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; + +import java.util.List; + +public class HotelEndorsementDetail { + + // 产品类型 + private HotelProductTypeEnum productType; + + // 入住开始日期 - 格式: yyyy-MM-dd + private String checkInDateBegin; + + // 入住结束日期 - 格式: yyyy-MM-dd + private String checkInDateEnd; + + // 离店开始日期 - 格式: yyyy-MM-dd + private String checkOutDateBegin; + + // 离店结束日期 - 格式: yyyy-MM-dd + private String checkOutDateEnd; + + // 乘客列表 + private List passengerList; + + // 入住国家ID列表 + private List checkInCountryIds; + + // 入住国家代码列表 + private List checkInCountryCodes; + + // 入住城市代码列表 + private List checkInCityCodes; + + // 最高价格 + private String maxPrice; + + // 最低价格 + private String minPrice; + + // 货币类型 - 默认CNY + private CurrencyType currency; + + // 最大星级 + private String maxStarRating; + + // 最小星级 + private String minStarRating; + + // 平均价格 + private String averagePrice; + + // 房间数量 + private int roomCount; + + // 跳过的字段位 - 用于标记不包含的字段 + private long skipFields; + + // 总房晚数 + private int totalRoomNightCount; + + // 房晚价格 + private String roomNightPrice; + + // 预验证字段位 - 用于标记需要预验证的字段 + private long preVerifyFields; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelPreVerifyFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelPreVerifyFields.java new file mode 100644 index 00000000..89539d57 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelPreVerifyFields.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.hotel; + +// HotelPreVerifyFields constants +public class HotelPreVerifyFields { + public static final long CheckInDateBegin = 1; + public static final long CheckInDateEnd = 2; + public static final long CheckOutDateBegin = 4; + public static final long CheckOutDateEnd = 8; + public static final long PassengerList = 16; + public static final long CheckInCityCodes = 32; + public static final long AveragePrice = 2048; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelProductTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelProductTypeEnum.java new file mode 100644 index 00000000..7713897a --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelProductTypeEnum.java @@ -0,0 +1,15 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.hotel; + +// HotelProductTypeEnum definition based on the provided image +public enum HotelProductTypeEnum { + Domestic(3), // 国内酒店 + International(4); // 国际酒店 + + private final int value; + + HotelProductTypeEnum(int value) { + this.value = value; + } + + // Getter... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelSkipFields.java new file mode 100644 index 00000000..71d26e06 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/hotel/HotelSkipFields.java @@ -0,0 +1,20 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.hotel; + +// HotelSkipFields constants based on the provided image +public class HotelSkipFields { + public static final long CheckInDateBegin = 1; + public static final long CheckInDateEnd = 2; + public static final long CheckOutDateBegin = 4; + public static final long CheckOutDateEnd = 8; + public static final long PassengerList = 16; + public static final long CheckInCityCodes = 32; + public static final long MaxPrice = 64; + public static final long MinPrice = 128; + public static final long Currency = 256; + public static final long MaxStarRating = 512; + public static final long MinStarRating = 1024; + public static final long AveragePrice = 2048; + public static final long RoomCount = 4096; + public static final long RoomNightPrice = 8192; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpEndorsementDetail.java new file mode 100644 index 00000000..2bdb9441 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpEndorsementDetail.java @@ -0,0 +1,36 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.pick; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; + +import java.util.List; + +public class CarPickUpEndorsementDetail { + + // 产品类型 + private int productType; + // 乘客列表, 最多100名 + private List passengerList; + // 城市代码 + private String cities; + // 接车开始日期 + private String pickUpBeginDate; + // 接车结束日期 + private String pickUpEndDate; + // 送车开始日期 + private String dropOffBeginDate; + // 送车结束日期 + private String dropOffEndDate; + // 货币类型, 默认CNY + private CurrencyType currency; + // 价格,默认为0 + private float price; + // 车辆组 + private String vehicleGroup; + // 有效性金额 + private int effectivenessAmount; + // 跳过的字段位 + private long skipFields; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpSkipFields.java new file mode 100644 index 00000000..c31cc6b2 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/pick/CarPickUpSkipFields.java @@ -0,0 +1,19 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.pick; + +// CarPickUpSkipFields bit field constants + +import lombok.Data; + +@Data +public class CarPickUpSkipFields { + public static final long PassengerList = 1; // 乘客列表 + public static final long Cities = 2; // 城市代码 + public static final long PickUpBeginDate = 4; // 接车开始日期 + public static final long PickUpEndDate = 8; // 接车结束日期 + public static final long DropOffBeginDate = 16; // 送车开始日期 + public static final long DropOffEndDate = 32; // 送车结束日期 + public static final long Price = 64; // 价格 + public static final long Currency = 128; // 货币类型 + public static final long VehicleGroup = 256; // 车辆组 + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/plan/TravelPlanEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/plan/TravelPlanEndorsementDetail.java new file mode 100644 index 00000000..a402b6c1 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/plan/TravelPlanEndorsementDetail.java @@ -0,0 +1,31 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.plan; + +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class TravelPlanEndorsementDetail { + + // 出差开始日期 + private String travelStartDate; + // 出差结束日期 + private String travelEndDate; + // 出发城市代码 + private String departCities; + // 到达城市代码 + private String arriveCities; + // 允许的产品类型列表 + private List allowProductTypes; + // 租车取车模式类型列表 + private List carPickupPatternTypes; + // 乘客列表 + private List passengerList; + // 酒店是否允许延迟退房 + private boolean hotelCheckOutDelay; + // 预验证字段 + private String preVerifyFields; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickEndorsementDetail.java new file mode 100644 index 00000000..c3334897 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickEndorsementDetail.java @@ -0,0 +1,42 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; +import lombok.Data; + +import java.util.List; + +@Data +public class CarQuickEndorsementDetail { + + // 产品类型 + private int productType; + // 乘客列表, 最多100名 + private List passengerList; + // 城市代码 + private String cities; + // 公司地址列表 + private List companyAddressList; + // 到达地址列表 + private List arrivalAddressList; + // 开始使用日期 + private String beginUseDate; + // 结束使用日期 + private String endUseDate; + // 使用时间列表 + private List useTimeList; + // 货币类型, 默认CNY + private CurrencyType currency; + // 价格,默认为0 + private float price; + // 车辆组 + private String vehicleGroup; + // 有效性金额 + private int effectivenessAmount; + // 跳过的字段位 + private long skipFields; + // 到达城市代码 + private String arrivalCities; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickSkipFields.java new file mode 100644 index 00000000..5cbc9ecd --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CarQuickSkipFields.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + +public class CarQuickSkipFields { + public static final long PassengerList = 1; // 乘客列表 + public static final long Cities = 2; // 城市代码 + public static final long CompanyAddressList = 4; // 公司地址列表 + public static final long BeginUseDate = 8; // 开始使用日期 + public static final long EndUseDate = 16; // 结束使用日期 + public static final long UseTimeList = 32; // 使用时间列表 + public static final long Currency = 64; // 货币类型 + public static final long Price = 128; // 价格 + public static final long VehicleGroup = 256; // 车辆组 + public static final long ArrivalAddressList = 512; // 到达地址列表 + public static final long ArrivalCities = 1024; // 到达城市代码 + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CompanyAddressDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CompanyAddressDetail.java new file mode 100644 index 00000000..69377796 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/CompanyAddressDetail.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + +public class CompanyAddressDetail { + + // 坐标类型 + private String coordinateType; + // 地址名称 + private String addressName; + // 经度 + private String longitude; + // 纬度 + private String latitude; + // 允许半径 + private int allowRadius; + + // Getters and setters... +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankInfo.java new file mode 100644 index 00000000..9500d6ec --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankInfo.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + +import lombok.Data; + +// RankInfo class +@Data +public class RankInfo { + // 职级名称 + private String rankName; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankStatus.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankStatus.java new file mode 100644 index 00000000..2adbdf4e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/RankStatus.java @@ -0,0 +1,20 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + + +// Enumeration for the provided table related to rank or status +public enum RankStatus { + UNKNOWN(1), // 未知 + LEVEL_2(2), // 二级 + LEVEL_3(3), // 三级 + LEVEL_4(4), // 四级 + // ... other levels + LEVEL_7(7); // 七级 + + private final int id; + + RankStatus(int id) { + this.id = id; + } + + // Getter... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/UseTimeDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/UseTimeDetail.java new file mode 100644 index 00000000..81e66dda --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/quick/UseTimeDetail.java @@ -0,0 +1,15 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.quick; + +// UseTimeDetail class + +import lombok.Data; + +@Data +public class UseTimeDetail { + // 开始使用时间, 格式为HHmm + private String beginUseTime; + // 结束使用时间, 格式为HHmm + private String endUseTime; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalEndorsementDetail.java new file mode 100644 index 00000000..3eeb40dd --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalEndorsementDetail.java @@ -0,0 +1,44 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.rental; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; + +import java.util.List; + +public class CarRentalEndorsementDetail { + + // 产品类型 + private int productType; + // 乘客列表,最多100名 + private List passengerList; + // 接车城市代码 + private String pickUpCities; + // 送车城市代码 + private String dropOffCities; + // 接车开始日期 + private String pickUpBeginDate; + // 接车结束日期 + private String pickUpEndDate; + // 送车开始日期 + private String dropOffBeginDate; + // 送车结束日期 + private String dropOffEndDate; + // 货币类型,默认CNY + private CurrencyType currency; + // 价格,默认为0 + private float price; + // 车辆组 + private String vehicleGroup; + // 跳过的字段位 + private long skipFields; + // 预验证字段位 + private long preVerifyFields; + // 有效性金额 + private int effectivenessAmount; + // 版本号 + private int version; + // 总旅客数 + private int totalTravelerCount; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalSkipFieldType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalSkipFieldType.java new file mode 100644 index 00000000..7c491d5d --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/rental/CarRentalSkipFieldType.java @@ -0,0 +1,15 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.rental; + +public class CarRentalSkipFieldType { + public static final long PassengerList = 1; + public static final long PickUpCities = 2; + public static final long DropOffCities = 4; + public static final long PickUpBeginDate = 8; + public static final long PickUpEndDate = 16; + public static final long DropOffBeginDate = 32; + public static final long DropOffEndDate = 64; + public static final long Price = 128; + public static final long Currency = 256; + public static final long VehicleGroup = 512; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/SeatTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/SeatTypeEnum.java new file mode 100644 index 00000000..1b285b26 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/SeatTypeEnum.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +// SeatTypeEnum definition +public enum SeatTypeEnum { + YZ(201), // 硬座 + RZ(203), // 软座 + // ... other seat types with their corresponding integer values + EDSR(314); // 二等卧 + + private final int value; + + SeatTypeEnum(int value) { + this.value = value; + } + + // Getter... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainEndorsementDetail.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainEndorsementDetail.java new file mode 100644 index 00000000..e4d9236a --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainEndorsementDetail.java @@ -0,0 +1,69 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +import com.chint.interfaces.rest.ctrip.dto.approval.CurrencyType; +import com.chint.interfaces.rest.ctrip.dto.approval.PassengerDetail; + +import java.util.List; + +// TrainEndorsementDetail class definition +public class TrainEndorsementDetail { + + // 火车产品类型 + private TrainProductTypeEnum productType; + + // 订票类型列表 - 1张, 2张, 3张, 超过3张 + private List bookingTypeList; + + // 订单ID列表 + private List orderIDList; + + // 行程类型 - 单程(1) or 往返(2) + private TripTypeEnum tripType; + + // 出发日期开始 - 格式: yyyy-MM-dd + private String departDateBegin; + + // 出发日期结束 - 格式: yyyy-MM-dd + private String departDateEnd; + + // 返回日期开始 - 格式: yyyy-MM-dd + private String returnDateBegin; + + // 返回日期结束 - 格式: yyyy-MM-dd + private String returnDateEnd; + + // 乘客列表 - 无限制 + private List passengerList; + + // 到达城市代码列表 - 最多1000个 + private List arrivalCityCodes; + + // 出发城市代码列表 - 最多1000个 + private List departCityCodes; + + // 价格 - 可为负数, 默认为0 + private String price; + + // 货币类型 - 默认CNY + private CurrencyType currency; + + // 座位类型 + private List seatType; + + // 跳过的字段位 - 用于标记不包含的字段 + private long skipFields; + + // 旅客数量 - 默认为0 + private int travelerCount; + + // 预验证字段位 - 用于标记需要预验证的字段 + private long preVerifyFields; + + // 列车车次列表 - 如G, D, C, Z, T, K等 + private List trainVehicleTypeList; + + // 总旅客数量 - 用于统计 + private int totalTravelerCount; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainPreVerifyFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainPreVerifyFields.java new file mode 100644 index 00000000..84cd2e75 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainPreVerifyFields.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +// TrainPreVerifyFields bit field constants +public class TrainPreVerifyFields { + public static final long TripType = 1; + public static final long DepartDateBegin = 2; + public static final long DepartDateEnd = 4; + public static final long ReturnDateBegin = 8; + public static final long ReturnDateEnd = 16; + public static final long PassengerList = 32; + public static final long FromCities = 64; + public static final long ToCities = 128; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainProductTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainProductTypeEnum.java new file mode 100644 index 00000000..0e6e9666 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainProductTypeEnum.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +// TrainProductTypeEnum definition +public enum TrainProductTypeEnum { + Domestic(5); // 国内火车 + + private final int value; + + TrainProductTypeEnum(int value) { + this.value = value; + } + + // Getter... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainSkipFields.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainSkipFields.java new file mode 100644 index 00000000..c0ed5109 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TrainSkipFields.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +// TrainSkipFields bit field constants +public class TrainSkipFields { + public static final long TripType = 1; + public static final long DepartDateBegin = 2; + public static final long DepartDateEnd = 4; + public static final long ReturnDateBegin = 8; + public static final long ReturnDateEnd = 16; + public static final long PassengerList = 32; + public static final long FromCities = 64; + public static final long ToCities = 128; + public static final long Price = 256; + public static final long Currency = 512; + public static final long SeatType = 1024; + // ... include other fields as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TripTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TripTypeEnum.java new file mode 100644 index 00000000..6bc29c9f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/approval/train/TripTypeEnum.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.ctrip.dto.approval.train; + +public enum TripTypeEnum { + SingleTrip(3), // 国内酒店 + RoundTrip(4); // 国际酒店 + + private final int value; + + TripTypeEnum(int value) { + this.value = value; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/AuthInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/AuthInfo.java new file mode 100644 index 00000000..69619906 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/AuthInfo.java @@ -0,0 +1,20 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class AuthInfo { + + // appKey + private String appKey; + // 访问令牌 + private String accessToken; + + // Getters and setters... + + public static AuthInfo of(String appKey, String accessToken) { + return new AuthInfo(appKey, accessToken); + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequest.java new file mode 100644 index 00000000..dc4999e8 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequest.java @@ -0,0 +1,21 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +@Data +public class BookingRelatedApiRequest { + + // 语言 + private String language; + // API名称 + private String apiName; + // 认证信息 + private AuthInfo authInfo; + // 请求内容 + private ValuateBudgetRequestType requestContent; + + // Getters and setters... + public static BookingRelatedApiRequestBuilder builder() { + return new BookingRelatedApiRequestBuilder(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequestBuilder.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequestBuilder.java new file mode 100644 index 00000000..86eac4ae --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/BookingRelatedApiRequestBuilder.java @@ -0,0 +1,272 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import java.util.ArrayList; + +public class BookingRelatedApiRequestBuilder { + + private BookingRelatedApiRequest request = new BookingRelatedApiRequest(); + + public BookingRelatedApiRequestBuilder language(String language) { + request.setLanguage(language); + return this; + } + + public BookingRelatedApiRequestBuilder apiName(String apiName) { + request.setApiName(apiName); + return this; + } + + public AuthInfoBuilder authInfo() { + return new AuthInfoBuilder(this, request); + } + + public ValuateBudgetRequestTypeBuilder requestContent() { + return new ValuateBudgetRequestTypeBuilder(this, request); + } + + public BookingRelatedApiRequest build() { + return request; + } + + // Sub-builder for AuthInfo (Example, needs implementation) + public static class AuthInfoBuilder { + private final BookingRelatedApiRequestBuilder parentBuilder; + private final BookingRelatedApiRequest request; + + public AuthInfoBuilder(BookingRelatedApiRequestBuilder parentBuilder, BookingRelatedApiRequest request) { + this.parentBuilder = parentBuilder; + this.request = request; + } + + public AuthInfoBuilder details(String appKey, String accessToken) { + AuthInfo authInfo = new AuthInfo(appKey,accessToken); // Construct AuthInfo with parameters + request.setAuthInfo(authInfo); + return this; + } + + public BookingRelatedApiRequestBuilder done() { + return parentBuilder; + } + } + + // Sub-builder for ValuateBudgetRequestType + public static class ValuateBudgetRequestTypeBuilder { + private final BookingRelatedApiRequestBuilder parentBuilder; + private final BookingRelatedApiRequest request; + private ValuateBudgetRequestType requestContent = new ValuateBudgetRequestType(); + + public ValuateBudgetRequestTypeBuilder(BookingRelatedApiRequestBuilder parentBuilder, BookingRelatedApiRequest request) { + this.parentBuilder = parentBuilder; + this.request = request; + } + + public ValuationBaseInfoBuilder valuationBaseInfo() { + return new ValuationBaseInfoBuilder(this, requestContent); + } + + public ValuationProductInfoBuilder valuationProductInfo() { + return new ValuationProductInfoBuilder(this, requestContent); + } + + public BookingRelatedApiRequestBuilder done() { + request.setRequestContent(requestContent); + return parentBuilder; + } + } + + // Sub-builder for ValuationBaseInfo + public static class ValuationBaseInfoBuilder { + private final ValuateBudgetRequestTypeBuilder parentBuilder; + private final ValuateBudgetRequestType requestContent; + private ValuationBaseInfo baseInfo = new ValuationBaseInfo(); + + public ValuationBaseInfoBuilder(ValuateBudgetRequestTypeBuilder parentBuilder, ValuateBudgetRequestType requestContent) { + this.parentBuilder = parentBuilder; + this.requestContent = requestContent; + } + + public ValuationBaseInfoBuilder corpID(String corpID) { + baseInfo.setCorpID(corpID); + return this; + } + + public ValuationBaseInfoBuilder eID(String eID) { + baseInfo.setEID(eID); + return this; + } + + public ValuationBaseInfoBuilder rankName(String rankName) { + baseInfo.setRankName(rankName); + return this; + } + + public ValuateBudgetRequestTypeBuilder done() { + requestContent.setValuationBaseInfo(baseInfo); + return parentBuilder; + } + } + + // Sub-builder for ValuationProductInfo (Example, needs further implementation for FlightProductInfo, TrainProductInfo, etc.) + public static class ValuationProductInfoBuilder { + private final ValuateBudgetRequestTypeBuilder parentBuilder; + private final ValuateBudgetRequestType requestContent; + private ValuationProductInfo productInfo = new ValuationProductInfo(); + + public ValuationProductInfoBuilder(ValuateBudgetRequestTypeBuilder parentBuilder, ValuateBudgetRequestType requestContent) { + this.parentBuilder = parentBuilder; + this.requestContent = requestContent; + } + + // Method to add FlightProductInfo, TrainProductInfo, etc. + public ValuationProductInfoBuilder addFlightProductInfo(FlightProductInfo flightProductInfo) { + if (productInfo.getFlightProductInfo() == null) { + productInfo.setFlightProductInfo(new ArrayList<>()); + } + productInfo.getFlightProductInfo().add(flightProductInfo); + return this; + } + + // Similar methods for adding TrainProductInfo, etc. + + public ValuationProductInfoBuilder addTrainProductInfo(TrainProductInfo trainProductInfo) { + if (productInfo.getTrainProductInfo() == null) { + productInfo.setTrainProductInfo(new ArrayList<>()); + } + productInfo.getTrainProductInfo().add(trainProductInfo); + return this; + } + + + public ValuateBudgetRequestTypeBuilder done() { + requestContent.setValuationProductInfo(productInfo); + return parentBuilder; + } + } + + // Sub-builder for FlightProductInfo + public static class FlightProductInfoBuilder { + private final ValuationProductInfoBuilder parentBuilder; + private FlightProductInfo flightProductInfo = new FlightProductInfo(); + + public FlightProductInfoBuilder(ValuationProductInfoBuilder parentBuilder) { + this.parentBuilder = parentBuilder; + } + + public FlightProductInfoBuilder flightWay(String flightWay) { + flightProductInfo.setFlightWay(flightWay); + return this; + } + + public FlightProductInfoBuilder classType(String classType) { + flightProductInfo.setClassType(classType); + return this; + } + + public FlightProductInfoBuilder searchRouteNum(Integer searchRouteNum) { + flightProductInfo.setSearchRouteNum(searchRouteNum); + return this; + } + + public FlightProductInfoBuilder airLineCode(String airLineCode) { + flightProductInfo.setAirLineCode(airLineCode); + return this; + } + + public FlightProductInfoBuilder addRouteInfo(RouteInfo routeInfo) { + if (flightProductInfo.getRoutes() == null) { + flightProductInfo.setRoutes(new ArrayList<>()); + } + flightProductInfo.getRoutes().add(routeInfo); + return this; + } + + public ValuationProductInfoBuilder done() { + parentBuilder.addFlightProductInfo(flightProductInfo); + return parentBuilder; + } + } + + // Sub-builder for TrainProductInfo + public static class TrainProductInfoBuilder { + private final ValuationProductInfoBuilder parentBuilder; + private TrainProductInfo trainProductInfo = new TrainProductInfo(); + + public TrainProductInfoBuilder(ValuationProductInfoBuilder parentBuilder) { + this.parentBuilder = parentBuilder; + } + + public TrainProductInfoBuilder departStation(String departStation) { + trainProductInfo.setDepartStation(departStation); + return this; + } + + public TrainProductInfoBuilder arriveStation(String arriveStation) { + trainProductInfo.setArriveStation(arriveStation); + return this; + } + + public TrainProductInfoBuilder departDate(String departDate) { + trainProductInfo.setDepartDate(departDate); + return this; + } + + public TrainProductInfoBuilder trainNo(String trainNo) { + trainProductInfo.setTrainNo(trainNo); + return this; + } + + public TrainProductInfoBuilder departCityID(String departCityID) { + trainProductInfo.setDepartCityID(departCityID); + return this; + } + + public TrainProductInfoBuilder arriveCityID(String arriveCityID) { + trainProductInfo.setArriveCityID(arriveCityID); + return this; + } + + public TrainProductInfoBuilder returnNoTicket(boolean returnNoTicket) { + trainProductInfo.setReturnNoTicket(returnNoTicket); + return this; + } + + public ValuationProductInfoBuilder done() { + parentBuilder.addTrainProductInfo(trainProductInfo); + return parentBuilder; + } + } + + // Sub-builder for RouteInfo + public static class RouteInfoBuilder { + private RouteInfo routeInfo = new RouteInfo(); + + public RouteInfoBuilder arriveCityCode(String arriveCityCode) { + routeInfo.setArriveCityCode(arriveCityCode); + return this; + } + + public RouteInfoBuilder departCityCode(String departCityCode) { + routeInfo.setDepartCityCode(departCityCode); + return this; + } + + public RouteInfoBuilder departDate(String departDate) { + routeInfo.setDepartDate(departDate); + return this; + } + + public RouteInfoBuilder arriveCityID(String arriveCityID) { + routeInfo.setArriveCityID(arriveCityID); + return this; + } + + public RouteInfoBuilder departCityID(String departCityID) { + routeInfo.setDepartCityID(departCityID); + return this; + } + + public RouteInfo build() { + return routeInfo; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/FlightProductInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/FlightProductInfo.java new file mode 100644 index 00000000..f10d523a --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/FlightProductInfo.java @@ -0,0 +1,18 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class FlightProductInfo { + // 航班方式 + private String flightWay; + // 舱位类型 + private String classType; + // 航线信息 + private List routes; + + private Integer searchRouteNum; + private String airLineCode; +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/LanguagesEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/LanguagesEnum.java new file mode 100644 index 00000000..2698483d --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/LanguagesEnum.java @@ -0,0 +1,5 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +public enum LanguagesEnum { + ZH, EN +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/RouteInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/RouteInfo.java new file mode 100644 index 00000000..a9ecb554 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/RouteInfo.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +@Data +public class RouteInfo { + + // 到达城市代码 + private String arriveCityCode; + // 出发城市代码 + private String departCityCode; + // 出发日期 + private String departDate; + private String arriveCityID; + private String departCityID; + // Getters and setters... +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/TrainProductInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/TrainProductInfo.java new file mode 100644 index 00000000..57671a1f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/TrainProductInfo.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +@Data +public class TrainProductInfo { + private String departStation; + private String arriveStation; + private String departDate; //出发日期 格式: yyyy-MM-dd + private String trainNo; //车次 + private String departCityID; //出发城市id,车站和城市id配套二传一,都传优先使用车站 + private String arriveCityID; //到达城市id,车站和城市id配套二传一,都传优先使用车站 + private boolean returnNoTicket; //是否返回无票价格,默认否 +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuateBudgetRequestType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuateBudgetRequestType.java new file mode 100644 index 00000000..0e2603f8 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuateBudgetRequestType.java @@ -0,0 +1,18 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; +import org.apache.commons.codec.language.bm.Languages; + +import java.util.List; + +@Data +public class ValuateBudgetRequestType { + + // 估算基础信息 + private ValuationBaseInfo valuationBaseInfo; + // 产品信息 + private ValuationProductInfo valuationProductInfo; + + private LanguagesEnum languages; + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationBaseInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationBaseInfo.java new file mode 100644 index 00000000..3d0201f4 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationBaseInfo.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +@Data +public class ValuationBaseInfo { + + // 公司ID + private String corpID; + // 员工ID + private String eID; + // 职级名称 + private String rankName; + + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationProductInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationProductInfo.java new file mode 100644 index 00000000..11109574 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/request/ValuationProductInfo.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class ValuationProductInfo { + + // Allowable product types like "DOMESTIC_FLIGHT", "INTERNATIONAL_FLIGHT", etc. + private List flightProductInfo; + private List trainProductInfo; + // Getters and setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AirlineInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AirlineInfo.java new file mode 100644 index 00000000..2ad3af3b --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AirlineInfo.java @@ -0,0 +1,21 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class AirlineInfo { + // 航班价格类型 + private Integer priceType; + // 航空公司名称 + private String airlineName; + // 起飞时间 + private String departTime; + // 起飞机场 + private String departPort; + // 到达机场 + private String arrivalPort; + // 航班折扣 + private BigDecimal discount; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AvailableProductEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AvailableProductEnum.java new file mode 100644 index 00000000..23ee410c --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/AvailableProductEnum.java @@ -0,0 +1,5 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +public enum AvailableProductEnum { + UNKNOWN,FLIGHT,HOTEL,TRAIN +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/BookingRelatedApiResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/BookingRelatedApiResponse.java new file mode 100644 index 00000000..a1c907c8 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/BookingRelatedApiResponse.java @@ -0,0 +1,18 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import com.chint.interfaces.rest.ctrip.dto.ResponseStatus; +import lombok.Data; + +import java.util.List; + +@Data +public class BookingRelatedApiResponse { + + // 请求相关API的响应 + private ResponseStatus status; + // 数据内容 + private ValuateBudgetResponseType data; + + + // Getters and Setters... +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/FlightValuationResult.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/FlightValuationResult.java new file mode 100644 index 00000000..ea95e12e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/FlightValuationResult.java @@ -0,0 +1,29 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Data +public class FlightValuationResult { + // 航班总价格 + private BigDecimal totalPrice; + // 航班最高价格 + private BigDecimal maxPrice; + // 航班中等价格 + private BigDecimal mediumPrice; + // 航班最高舱位类别 + private String highestClass; + + private List airlineInfoList; + + // 航班结果描述 + private String resultDescription; + // 航班较低的价格 + private BigDecimal lessPrice; + // 航班更高的价格 + private BigDecimal morePrice; + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/HotelValuationResult.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/HotelValuationResult.java new file mode 100644 index 00000000..3773925e --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/HotelValuationResult.java @@ -0,0 +1,18 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class HotelValuationResult { + + // 币种 + private String currency; + // 酒店最高价格 + private BigDecimal maxPrice; + // 酒店结果描述 + private String resultDescription; + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/SeatMaxPriceInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/SeatMaxPriceInfo.java new file mode 100644 index 00000000..da2d33c9 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/SeatMaxPriceInfo.java @@ -0,0 +1,15 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class SeatMaxPriceInfo { + // 座位最高价格信息 + private String seatCode; // 座位代码 + private BigDecimal maxPrice; // 最高价格 + + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeDurationMinute.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeDurationMinute.java new file mode 100644 index 00000000..6002c79f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeDurationMinute.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +@Data +public class TrainTypeDurationMinute { + // 火车类型 + private TrainTypeEnum trainType; // 火车类型枚举 + private Float maxDurationMinutes; // 最大持续时间分钟 + private Integer minDurationMinutes; // 最小持续时间分钟 + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeEnum.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeEnum.java new file mode 100644 index 00000000..167712f5 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainTypeEnum.java @@ -0,0 +1,9 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +public enum TrainTypeEnum { + G, // 高铁 + D, // 动车 + T, // 特快 + K, // 快速 + // ... Add additional train types as necessary +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainValuationResult.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainValuationResult.java new file mode 100644 index 00000000..bdedad51 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/TrainValuationResult.java @@ -0,0 +1,22 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Data +public class TrainValuationResult { + // 估算的最高价格 + private BigDecimal maxPrice; + // 座位最高价格信息列表 + private List seatMaxPriceInfoList; + // 结果描述 + private String resultDescription; + // 火车类型持续时间分钟列表 + private List trainTypeDurationMinuteList; + // 可用产品列表 + + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResponseType.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResponseType.java new file mode 100644 index 00000000..37482d19 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResponseType.java @@ -0,0 +1,19 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import java.math.BigDecimal; +import java.util.List; + +public class ValuateBudgetResponseType { + // 估算结果 + private ValuateBudgetResult valuateBudgetResult; + // 航班估算结果 + private FlightValuationResult flightValuationResult; + // 估算的总价格 + private HotelValuationResult hotelValuationResult; + // 火车估算结果 + private TrainValuationResult trainValuationResult; + + private List availableProductList; + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResult.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResult.java new file mode 100644 index 00000000..5716d36d --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/estimate/response/ValuateBudgetResult.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.estimate.response; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class ValuateBudgetResult { + // 总价格 + private BigDecimal totalPrice; + // 最高价格 + private BigDecimal maxPrice; + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/City.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/City.java new file mode 100644 index 00000000..6462efe1 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/City.java @@ -0,0 +1,21 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class City { + + private Long id; + private String City; + private String CityEName; + private String CityName; + private String Country; + private String CountryEName; + private String CountryName; + private String JianPin; + private String Province; + private String ProvinceEName; + private String ProvinceName; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CityResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CityResponse.java new file mode 100644 index 00000000..b95933f5 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CityResponse.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import com.chint.interfaces.rest.ctrip.dto.ResponseStatus; +import com.chint.interfaces.rest.ctrip.dto.location.City; +import lombok.Data; + +import java.util.List; +@Data +public class CityResponse { + private ResponseStatus Status; + private List Data; + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/Country.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/Country.java new file mode 100644 index 00000000..0cc1021c --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/Country.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class Country { + private Long id; + private Integer Country; // 注意:在Kotlin中是Int,在Java中对应的是Integer + private String CountryEName; + private String CountryName; +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CountryResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CountryResponse.java new file mode 100644 index 00000000..c9bf113a --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/CountryResponse.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import com.chint.interfaces.rest.ctrip.dto.ResponseStatus; +import lombok.Data; + +import java.util.List; +@Data +public class CountryResponse { + private ResponseStatus Status; + private List Data; + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountry.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountry.java new file mode 100644 index 00000000..a902e141 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountry.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import com.chint.interfaces.rest.ctrip.dto.Authentification; +import lombok.Data; + +@Data +public class GetCountry { + private Authentification Auth; + private String Language; + + public GetCountry(Authentification auth, String language) { + Auth = auth; + Language = language; + } +// Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountryCityExtend.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountryCityExtend.java new file mode 100644 index 00000000..cca54cc3 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/location/GetCountryCityExtend.java @@ -0,0 +1,19 @@ +package com.chint.interfaces.rest.ctrip.dto.location; + +import com.chint.interfaces.rest.ctrip.dto.Authentification; +import lombok.Data; + +@Data +public class GetCountryCityExtend { + private Authentification Auth; + private String Language; + private Integer CountryId; + + public GetCountryCityExtend(Authentification auth, String language, Integer countryId) { + Auth = auth; + Language = language; + CountryId = countryId; + } + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarOrderInfoEntity.java new file mode 100644 index 00000000..cd06a3de --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class CarOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarQuickOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarQuickOrderInfoEntity.java new file mode 100644 index 00000000..9ce0bf36 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/CarQuickOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class CarQuickOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomCharterCarOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomCharterCarOrderInfoEntity.java new file mode 100644 index 00000000..e59200c0 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomCharterCarOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class DomCharterCarOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomPickUpCarOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomPickUpCarOrderInfoEntity.java new file mode 100644 index 00000000..63eba79f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/DomPickUpCarOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class DomPickUpCarOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/FlightOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/FlightOrderInfoEntity.java new file mode 100644 index 00000000..94169f44 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/FlightOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class FlightOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/HotelOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/HotelOrderInfoEntity.java new file mode 100644 index 00000000..65c01773 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/HotelOrderInfoEntity.java @@ -0,0 +1,7 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +import lombok.Data; + +@Data +public class HotelOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/IntlTrainOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/IntlTrainOrderInfoEntity.java new file mode 100644 index 00000000..f60e1204 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/IntlTrainOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class IntlTrainOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/ItineraryEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/ItineraryEntity.java new file mode 100644 index 00000000..1abb9ec0 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/ItineraryEntity.java @@ -0,0 +1,30 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +import lombok.Data; + +import java.util.List; + +@Data +public class ItineraryEntity { + + // 行程单号 + private String journeyNO; // 行程单号 + // 酒店订单信息列表 + private List hotelOrderInfoList; // 酒店订单信息列表 + // 航班订单信息列表 + private List flightOrderInfoList; // 航班订单信息列表 + // 火车票订单信息列表 + private List trainOrderInfoList; // 火车票订单信息列表 + // 租车订单信息列表 + private List carOrderInfoList; // 租车订单信息列表 + // 快捷租车订单信息列表 + private List carQuickOrderInfoList; // 快捷租车订单信息列表 + // 接送机租车订单信息列表 + private List domPickUpCarOrderInfoList; // 接送机租车订单信息列表 + // 包车租车订单信息列表 + private List domCharterCarOrderInfoList; // 包车租车订单信息列表 + // 国际火车票订单信息列表 + private List intlTrainOrderInfoList; // 国际火车票订单信息列表 + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderRequest.java new file mode 100644 index 00000000..5de078d3 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderRequest.java @@ -0,0 +1,38 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +import com.chint.interfaces.rest.ctrip.dto.Authentication; +import lombok.Data; + +@Data +public class SearchOrderRequest { + + // 认证信息,ticket用 + private Authentication auth; + // 语言版本 + private String language; // zh-CN 表示中文版; en-US 英文版; + // 行程单号 + private String journeyNo; + // 订单号 + private String orderId; + // 员工编号 + private String eID; + // 用户编号 + private String uID; + // 开始日期 + private String dateFrom; // 查询开始日期,日期格式为:yyyy-MM-dd + // 结束日期 + private String dateTo; // 查询结束日期,日期格式为:yyyy-MM-dd + // 查询类型 + private String searchType; // 查询类型,默认值为1 + // 版本号 + private String version; // 版本号,默认为1.0 + // 国际机票查询类型扩展 + private String fltSearchTypeExtend; // 国际机票查询类型扩展,用于控制DateFrom, DateTo收敛。比如填写“RefundTime” 或 “RebookedTime” 时使用不同的查询逻辑 + // 火车票查询类型扩展 + private String trainSearchTypeExtend; // 火车票查询类型扩展 + // 其他查询类型扩展 + private String htlSearchTypeExtend; // 酒店查询类型扩展 + private String carSearchTypeExtend; // 租车查询类型扩展 + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderResponse.java new file mode 100644 index 00000000..65a6c07b --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/SearchOrderResponse.java @@ -0,0 +1,17 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +import com.chint.interfaces.rest.ctrip.dto.ResponseStatus; +import lombok.Data; + +import java.util.List; + +@Data +public class SearchOrderResponse { + + // 响应状态 + private ResponseStatus status; // 响应状态 + // 行程单列表 + private List itineraryList; // 行程单列表 + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/TrainOrderInfoEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/TrainOrderInfoEntity.java new file mode 100644 index 00000000..ff8cdfee --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/search/TrainOrderInfoEntity.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ctrip.dto.search; + +public class TrainOrderInfoEntity { +} diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketParam.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketParam.java new file mode 100644 index 00000000..90ecb1d7 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketParam.java @@ -0,0 +1,16 @@ +package com.chint.interfaces.rest.ctrip.dto.ticket; + +import lombok.Data; + +@Data +public class TicketParam { + private String appKey; + private String appSecurity; + + public TicketParam(String appKey, String appSecurity) { + this.appKey = appKey; + this.appSecurity = appSecurity; + } + + // Getters and setters (or you can make the fields public) +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketResponse.java new file mode 100644 index 00000000..ccf6b952 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/ticket/TicketResponse.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.ctrip.dto.ticket; + +import com.chint.interfaces.rest.ctrip.dto.ResponseStatus; +import lombok.Data; + +@Data +public class TicketResponse { + private ResponseStatus Status; + private String Ticket; + + +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenRequest.java new file mode 100644 index 00000000..27ca1dc5 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenRequest.java @@ -0,0 +1,35 @@ +package com.chint.interfaces.rest.ctrip.dto.token; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class GetUnionAccessTokenRequest { + + // 应用标识 + private String appKey; + // 应用安全码 + private String appSecurity; + // 访问类型 + private Integer accessType; // token类型:1-获取访问,2-刷新访问;访问类型一般有1、用户级别访问权限获取;2、应用级别访问权限获取 + // 扩展字段 + private String extend; // 扩展字段 + // ip地址 + private String ip; // ip + // 语言 + private String language; // 语言 + // 版本号 + private String version; // 版本号 + + private GetUnionAccessTokenRequest(String appKey, String appSecurity, Integer accessType) { + this.appKey = appKey; + this.appSecurity = appSecurity; + this.accessType = accessType; + } + + // Getters and Setters... + public static GetUnionAccessTokenRequest of(String appKey, String appSecurity, Integer accessType) { + return new GetUnionAccessTokenRequest(appKey, appSecurity, accessType); + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenResponse.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenResponse.java new file mode 100644 index 00000000..b0411509 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/token/GetUnionAccessTokenResponse.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.token; + +import lombok.Data; + +@Data +public class GetUnionAccessTokenResponse { + + // 访问令牌 + private String accessToken; // 令牌 + // 访问时间 + private Integer accessTime; // 令牌有效时间 + + // Getters and Setters... +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationEntity.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationEntity.java new file mode 100644 index 00000000..d7e9b857 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationEntity.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.ctrip.dto.user; + +import lombok.Data; + +@Data +public class AuthenticationEntity { + private String EmployeeID; + private String Name; + private String Valid; //在职情况 A-在职,业务操作为新建卡或者更新卡;I-离职,业务操作为关卡。 + private String RankName; // 职级名称(中文)注:职级的中文名跟英文名,只能传递其中一个。(如果需要使用该字段,需提前联系实施经理在携程后台进行配置) + private String SubAccountName; //子账户,即确定该人员信息落在那个结算主体中,用于确定后续订单费用归属 +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationInfo.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationInfo.java new file mode 100644 index 00000000..e5ebe136 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationInfo.java @@ -0,0 +1,11 @@ +package com.chint.interfaces.rest.ctrip.dto.user; + +import lombok.Data; + +@Data +public class AuthenticationInfo { + private String Sequence; + private AuthenticationEntity Authentication; + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationListRequest.java b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationListRequest.java new file mode 100644 index 00000000..e8b41380 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ctrip/dto/user/AuthenticationListRequest.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.ctrip.dto.user; + +import lombok.Data; + +import java.util.List; +@Data +public class AuthenticationListRequest { + private String Appkey; + private String Ticket; + private String CorporationID; + private List AuthenticationInfoList; + + // Constructors, getters, and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/LYPostRequest.java b/src/main/java/com/chint/interfaces/rest/ly/LYPostRequest.java new file mode 100644 index 00000000..19150e05 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/LYPostRequest.java @@ -0,0 +1,53 @@ +package com.chint.interfaces.rest.ly; + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ly.dto.LYBaseRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + +import static com.chint.infrastructure.constant.Constant.L_Y_SECRET; + +@Service +public class LYPostRequest { + + @Autowired + private PostRequest postRequest; + + @Autowired + private LYTokenRequest lyTokenRequest; + + private String mySecret = L_Y_SECRET; + + public T post(String url, LYBaseRequest jsonRequest, Class responseType) { + String token = lyTokenRequest.loadToken(); + jsonRequest.setRandom(UUID.randomUUID().toString()); + jsonRequest.setTimestamp(String.valueOf(System.currentTimeMillis())); + jsonRequest.setAccessToken(token); + String postDataMd5 = md5(postRequest.gson().toJson(jsonRequest)); + String finallySign = md5(postDataMd5 + mySecret); + jsonRequest.setSign(finallySign); + return postRequest.post(url, jsonRequest, responseType); + } + + public static String md5(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(input.getBytes()); + StringBuilder hexString = new StringBuilder(); + for (byte b : messageDigest) { + String hex = Integer.toHexString(0xFF & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString().toLowerCase(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ly/LYTokenRequest.java b/src/main/java/com/chint/interfaces/rest/ly/LYTokenRequest.java new file mode 100644 index 00000000..50d8a2c6 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/LYTokenRequest.java @@ -0,0 +1,33 @@ +package com.chint.interfaces.rest.ly; + + +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ly.dto.token.TokenParam; +import com.chint.interfaces.rest.ly.dto.token.TokenRequest; +import com.chint.interfaces.rest.ly.dto.token.TokenResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.UUID; + +import static com.chint.infrastructure.constant.Constant.*; + +@Component +public class LYTokenRequest { + + private String tokenUrl = L_Y_BASE_URL + L_Y_TOKEN_PATH; + + @Autowired + private PostRequest postRequest; + + public String loadToken() { + TokenParam tokenParam = new TokenParam(L_Y_ACCOUNT, L_Y_PASSWORD, ""); + TokenRequest tokenRequest = new TokenRequest(); + tokenRequest.setRandom(UUID.randomUUID().toString()); + tokenRequest.setTimestamp(String.valueOf(System.currentTimeMillis())); + tokenRequest.setParam(tokenParam); + TokenResponse post = postRequest.post(tokenUrl, tokenRequest, TokenResponse.class); + return post.getData().getAccessToken(); + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ly/LYUserRequest.java b/src/main/java/com/chint/interfaces/rest/ly/LYUserRequest.java new file mode 100644 index 00000000..741913ea --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/LYUserRequest.java @@ -0,0 +1,73 @@ +package com.chint.interfaces.rest.ly; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.ly.dto.user.EmployeeRequest; +import com.chint.interfaces.rest.ly.dto.user.EmployeeEntity; +import com.chint.interfaces.rest.user.UserHttpRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.chint.interfaces.rest.ly.dto.user.UserResponse; +import java.util.UUID; + +import static com.chint.infrastructure.constant.Constant.L_Y_BASE_URL; +import static com.chint.infrastructure.constant.Constant.L_Y_USER_PATH; + +@Service +public class LYUserRequest { + + @Autowired + private LYPostRequest postRequest; + + @Autowired + private LYTokenRequest tokenRequest; + + @Autowired + private UserHttpRequest userHttpRequest; + + private String userUrl = L_Y_BASE_URL + L_Y_USER_PATH; + + public boolean saveCurrentUser() { + User currentUser = BaseContext.getCurrentUser(); + userHttpRequest.loadUserInfo(currentUser); + EmployeeEntity employeeEntity = user2LYEmployee(currentUser); + EmployeeRequest employeeData = new EmployeeRequest(); + employeeData.setParam(employeeEntity); + UserResponse post = postRequest.post(userUrl, employeeData, UserResponse.class); + return post.isSuccess(); + } + + private Integer translateGender(String gender) { + switch (gender) { + case "M": + return 1; + case "F": + return 0; + default: + throw new RuntimeException("未知性别"); + } + } + + private Integer translateWorkStatus(String workStatus) { + switch (workStatus) { + case "A": + return 1; + case "T": + return 0; + default: + return 0; + } + } + + private EmployeeEntity user2LYEmployee(User user){ + EmployeeEntity employeeEntity = new EmployeeEntity(); + employeeEntity.setOutEmployeeId(String.valueOf(user.employeeNo)); + employeeEntity.setSurName(user.getName()); + employeeEntity.setGender(translateGender(user.getGender())); + employeeEntity.setWorkingState(translateWorkStatus(user.getWorkStatus())); + employeeEntity.setReservationType(0); + employeeEntity.setPositionLevelName(user.getRankCode()); + return employeeEntity; + } +} diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/LYBaseRequest.java b/src/main/java/com/chint/interfaces/rest/ly/dto/LYBaseRequest.java new file mode 100644 index 00000000..d0b0d3c2 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/LYBaseRequest.java @@ -0,0 +1,11 @@ +package com.chint.interfaces.rest.ly.dto; + +import lombok.Data; + +@Data +public class LYBaseRequest { + private String accessToken; + private String random; + private String timestamp; + private String sign; +} diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenParam.java b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenParam.java new file mode 100644 index 00000000..56b477f4 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenParam.java @@ -0,0 +1,42 @@ +package com.chint.interfaces.rest.ly.dto.token; + +import lombok.Data; + +@Data +public class TokenParam { + private String account; + private String password; + private String tokenType; + + // 构造函数 + public TokenParam(String account, String password, String tokenType) { + this.account = account; + this.password = password; + this.tokenType = tokenType; + } + + // Getter 和 Setter 方法 + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getTokenType() { + return tokenType; + } + + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenRequest.java b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenRequest.java new file mode 100644 index 00000000..f03a40b5 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenRequest.java @@ -0,0 +1,13 @@ +package com.chint.interfaces.rest.ly.dto.token; + +import com.chint.interfaces.rest.ly.dto.LYBaseRequest; +import lombok.Data; + +@Data +public class TokenRequest { + private String random; + + private String timestamp; + + private TokenParam param; +} diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenResponse.java b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenResponse.java new file mode 100644 index 00000000..e714508a --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/token/TokenResponse.java @@ -0,0 +1,84 @@ +package com.chint.interfaces.rest.ly.dto.token; + +import lombok.Data; + +@Data +public class TokenResponse { + private boolean success; + private String errorCode; + private String errorMessage; + private ResponseData data; + private int errorType; + + // 内部类,用于表示响应中的"data"字段 + public static class ResponseData { + private String accessToken; + private long expiryTime; + + // Getter 和 Setter 方法 + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public long getExpiryTime() { + return expiryTime; + } + + public void setExpiryTime(long expiryTime) { + this.expiryTime = expiryTime; + } + } + + // 构造函数、Getter 和 Setter 方法 + public TokenResponse(boolean success, String errorCode, String errorMessage, ResponseData data, int errorType) { + this.success = success; + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.data = data; + this.errorType = errorType; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public ResponseData getData() { + return data; + } + + public void setData(ResponseData data) { + this.data = data; + } + + public int getErrorType() { + return errorType; + } + + public void setErrorType(int errorType) { + this.errorType = errorType; + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/CostCenter.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/CostCenter.java new file mode 100644 index 00000000..cdb4ad73 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/CostCenter.java @@ -0,0 +1,10 @@ +package com.chint.interfaces.rest.ly.dto.user; + +public class CostCenter { + private String costCenterName; + private String costCenterCode; + private String costCenterTypeName; + private String costCenterTypeCode; + private boolean isDefault; + // Getters and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeEntity.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeEntity.java new file mode 100644 index 00000000..7399dce9 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeEntity.java @@ -0,0 +1,36 @@ +package com.chint.interfaces.rest.ly.dto.user; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class EmployeeEntity { + private String outEmployeeId; + private int employeeType; + private String surName; + private String givenName; + private String enSurName; + private String enGivenName; + private int gender; + private String mobile; + private String email; + private String idCard; + private int reservationType; + private String positionName; + private String positionLevelName; + private String departName; + private int workingState; + private String birthday; + private String credentialExpireDate; + private int credentialType; + private int addTravellerAllowed; + private String employeeCode; + private String costCenter; + private List preTravelPolicyList; + private Map remarks; + private String baseCity; + + // Getters and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeRequest.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeRequest.java new file mode 100644 index 00000000..a793f4c3 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/EmployeeRequest.java @@ -0,0 +1,15 @@ +package com.chint.interfaces.rest.ly.dto.user; + +import com.chint.interfaces.rest.ly.dto.LYBaseRequest; +import lombok.Data; + +import java.util.List; + +@Data +public class EmployeeRequest extends LYBaseRequest { + private boolean isEncrypt; + private EmployeeEntity param; + private List costCenterList; + + // Getters and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/PreTravelPolicy.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/PreTravelPolicy.java new file mode 100644 index 00000000..4700bd91 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/PreTravelPolicy.java @@ -0,0 +1,8 @@ +package com.chint.interfaces.rest.ly.dto.user; + +public class PreTravelPolicy { + private String policyCode; + private int productTypeId; + + // Getters and setters +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserResponse.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserResponse.java new file mode 100644 index 00000000..5f2816e1 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserResponse.java @@ -0,0 +1,68 @@ +package com.chint.interfaces.rest.ly.dto.user; + +import lombok.Data; + +@Data +public class UserResponse { + private boolean success; + private String errorCode; + private String errorMessage; + private Data data; + private int errorType; + + @lombok.Data + public static class Data { + private String employeeId; + + // Getter and Setter methods for employeeId + public String getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(String employeeId) { + this.employeeId = employeeId; + } + } + + // Getter and Setter methods for all other fields + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public Data getData() { + return data; + } + + public void setData(Data data) { + this.data = data; + } + + public int getErrorType() { + return errorType; + } + + public void setErrorType(int errorType) { + this.errorType = errorType; + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserSave.java b/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserSave.java new file mode 100644 index 00000000..5d2d9445 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/ly/dto/user/UserSave.java @@ -0,0 +1,4 @@ +package com.chint.interfaces.rest.ly.dto.user; + +public class UserSave { +} diff --git a/src/main/java/com/chint/interfaces/rest/user/UserHttpRequest.java b/src/main/java/com/chint/interfaces/rest/user/UserHttpRequest.java new file mode 100644 index 00000000..9566c07f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/UserHttpRequest.java @@ -0,0 +1,7 @@ +package com.chint.interfaces.rest.user; + +import com.chint.domain.aggregates.user.User; + +public interface UserHttpRequest { + User loadUserInfo(User user); +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/UserHttpRequestImpl.java b/src/main/java/com/chint/interfaces/rest/user/UserHttpRequestImpl.java new file mode 100644 index 00000000..b03456fb --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/UserHttpRequestImpl.java @@ -0,0 +1,101 @@ +package com.chint.interfaces.rest.user; + +import com.chint.dc.api.DataCenterResult; +import com.chint.dc.api.dto.DataCenterOption; +import com.chint.dc.api.service.DataCenterService; +import com.chint.domain.aggregates.user.User; +import com.chint.interfaces.rest.base.PostRequest; +import com.chint.interfaces.rest.user.dto.*; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.List; + +import static com.chint.infrastructure.constant.Constant.*; + +@Service +public class UserHttpRequestImpl implements UserHttpRequest { + + + private final String asSkUrl = AK_BASE_URL + GET_AK_URL + "?systemId=" + SYSTEM_ID; + private final String userUrl = OPENAI_BASE_URL + USER_DATA_PATH; + private final String travelRankUrl = TRAVEL_RANK_BASE_URL + TRAVEL_RANK_PATH; + + @Autowired + private PostRequest postRequest; + + @Override + public User loadUserInfo(User user) { + return this.loadSFAndRank(user); + } + + private User loadSFAndRank(User user) { + List loadSFInfo = loadSFInfo(user); + String custManaLevel = loadSFInfo.get(0).getCust_manaLevel(); + String level = custManaLevel != null ? custManaLevel : loadSFInfo.get(0).getCust_profLevel(); + if (level.contains("R")) { + level = level.substring(0, level.length() - 3) + "M0"; + } + TravelRankDTO loadTravelRank = loadTravelRank(new TravelRankParam(level)); + user.rankCode = loadTravelRank.getLEVEL_MAPPING_CODE(); + return user; + } + + private AccessKeyDTO akSkLoad() { + HttpClient client = HttpClients.createDefault(); + HttpGet getMethod = new HttpGet(asSkUrl); + getMethod.setHeader("Content-Type", "application/json"); + try { + var response = client.execute(getMethod); + var responseBody = EntityUtils.toString(response.getEntity(), "UTF-8"); + var gson = new Gson(); + return gson.fromJson(responseBody, AccessKeyDTO.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private List loadSFInfo(User user) { + Gson gson = new Gson(); + AccessKeyDTO akSkLoad = akSkLoad(); + DataCenterOption option = new DataCenterOption(); + option.setSk(akSkLoad.sk); + option.setAk(akSkLoad.ak); + option.setUrl(OPENAI_BASE_URL); + DataCenterService dataCenterService = new DataCenterService(option); + LinkedHashMap map = new LinkedHashMap(); + map.put("LoginUsername", user.employeeNo.toString()); + map.put("start", 0); + map.put("pageSize", 1); + DataCenterResult result = dataCenterService.post(USER_DATA_PATH, map); + Type type = new TypeToken>() { + }.getType(); + if (result.getData() != null) { + List fromJson = gson.fromJson(result.getData().toString(), type); + UserDataDTO userDataDTO = fromJson.get(0); + user.setCompanyCode(userDataDTO.getCompany()); + user.setWorkStatus(userDataDTO.getStatus()); + user.setGender(userDataDTO.getGender()); + return fromJson; + } else { + throw new RuntimeException("用户数据不存在"); + } + } + + private TravelRankDTO loadTravelRank(TravelRankParam travelRankParam) { + TravelRankResponseDTO travelRankResponseDTO = postRequest.post(travelRankUrl, travelRankParam, TravelRankResponseDTO.class); + try { + return travelRankResponseDTO.datas.get(0); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/dto/AccessKeyDTO.java b/src/main/java/com/chint/interfaces/rest/user/dto/AccessKeyDTO.java new file mode 100644 index 00000000..9443fcde --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/dto/AccessKeyDTO.java @@ -0,0 +1,8 @@ +package com.chint.interfaces.rest.user.dto; + +public class AccessKeyDTO { + public String ak; + public String sk; + public String expire; + // Constructor, getters, and setters as needed +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankDTO.java b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankDTO.java new file mode 100644 index 00000000..faa15c2f --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankDTO.java @@ -0,0 +1,12 @@ +package com.chint.interfaces.rest.user.dto; + +import lombok.Data; + +@Data +public class TravelRankDTO { + public String RANK_MAPPING_NAME; + public String LEVEL_MAPPING_CODE; + public String RANK_MAPPING_CODE; + public String LEVEL_MAPPING_NAME; + // Constructor, getters, and setters as needed +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankParam.java b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankParam.java new file mode 100644 index 00000000..85995093 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankParam.java @@ -0,0 +1,14 @@ +package com.chint.interfaces.rest.user.dto; + + +import lombok.Data; + +@Data +public class TravelRankParam { + public String rankCode; + // Constructor, getters, and setters as needed + + public TravelRankParam(String rankCode) { + this.rankCode = rankCode; + } +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankResponseDTO.java b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankResponseDTO.java new file mode 100644 index 00000000..b884e001 --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/dto/TravelRankResponseDTO.java @@ -0,0 +1,10 @@ +package com.chint.interfaces.rest.user.dto; + +import java.util.List; + +public class TravelRankResponseDTO { + public int total; + public boolean success; + public List datas; + // Constructor, getters, and setters as needed +} \ No newline at end of file diff --git a/src/main/java/com/chint/interfaces/rest/user/dto/UserDataDTO.java b/src/main/java/com/chint/interfaces/rest/user/dto/UserDataDTO.java new file mode 100644 index 00000000..ca7b100b --- /dev/null +++ b/src/main/java/com/chint/interfaces/rest/user/dto/UserDataDTO.java @@ -0,0 +1,148 @@ +package com.chint.interfaces.rest.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserDataDTO { + private String userId; + private String personIdExternal; + private String LoginUsername; + private String uname; + private String adcode; + private String gender; + private String gender_cn; + private String mobilePhone; + private String email; + private String position; + private String position_cn; + private String cust_manaLevel; + private String cust_manaLevelF; + private String cust_profLevel; + private String cust_techLevel; + private String cust_qualityLevel; + private String nationalId; + private String status; + private String status_cn; + private String managerId; + private String manageSfNum; + private String managerName; + private String company; + private String company_cn; + private String unit1; + private String unit2; + private String unit3; + private String unit4; + private String unit5; + private String unit1_cn; + private String unit2_cn; + private String unit3_cn; + private String unit4_cn; + private String unit5_cn; + private String lastModifiedDateTime; + private String SFModifiedDateTime; + private String okToRehire; + private String leaveReason; + private String joinCompanyDate; + private String joinJtDate; + private String firstDateWorked; + private String dateOfBirth; + private String transDate; + private String lzDate; + private String kqPlace; + private String kqPlaceCN; + private String documentTitle; + private String employeeType; + private String employeeTypeCN; + private String cust_type; + private String custtypeCN; + private String custCategory; + private String custCategoryCN; + private String custSubCategory; + private String custSubCategoryCN; + private String employeeClass; + private String employeeClassCN; + private String customString26; + private String degree_cn; + private String cust_FomatTypeCN; + private String cust_EducationTypeCN; + private String cust_schoolAddressCN; + private String cust_major; + private String cust_school; + private String cust_endDate; + private String cust_degree; + private String cust_degreeCN; + private String customString12; + private String workHour; + private String customString31; + private String customString31_CN; + private String customString32; + private String customString32_CN; + private String customString33; + private String customString33_CN; + private String nation; + private String nativePlace; + private String politicalType; + private String politicalType_CN; + private String maritalStatus; + private String maritalStatus_CN; + private String hKType; + private String hKType_CN; + private String nationality; + private String nationality_CN; + private String customString17; + private String hrbpId; + private String hrbpName; + private String costCenter; + private String employmentType; + private String employmentTypeCN; + private String customString23; + private String customString23CN; + private String customString24; + private String customString24CN; + private String customString25; + private String customString25CN; + private String nationalCardType; + private Integer childCount; + private String customDouble1; + private String customDouble2; + private Integer customLong1; + private String customDate2; + private String jobCode; + private String jobCodeCN; + private String customString34; + private String customString34CN; + private String customString11; + private String customString11CN; + private String projectmanager; + private String documentNumber; + private String contractCustomString6; + private String contractCustomDate2; + private String contractCustomDate3; + private String cust_issueDate; + private String cust_expirationDate; + private String contractCustomString2; + private String contractCustomString1; + private String contractCustomString4; + private String contractCustomString5; + private String contractCustomString3; + private String selfinfoCustomString7; + private String cust_documentType; + private String cust_documentTypeCN; + private String firstName; + private String lastName; + private String cust_position_description; + private String cust_position_descriptionCN; + private String positionStartDate; + private String enuname; + private String urgentRelationName; + private String urgentRelationPhone; + private String urgentRelationShip; + private String urgentRelationShipCN; + private String customString35; + private String customString35CN; + private String pinyin; +} \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 00000000..379524b8 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,11 @@ +server: + port: 8081 + +chint: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + host: localhost + port: 3306 + database: itinerary_booking + username: root + password: 123456 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..7db06668 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,12 @@ +server: + port: 8080 + +chint: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + host: localhost + port: 3306 + database: itinerary_booking + username: root + password: 123456 + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 00000000..25bc92fb --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + profiles: + active: dev + datasource: + driver-class-name: ${chint.datasource.driver-class-name} + url: jdbc:mysql://${chint.datasource.host}:${chint.datasource.port}/${chint.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true + username: ${chint.datasource.username} + password: ${chint.datasource.password} + diff --git a/src/test/java/com/chint/CTripTest.java b/src/test/java/com/chint/CTripTest.java new file mode 100644 index 00000000..ac0fb4dc --- /dev/null +++ b/src/test/java/com/chint/CTripTest.java @@ -0,0 +1,38 @@ +package com.chint; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.ctrip.CTripLocationHttpRequest; +import com.chint.interfaces.rest.ctrip.CTripUserSaveRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class CTripTest { + + @Autowired + private CTripLocationHttpRequest cTripLocationHttpRequest; + + @Autowired + private CTripUserSaveRequest cTripUserSaveRequest; + + private User user = new User(1L, 230615020L, 1, "卢麟哲", "1033719135@qq.com", "15857193365"); + + @Test + void locationCountry() { + System.out.println(cTripLocationHttpRequest.syncCountry()); + } + + @Test + void locationCity() { + System.out.println(cTripLocationHttpRequest.syncCity()); + } + + @Test + void SaveCorpCustInfoList() { + BaseContext.setCurrentUser(user); + cTripUserSaveRequest.saveUserToCTrip(); + } + +} diff --git a/src/test/java/com/chint/LTTest.java b/src/test/java/com/chint/LTTest.java new file mode 100644 index 00000000..5f426dca --- /dev/null +++ b/src/test/java/com/chint/LTTest.java @@ -0,0 +1,34 @@ +package com.chint; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.ly.LYTokenRequest; +import com.chint.interfaces.rest.ly.LYUserRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class LTTest { + + @Autowired + private LYTokenRequest lyTokenRequest; + + + @Autowired + private LYUserRequest lyUserRequest; + + private User user = new User(1L, 230615020L, 1, "卢麟哲", "1033719135@qq.com", "15857193365"); + + @Test + void loadToken(){ + System.out.println(lyTokenRequest.loadToken()); + } + + @Test + void saveCurrentUser2Ly(){ + BaseContext.setCurrentUser(user); + System.out.println(lyUserRequest.saveCurrentUser()); + } + +} diff --git a/src/test/java/com/chint/RouteApplicationTests.java b/src/test/java/com/chint/RouteApplicationTests.java new file mode 100644 index 00000000..c79bbeb5 --- /dev/null +++ b/src/test/java/com/chint/RouteApplicationTests.java @@ -0,0 +1,25 @@ +package com.chint; + +import com.chint.domain.aggregates.user.User; +import com.chint.infrastructure.util.BaseContext; +import com.chint.interfaces.rest.user.UserHttpRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RouteApplicationTests { + + @Autowired + private UserHttpRequest userHttpRequest; + + private User user = new User(1L, 230615020L, 1, "卢麟哲", "1033719135@qq.com", "15857193365"); + + + @Test + void contextLoads() { + + userHttpRequest.loadUserInfo(user); + } + +}