Skip to content
Open
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 @@ -12,6 +12,7 @@
import com.homeaid.payment.exception.PaymentErrorCode;
import com.homeaid.payment.repository.PaymentRepository;
import com.homeaid.payment.validator.PaymentValidator;
import com.homeaid.reservation.dto.ReservationDtoMapper;
import com.homeaid.reservation.dto.response.ReservationResponseDto;
import com.homeaid.reservation.repository.ReservationRepository;
import com.homeaid.repository.UserRepository;
Expand All @@ -30,6 +31,7 @@ public class PaymentServiceImpl implements PaymentService {
private final ReservationRepository reservationRepository;
private final UserRepository userRepository;
private final PaymentValidator paymentValidator;
private final ReservationDtoMapper reservationDtoMapper;

@Override
@Transactional
Expand Down Expand Up @@ -80,7 +82,7 @@ public ReservationPaymentDetailResponseDto getReservationPaymentDetail(Long cust

String customerName = getCustomerName(reservation.getCustomer().getId());

ReservationResponseDto reservationDto = ReservationResponseDto.toDto(reservation);
ReservationResponseDto reservationDto = reservationDtoMapper.toDto(reservation);
PaymentResponseDto paymentDto = PaymentResponseDto.toDto(payment, customerName);

return ReservationPaymentDetailResponseDto.of(reservationDto, paymentDto);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ public class ServiceIssueServiceImpl implements ServiceIssueService {
public void createIssue(Long reservationId, Long managerId, String content,
List<MultipartFile> files) {

Reservation reservation = reservationService.validateReservation(reservationId);
reservationService.validateManagerAccess(reservation, managerId);
Reservation reservation = reservationService.validateReservation(reservationId, managerId);
existsByReservationId(reservation.getId());

ServiceIssue issue = ServiceIssue.builder()
Expand All @@ -50,8 +49,7 @@ public void createIssue(Long reservationId, Long managerId, String content,
@Transactional(readOnly = true)
public ServiceIssue getIssueByReservation(Long reservationId, Long userId) {

Reservation reservation = reservationService.validateReservation(reservationId);
reservationService.validateUserAccess(reservation, userId);
reservationService.validateReservationAndUserAccess(reservationId, userId);

return findByReservationId(reservationId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import com.homeaid.common.response.CommonApiResponse;
import com.homeaid.common.response.PagedResponseDto;
import com.homeaid.reservation.domain.Reservation;
import com.homeaid.reservation.dto.response.ReservationInfo;
import com.homeaid.reservation.domain.enumerate.ReservationStatus;
import com.homeaid.reservation.dto.ReservationDtoMapper;
import com.homeaid.reservation.dto.request.ReservationRequestDto;
import com.homeaid.reservation.dto.request.UpdateReservationRequestDto;
import com.homeaid.reservation.dto.response.ManagerReservationResponseDto;
import com.homeaid.reservation.dto.response.ReservationResponseDto;
import com.homeaid.auth.user.CustomUserDetails;
Expand Down Expand Up @@ -45,22 +46,25 @@ public class ReservationController {

private final ReservationService reservationService;

private final ReservationDtoMapper reservationDtoMapper;


@PostMapping
@Operation(summary = "예약 생성", description = "고객이 예약 옵션을 선택하여 예약을 생성합니다.")
@ApiResponse(responseCode = "201", description = "예약 생성 성공",
content = @Content(schema = @Schema(implementation = ReservationResponseDto.class)))
@ApiResponse(responseCode = "400", description = "유효하지 않은 요청",
content = @Content(schema = @Schema(implementation = CommonApiResponse.class)))
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> createReservation(
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> createReservation (
@AuthenticationPrincipal CustomUserDetails user,
@RequestBody @Valid ReservationRequestDto reservationRequestDto) {
@RequestBody @Valid ReservationRequestDto reservationRequestDto
) {

Reservation reservation = reservationService.createReservation(
ReservationRequestDto.toEntity(reservationRequestDto), user.getUserId(),
reservationRequestDto.getOptionId());
ReservationInfo reservationInfo = reservationService.createReservation(
reservationDtoMapper.toCommand(reservationRequestDto, user.getUserId()));

return ResponseEntity.status(HttpStatus.CREATED)
.body(CommonApiResponse.success(ReservationResponseDto.toDto(reservation)));
.body(CommonApiResponse.success(reservationDtoMapper.toDto(reservationInfo)));
}

@GetMapping("/{reservationId}")
Expand All @@ -71,13 +75,13 @@ public ResponseEntity<CommonApiResponse<ReservationResponseDto>> createReservati
@ApiResponse(responseCode = "404", description = "해당 예약이 존재하지 않음",
content = @Content(schema = @Schema(implementation = CommonApiResponse.class))),
})
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> getReservation(
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> getReservation (
@Parameter(description = "조회할 예약 ID", example = "1")
@PathVariable(name = "reservationId") Long reservationId
@PathVariable(name = "reservationId") final Long reservationId
) {

return ResponseEntity.ok(
CommonApiResponse.success(reservationService.getReservation(reservationId)));
CommonApiResponse.success(reservationDtoMapper.toDto(reservationService.getReservation(reservationId))));
}

@PutMapping("/{reservationId}")
Expand All @@ -88,19 +92,16 @@ public ResponseEntity<CommonApiResponse<ReservationResponseDto>> getReservation(
@ApiResponse(responseCode = "400", description = "유효하지 않은 요청 또는 수정 불가 상태",
content = @Content(schema = @Schema(implementation = CommonApiResponse.class))),
})
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> updateReservation(
public ResponseEntity<CommonApiResponse<ReservationResponseDto>> updateReservation (
@AuthenticationPrincipal CustomUserDetails user,
@Parameter(description = "수정할 예약 ID", example = "1")
@PathVariable(name = "reservationId") Long reservationId,
@PathVariable(name = "reservationId") final Long reservationId,
@RequestBody @Valid ReservationRequestDto reservationRequestDto) {

Reservation updated = reservationService.updateReservation(
user.getUserId(),
reservationId,
UpdateReservationRequestDto.toEntity(reservationRequestDto),
reservationRequestDto.getOptionId());
ReservationInfo reservationInfo = reservationService.updateReservation(
reservationDtoMapper.toCommand(reservationRequestDto, user.getUserId(), reservationId));

return ResponseEntity.ok(CommonApiResponse.success(ReservationResponseDto.toDto(updated)));
return ResponseEntity.ok(CommonApiResponse.success(reservationDtoMapper.toDto(reservationInfo)));
}

@DeleteMapping("/{reservationId}")
Expand All @@ -114,7 +115,7 @@ public ResponseEntity<CommonApiResponse<ReservationResponseDto>> updateReservati
public ResponseEntity<CommonApiResponse<Void>> deleteReservation(
@AuthenticationPrincipal CustomUserDetails user,
@Parameter(description = "삭제할 예약 ID", example = "1")
@PathVariable(name = "reservationId") Long reservationId
@PathVariable(name = "reservationId") final Long reservationId
) {
reservationService.deleteReservation(reservationId, user.getUserId());
return ResponseEntity.ok(CommonApiResponse.success(null));
Expand All @@ -125,7 +126,7 @@ public ResponseEntity<CommonApiResponse<Void>> deleteReservation(
*/
@GetMapping
@Operation(summary = "예약 전체 조회", description = "페이지네이션 기반으로 예약 목록을 조회합니다.")
public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>>> getReservationsList(
public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>>> getReservationsList (
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size,
@RequestParam(value = "status", required = false) ReservationStatus status
Expand All @@ -144,17 +145,21 @@ public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>
*/
@GetMapping("/customer")
@Operation(summary = "특정 유저의 예약 전체 조회", description = "고객의 모든 예약을 페이지네이션으로 조회합니다.")
public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>>> getReservationsByCustomer(
public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>>> getReservationsByCustomer (
@AuthenticationPrincipal CustomUserDetails user,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {

Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdDate"));

Page<Reservation> reservations = reservationService.getReservationsByCustomer(user.getUserId(),
pageable);


PagedResponseDto<ReservationResponseDto> response =
PagedResponseDto.fromPage(reservations, ReservationResponseDto::toDto);
PagedResponseDto.fromPage(reservations, reservationDtoMapper::toDto);

return ResponseEntity.ok(CommonApiResponse.success(response));
}

Expand All @@ -163,17 +168,19 @@ public ResponseEntity<CommonApiResponse<PagedResponseDto<ReservationResponseDto>
*/
@GetMapping("/manager")
@Operation(summary = "매니저 담당 예약 전체 조회", description = "매니저가 담당 중인 예약을 페이지네이션으로 조회합니다.")
public ResponseEntity<CommonApiResponse<PagedResponseDto<ManagerReservationResponseDto>>> getReservationsByManager(
public ResponseEntity<CommonApiResponse<PagedResponseDto<ManagerReservationResponseDto>>> getReservationsByManager (
@AuthenticationPrincipal CustomUserDetails userDetails,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {

Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdDate"));

Page<ManagerReservationResponseDto> reservations = reservationService.getReservationsByManager(
userDetails.getUserId(), pageable);

PagedResponseDto<ManagerReservationResponseDto> response = PagedResponseDto.fromPage(reservations);
PagedResponseDto<ManagerReservationResponseDto> response = PagedResponseDto.fromPage(
reservations);

return ResponseEntity.ok(CommonApiResponse.success(response));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.homeaid.domain.Manager;
import com.homeaid.matching.domain.Matching;
import com.homeaid.reservation.domain.enumerate.ReservationStatus;
import com.homeaid.reservation.dto.request.ReservationCommand;
import com.homeaid.serviceoption.domain.ServiceOption;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -119,12 +120,13 @@ public void addItem(ServiceOption serviceOption) {
this.totalPrice = serviceOption.getPrice() * this.duration;
}

public void updateReservation(Reservation newReservation, int newTotalPrice,
int newDuration) {
public void updateReservation(ReservationCommand newReservation) {
this.requestedDate = newReservation.getRequestedDate();
this.requestedTime = newReservation.getRequestedTime();
this.totalPrice = newTotalPrice;
this.duration = newDuration;
this.latitude = newReservation.getLatitude();
this.longitude = newReservation.getLongitude();
this.address = newReservation.getAddress();
this.addressDetail = newReservation.getAddressDetail();
}

public void softDelete() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.homeaid.reservation.domain;


import com.homeaid.reservation.domain.enumerate.ReservationStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ReservationReader {

Reservation getReservation(Long reservationId);

Page<Reservation> getReservationByStatus(ReservationStatus status, Pageable pageable);

Page<Reservation> getReservationsByCustomerId(Long userId, Pageable pageable);

Page<Reservation> getReservationsByManagerId(Long managerId, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.homeaid.reservation.domain;

import com.homeaid.exception.CustomException;
import com.homeaid.reservation.domain.enumerate.ReservationStatus;
import com.homeaid.reservation.exception.ReservationErrorCode;
import com.homeaid.reservation.repository.ReservationRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

@Component
@Slf4j
@RequiredArgsConstructor
public class ReservationReaderImpl implements ReservationReader {

private final ReservationRepository reservationRepository;

@Override
public Reservation getReservation(Long reservationId) {
return getReservationById(reservationId);
}

@Override
public Page<Reservation> getReservationByStatus(ReservationStatus status, Pageable pageable) {
return reservationRepository.findByOptionalStatus(status, pageable);
}

@Override
public Page<Reservation> getReservationsByCustomerId(Long userId, Pageable pageable) {
return reservationRepository.findAllByCustomerId(userId, pageable);
}

@Override
public Page<Reservation> getReservationsByManagerId(Long managerId, Pageable pageable) {
return reservationRepository.findAllByManagerId(managerId, pageable);
}

private Reservation getReservationById(Long reservationId) {
return reservationRepository.findById(reservationId)
.orElseThrow(() -> new CustomException(ReservationErrorCode.RESERVATION_NOT_FOUND));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.homeaid.reservation.domain;

import com.homeaid.reservation.dto.request.ReservationCommand;

public interface ReservationStore {

Reservation save(ReservationCommand reservationCommand);

Reservation update(ReservationCommand reservationCommand);

void delete(Long reservationId, Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.homeaid.reservation.domain;


import com.homeaid.domain.Customer;
import com.homeaid.exception.CustomException;
import com.homeaid.exception.UserErrorCode;
import com.homeaid.repository.CustomerRepository;
import com.homeaid.reservation.domain.enumerate.ReservationStatus;
import com.homeaid.reservation.dto.request.ReservationCommand;
import com.homeaid.reservation.exception.ReservationErrorCode;
import com.homeaid.reservation.repository.ReservationRepository;
import com.homeaid.serviceoption.domain.ServiceOption;
import com.homeaid.serviceoption.repository.ServiceOptionRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
@RequiredArgsConstructor
public class ReservationStoreImpl implements ReservationStore {


private final ReservationRepository reservationRepository;
private final CustomerRepository customerRepository;
private final ServiceOptionRepository serviceOptionRepository;

@Override
public Reservation save(ReservationCommand reservationCommand) {

Reservation reservation = reservationCommand.toEntity();

Customer customer = customerRepository.findById(reservationCommand.getUserId())
.orElseThrow(() -> new CustomException(UserErrorCode.CUSTOMER_NOT_FOUND));

ServiceOption serviceOption = serviceOptionRepository.findById(reservationCommand.getOptionId())
.orElseThrow(() -> new CustomException(ReservationErrorCode.RESERVATION_NOT_FOUND));

reservation.addItem(serviceOption);
reservation.setCustomer(customer);

log.info("[예약 생성] customerId={}, serviceOptionId={}", reservationCommand.getUserId(),
reservationCommand.getOptionId());

return reservationRepository.save(reservation);
}

@Override
public Reservation update(ReservationCommand reservationCommand) {
Reservation originReservation = getReservationById(reservationCommand.getReservationId());

if (!originReservation.getCustomer().getId().equals(reservationCommand.getUserId())) {
log.warn("[예약 수정 실패] 권한 없음 - reservationId={}, userId={}", reservationCommand.getReservationId(), reservationCommand.getUserId());
throw new CustomException(ReservationErrorCode.UNAUTHORIZED_RESERVATION_ACCESS);
}

if (originReservation.getStatus() != ReservationStatus.REQUESTED) {
log.warn("[예약 수정 실패] 예약 상태 불가 - reservationId={}, status={}", reservationCommand.getReservationId(),
originReservation.getStatus());
throw new CustomException(ReservationErrorCode.RESERVATION_CANNOT_UPDATE);
}

ServiceOption serviceOption = getServiceOptionById(reservationCommand.getOptionId());

originReservation.updateReservation(reservationCommand);

ReservationItem item = originReservation.getItem();
item.updateItem(serviceOption);

return originReservation;
}

@Override
public void delete(Long reservationId, Long userId) {
Reservation reservation = getReservationById(reservationId);

if (!reservation.getCustomer().getId().equals(userId)) {
log.warn("[예약 삭제 실패] 권한 없음 - reservationId={}, userId={}", reservationId, userId);
throw new CustomException(ReservationErrorCode.UNAUTHORIZED_RESERVATION_ACCESS);
}

reservation.softDelete();
}

private Reservation getReservationById(Long reservationId) {
return reservationRepository.findById(reservationId)
.orElseThrow(() -> new CustomException(ReservationErrorCode.RESERVATION_NOT_FOUND));
}

private ServiceOption getServiceOptionById(Long serviceOptionId) {
return serviceOptionRepository.findById(serviceOptionId)
.orElseThrow(() -> new CustomException(ReservationErrorCode.RESERVATION_NOT_FOUND));
}

}
Loading