Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Develop #113

Merged
merged 13 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ public ResponseDto<MypageResponse> bringMember(@AuthenticationPrincipal Principa

@PreAuthorize(HAS_ROLE_USER)
@PatchMapping("/mypage")
public ResponseDto<MypageUpdateResponse> updateMember(@RequestBody @Valid MypageUpdateRequest mypageUpdateRequest) {
MypageUpdateResponse mypageUpdateResponse = memberService.updateMemberProfile(mypageUpdateRequest);
public ResponseDto<MypageUpdateResponse> updateMember(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestBody @Valid MypageUpdateRequest mypageUpdateRequest
) {
MypageUpdateResponse mypageUpdateResponse = memberService.updateMemberProfile(
principalDetails,
mypageUpdateRequest
);

return new ResponseDto<>(HttpStatus.OK.value(), mypageUpdateResponse);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
package ybe.mini.travelserver.domain.member.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import ybe.mini.travelserver.domain.member.entity.Member;

import java.io.Serializable;

@JsonIgnoreProperties(ignoreUnknown = true)
public record MypageDeleteRequest(
@Email
String email,
@NotBlank
String password
String email
) implements Serializable {
public Member toEntity() {
return Member.builder()
.email(email)
.password(password)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package ybe.mini.travelserver.domain.member.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import ybe.mini.travelserver.domain.member.entity.Member;
Expand All @@ -14,12 +12,12 @@ public record MypageDeleteResponse(
@Email
String email,
@NotBlank
String password
String name
) implements Serializable {
public static MypageDeleteResponse fromEntity(Member member) {
return new MypageDeleteResponse(
member.getEmail(),
member.getPassword()
member.getName()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
package ybe.mini.travelserver.domain.member.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import ybe.mini.travelserver.domain.member.entity.Member;

import java.io.Serializable;

@JsonIgnoreProperties(ignoreUnknown = true)
public record MypageUpdateRequest(
@Email
String email,
@NotBlank
String password,
@NotBlank
String name
) implements Serializable {
public Member toEntity() {
return Member.builder()
.email(email)
.password(password)
.name(name)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ybe.mini.travelserver.domain.member.exception;

public class CanNotControlOtherMembersData extends RuntimeException{
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
@AllArgsConstructor
public enum MemberErrorMessage implements ErrorMessage {
MEMBER_ALREADY_EXIST(BAD_REQUEST, "회원이 이미 있습니다"),
MEMBER_NOT_FOUND(BAD_REQUEST, "없는 회원입니다");
MEMBER_NOT_FOUND(BAD_REQUEST, "없는 회원입니다"),
CAN_NOT_CONTROL_OTHER_MEMBERS_DATA(BAD_REQUEST, "다른 회원의 정보를 제어할 수 없습니다");

private final HttpStatus status;
private final String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import org.springframework.web.bind.annotation.RestControllerAdvice;
import ybe.mini.travelserver.global.exception.ProblemDetailCreator;

import static ybe.mini.travelserver.domain.member.exception.MemberErrorMessage.MEMBER_ALREADY_EXIST;
import static ybe.mini.travelserver.domain.member.exception.MemberErrorMessage.MEMBER_NOT_FOUND;
import static ybe.mini.travelserver.domain.member.exception.MemberErrorMessage.*;

@RestControllerAdvice
public class MemberExceptionHandler extends ProblemDetailCreator<MemberErrorMessage> {
Expand All @@ -24,4 +23,10 @@ public ProblemDetail handleMemberAlreadyExistException(HttpServletRequest reques
public ProblemDetail handleMemberNotFoundException(HttpServletRequest request) {
return createProblemDetail(MEMBER_NOT_FOUND, request);
}

@ExceptionHandler(CanNotControlOtherMembersData.class)
public ProblemDetail handleCanNotUpdateWithOtherValidTokens(HttpServletRequest request) {
return createProblemDetail(CAN_NOT_CONTROL_OTHER_MEMBERS_DATA, request);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.transaction.annotation.Transactional;
import ybe.mini.travelserver.domain.member.dto.*;
import ybe.mini.travelserver.domain.member.entity.Member;
import ybe.mini.travelserver.domain.member.exception.CanNotControlOtherMembersData;
import ybe.mini.travelserver.domain.member.exception.MemberAlreadyExistException;
import ybe.mini.travelserver.domain.member.exception.MemberNotFoundException;
import ybe.mini.travelserver.domain.member.repository.MemberRepository;
Expand Down Expand Up @@ -81,13 +82,16 @@ public MypageResponse getMemberProfile(PrincipalDetails principalDetails) {


@Transactional
public MypageUpdateResponse updateMemberProfile(MypageUpdateRequest mypageUpdateRequest) {
Member existingMember = memberRepository.findByEmail(mypageUpdateRequest.email())
public MypageUpdateResponse updateMemberProfile(
PrincipalDetails principalDetails,
MypageUpdateRequest mypageUpdateRequest
) {
Member existingMember = memberRepository.findByEmail(principalDetails.getEmail())
.orElseThrow(MemberNotFoundException::new);

return MypageUpdateResponse.fromEntity(
existingMember.updateProfile(
mypageUpdateRequest.email(),
principalDetails.getEmail(),
passwordEncoder.encode(mypageUpdateRequest.password()),
mypageUpdateRequest.name()
)
Expand All @@ -100,11 +104,11 @@ public MypageDeleteResponse deleteMemberProfile(
PrincipalDetails principalDetails,
MypageDeleteRequest mypageDeleteRequest
) {
if (!principalDetails.getUsername().equals(mypageDeleteRequest.email())) {
throw new MemberNotFoundException();
if (!principalDetails.getEmail().equals(mypageDeleteRequest.email())) {
throw new CanNotControlOtherMembersData();
}

Member existingMember = memberRepository.findByEmail(mypageDeleteRequest.email())
Member existingMember = memberRepository.findByEmail(principalDetails.getEmail())
.orElseThrow(MemberNotFoundException::new);

memberRepository.delete(existingMember);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
@AllArgsConstructor
public enum ReservationErrorMessage implements ErrorMessage {

RESERVATION_NOT_FOUND(BAD_REQUEST, "해당 ID의 예약 정보가 없습니다.")
RESERVATION_NOT_FOUND(BAD_REQUEST, "해당 ID의 예약 정보가 없습니다."),
ROOM_STOCK_IS_EMPTY(BAD_REQUEST, "예약하려는 객실 상품이 이미 품절되었습니다.")
;
private final HttpStatus status;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ybe.mini.travelserver.global.exception.ProblemDetailCreator;

import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.RESERVATION_NOT_FOUND;
import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.ROOM_STOCK_IS_EMPTY;

@RestControllerAdvice
public class ReservationExceptionHandler extends ProblemDetailCreator<ReservationErrorMessage> {
Expand All @@ -20,5 +21,10 @@ public ProblemDetail handleReservationNotFoundException(HttpServletRequest reque
return createProblemDetail(RESERVATION_NOT_FOUND, request);
}

@ExceptionHandler(RoomStockIsEmptyException.class)
public ProblemDetail handleRoomStockIsEmptyException(HttpServletRequest request) {
return createProblemDetail(ROOM_STOCK_IS_EMPTY, request);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ybe.mini.travelserver.domain.reservation.exception;

public class RoomStockIsEmptyException extends RuntimeException {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.Local;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ybe.mini.travelserver.domain.accommodation.entity.Accommodation;
Expand All @@ -16,14 +17,16 @@
import ybe.mini.travelserver.domain.reservation.dto.ReservationGetResponse;
import ybe.mini.travelserver.domain.reservation.entity.Reservation;
import ybe.mini.travelserver.domain.reservation.exception.ReservationNotFoundException;
import ybe.mini.travelserver.domain.reservation.exception.RoomStockIsEmptyException;
import ybe.mini.travelserver.domain.reservation.repository.ReservationRepository;
import ybe.mini.travelserver.domain.reservation_room.dto.ReservationRoomCreateRequest;
import ybe.mini.travelserver.domain.reservation_room.entity.ReservationRoom;
import ybe.mini.travelserver.domain.reservation_room.repository.ReservationRoomRepository;
import ybe.mini.travelserver.domain.room.entity.Room;
import ybe.mini.travelserver.domain.room.repository.RoomRepository;
import ybe.mini.travelserver.global.api.TourAPIService;
import ybe.mini.travelserver.global.util.Validation;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -35,6 +38,7 @@
public class ReservationService {

private final ReservationRepository reservationRepository;
private final ReservationRoomRepository reservationRoomRepository;
private final MemberRepository memberRepository;
private final TourAPIService tourAPIService;
private final RoomRepository roomRepository;
Expand All @@ -44,15 +48,35 @@ public class ReservationService {
@Transactional
public ReservationCreateResponse createReservation(String userEmail, ReservationCreateRequest reservationRequest) {


List<ReservationRoom> reservationRooms =
reservationRoomDtosToEntityList(reservationRequest.reservationRooms());

reservationRooms.forEach(this::isEnableReservation);

Member member = getMemberByEmail(userEmail);
Reservation reservation =
Reservation.createReservation(member, reservationRequest.paymentType(), reservationRooms);

return ReservationCreateResponse.fromEntity(reservationRepository.save(reservation));
}

private void isEnableReservation(ReservationRoom resRoom) {
int restStock = getRestStock(
resRoom.getRoom(), resRoom.getCheckIn(), resRoom.getCheckOut()
);
if(restStock==0) throw new RoomStockIsEmptyException();
}

private Integer getRestStock(Room room, LocalDate checkIn, LocalDate checkOut) {
List<ReservationRoom> reservationRooms =
reservationRoomRepository.findAllByRoomAndCheckInBetweenAndCheckOutBetween(
room, checkIn, checkOut, checkIn, checkOut
);
return Math.max(0, room.getStock() - reservationRooms.size());

}

public ReservationCreateResponse createReservationAndDeleteCart(
String userEmail, ReservationCreateFromCartRequest reservationRequest
) {
Expand Down Expand Up @@ -95,7 +119,7 @@ private ReservationRoom reservationRoomDtoToEntity(ReservationRoomCreateRequest
String areaCodeString =
(roomRequest.areaCode() != null) ? String.valueOf(roomRequest.areaCode().getCode()) : null;

Accommodation accommodation = //todo : Bring 제대로 안되면 Exception 날려주는 거 고민
Accommodation accommodation =
tourAPIService.bringAccommodation(roomRequest.accommodationName(), areaCodeString);
Room room = tourAPIService.bringRoom(roomRequest.accommodationId(), roomRequest.roomTypeId());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ybe.mini.travelserver.domain.reservation_room.dto;

import jakarta.validation.constraints.*;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Builder;
import org.springframework.format.annotation.DateTimeFormat;
import ybe.mini.travelserver.domain.accommodation.entity.AreaCode;

import java.io.Serializable;
import java.time.LocalDateTime;

@Builder
public record ReservationRoomCreateRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private Integer getRestStock(Room room, LocalDate checkIn, LocalDate checkOut) {
reservationRoomRepository.findAllByRoomAndCheckInBetweenAndCheckOutBetween(
roomOpt.get(), checkIn, checkOut, checkIn, checkOut
);
return room.getStock() - reservationRooms.size();
return Math.max(0, room.getStock() - reservationRooms.size());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TourAPIProperties {
public static final String KEY_DECODED = "0ON3kBtDxd0KYGW5spO8inNljADd/IqfnS/l3nMWq3EkARl20N3MmZVYlSvH3Y8V5fEAo7Seucd5pR7Ebm2Phg==";
public static final String KEY_ENCODED = "0ON3kBtDxd0KYGW5spO8inNljADd%2FIqfnS%2Fl3nMWq3EkARl20N3MmZVYlSvH3Y8V5fEAo7Seucd5pR7Ebm2Phg%3D%3D";

private static int keyIndex = 0;

public static final String BASE_URL = "https://apis.data.go.kr/B551011/KorService1/";

public static final String SEARCH_KEYWORD = "searchKeyword1";
Expand All @@ -15,4 +20,21 @@ public class TourAPIProperties {
public static final String MOBILE_OS = "ETC";
public static final String MOBILE_APP = "TravelAPP";
public static final String RENDER_TYPE = "json";

private static final List<String> keyList = List.of(
System.getenv("TOUR_API_KEY_1"),
System.getenv("TOUR_API_KEY_2"),
System.getenv("TOUR_API_KEY_3"),
System.getenv("TOUR_API_KEY_4"),
System.getenv("TOUR_API_KEY_5")
);

public static String getEncodedKey() {
return keyList.get(keyIndex);
}

public static void changeNextKey() {
log.warn("API KEY를 변경합니다.");
TourAPIProperties.keyIndex = ++keyIndex % keyList.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private static StringBuilder buildCommonUrl(String endpoint) {
url.append("&MobileApp=").append(MOBILE_APP);
url.append("&_type=").append(RENDER_TYPE);
url.append("&contentTypeId=").append(CONTENT_TYPE_ID);
url.append("&serviceKey=").append(KEY_ENCODED);
url.append("&serviceKey=").append(getEncodedKey());

return url;
}
Expand All @@ -78,7 +78,9 @@ private static <T> T fetchDataFromAPI(
clientHttpResponse -> {
MediaType contentType = clientHttpResponse.getHeaders().getContentType();
if (contentType != null && contentType.includes(MediaType.TEXT_XML)) {
try {
try (clientHttpResponse) {
changeNextKey();

JAXBContext jaxbContext = JAXBContext.newInstance(TourAPIXMLErrorResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
TourAPIXMLErrorResponse tourAPIXMLErrorResponse = (TourAPIXMLErrorResponse) unmarshaller.unmarshal(clientHttpResponse.getBody());
Expand Down
Loading