From 18d8bcbd6231064f30fd5ed2e7d106e3c42d3a5a Mon Sep 17 00:00:00 2001 From: Young Hun Park Date: Wed, 14 Feb 2024 23:54:13 +0900 Subject: [PATCH] feat: Carpool close API --- .../application/carpool/CarpoolService.java | 28 +++++++++++--- .../carpool/application/form/FormService.java | 32 ++++++++-------- .../com/fullcar/carpool/domain/form/Form.java | 37 +++++++++++++++---- .../form/event/FormStateChangedEvent.java | 11 ++++++ .../domain/service/CarpoolCloseService.java | 28 -------------- .../carpool/CarpoolController.java | 16 ++++++++ 6 files changed, 94 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/fullcar/carpool/domain/form/event/FormStateChangedEvent.java delete mode 100644 src/main/java/com/fullcar/carpool/domain/service/CarpoolCloseService.java diff --git a/src/main/java/com/fullcar/carpool/application/carpool/CarpoolService.java b/src/main/java/com/fullcar/carpool/application/carpool/CarpoolService.java index 9570656..2e0f01a 100644 --- a/src/main/java/com/fullcar/carpool/application/carpool/CarpoolService.java +++ b/src/main/java/com/fullcar/carpool/application/carpool/CarpoolService.java @@ -6,7 +6,7 @@ import com.fullcar.carpool.domain.carpool.Driver; import com.fullcar.carpool.domain.form.Form; import com.fullcar.carpool.domain.form.FormRepository; -import com.fullcar.carpool.domain.service.CarpoolCloseService; +import com.fullcar.carpool.domain.form.FormState; import com.fullcar.carpool.presentation.carpool.dto.request.CarpoolRequestDto; import com.fullcar.carpool.presentation.carpool.dto.response.CarpoolResponseDto; import com.fullcar.carpool.presentation.carpool.dto.response.MyCarpoolDto; @@ -16,6 +16,7 @@ import com.fullcar.member.domain.car.CarRepository; import com.fullcar.member.domain.member.Member; +import com.fullcar.member.domain.member.MemberRepository; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; @@ -32,9 +33,9 @@ public class CarpoolService { private final CarpoolRepository carpoolRepository; private final CarRepository carRepository; //:TODO Event 기반으로 변경 + private final MemberRepository memberRepository; //:TODO Event 기반으로 변경 private final FormRepository formRepository; private final CarpoolMapper carpoolMapper; - private final CarpoolCloseService carpoolCloseService; @Transactional public CarpoolResponseDto registerCarpool(Member member, CarpoolRequestDto carpoolRequestDto) { @@ -86,17 +87,32 @@ public List getMyCarpoolList(Member member) { } @Transactional - public CarpoolResponseDto closeCarpool(Member member, CarpoolId carpoolId) { + public CarpoolResponseDto.CarpoolDetailDtO closeCarpool(Member member, CarpoolId carpoolId) { Carpool carpool = carpoolRepository.findByCarpoolIdAndIsDeletedOrThrow(carpoolId, false); + Car car = carRepository.findByCarIdAndIsDeletedOrThrow(member.getCarId(), false); if (!carpool.isMyCarpool(member.getId())) { throw new CustomException(ErrorCode.CANNOT_CLOSE_CARPOOL); } List
forms = formRepository.findAllByCarpoolIdAndIsDeleted(carpoolId, false); - carpool = carpoolCloseService.closeCarpool(carpool); - forms = carpoolCloseService.rejectForms(forms); + carpool.close(); - return carpoolMapper.toDto(carpool, member); + for (Form form: forms) { + if (form.getFormState() == FormState.REQUEST) { + form.reject( + memberRepository.findByIdAndIsDeletedOrThrow( + form.getPassenger().getMemberId(), + false + ) + ); + } + + } // TODO: N+1 문제 개선 필요. + + carpoolRepository.save(carpool); + formRepository.saveAllAndFlush(forms); + + return carpoolMapper.toDetailDto(carpool, member, car); } } diff --git a/src/main/java/com/fullcar/carpool/application/form/FormService.java b/src/main/java/com/fullcar/carpool/application/form/FormService.java index 28d21e2..b3d7c2e 100644 --- a/src/main/java/com/fullcar/carpool/application/form/FormService.java +++ b/src/main/java/com/fullcar/carpool/application/form/FormService.java @@ -5,8 +5,9 @@ import com.fullcar.carpool.domain.carpool.CarpoolRepository; import com.fullcar.carpool.domain.carpool.CarpoolState; import com.fullcar.carpool.domain.form.*; +import com.fullcar.carpool.domain.form.event.FormStateChangedEvent; import com.fullcar.carpool.domain.service.NotificationService; -import com.fullcar.carpool.infra.NotificationClient; +import com.fullcar.carpool.infra.dto.NotificationDto; import com.fullcar.carpool.presentation.form.dto.request.FormRequestDto; import com.fullcar.carpool.presentation.form.dto.request.FormUpdateDto; import com.fullcar.carpool.presentation.form.dto.response.FormResponseDto; @@ -16,6 +17,7 @@ import com.fullcar.member.domain.member.MemberRepository; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -32,6 +34,7 @@ public class FormService { private final MemberRepository memberRepository; //TODO: Event 기반으로 변경 필요. private final FormMapper formMapper; private final NotificationService notificationService; + private final ApplicationEventPublisher eventPublisher; @Transactional public FormResponseDto requestForm(Member member, CarpoolId carpoolId, FormRequestDto formRequestDto) { @@ -59,7 +62,17 @@ public FormResponseDto requestForm(Member member, CarpoolId carpoolId, FormReque } Form form = formMapper.toEntity(member, carpoolId, formRequestDto); - notificationService.sendNotification(driver.getNickname(), driver.getDeviceToken(), "탑승 요청이 들어왔어요!", "탑승자 정보를 확인하고 승인해 주세요🚘"); + + eventPublisher.publishEvent( + new FormStateChangedEvent( + NotificationDto.builder() + .nickName(driver.getNickname()) + .deviceToken(driver.getDeviceToken()) + .title(FormMessage.REQUEST_TITLE.getMessage()) + .body(FormMessage.REQUEST_BODY.getMessage()) + .build() + ) + ); return formMapper.toDto( formRepository.saveAndFlush(form), @@ -101,8 +114,6 @@ public List readReceivedFormList(Member member) { @Transactional public FormResponseDto.FormDetailDto updateForm(Member member, FormId formId, FormUpdateDto formUpdateDto) { Form form = formRepository.findByFormIdAndIsDeletedOrThrow(formId, false); - form.changeFormState(formUpdateDto); - Member passenger = memberRepository.findByIdAndIsDeletedOrThrow(form.getPassenger().getMemberId(), false); Carpool carpool = carpoolRepository.findByCarpoolIdAndIsDeletedOrThrow(form.getCarpoolId(), false); @@ -110,18 +121,7 @@ public FormResponseDto.FormDetailDto updateForm(Member member, FormId formId, Fo throw new CustomException(ErrorCode.CANNOT_CHANGE_FORM_STATE); } - System.out.println(passenger.getDeviceToken()); - - if (formUpdateDto.getFormState() == FormState.ACCEPT) { - String title = "카풀 매칭에 성공했어요!"; - String body = "운전자 정보를 확인해 주세요🚘"; - notificationService.sendNotification(passenger.getNickname(), passenger.getDeviceToken(), title, body); - } - else if (formUpdateDto.getFormState() == FormState.REJECT) { - String title = "카풀 매칭에 실패했어요."; - String body = "다른 카풀을 찾아볼까요?💁🏻‍♀️"; - notificationService.sendNotification(passenger.getNickname(), passenger.getDeviceToken(), title, body); - } + form.changeFormState(formUpdateDto, passenger); return formMapper.toDetailDto( formRepository.saveAndFlush(form), diff --git a/src/main/java/com/fullcar/carpool/domain/form/Form.java b/src/main/java/com/fullcar/carpool/domain/form/Form.java index a7ce401..5e80331 100644 --- a/src/main/java/com/fullcar/carpool/domain/form/Form.java +++ b/src/main/java/com/fullcar/carpool/domain/form/Form.java @@ -1,13 +1,17 @@ package com.fullcar.carpool.domain.form; import com.fullcar.carpool.domain.carpool.CarpoolId; +import com.fullcar.carpool.domain.form.event.FormStateChangedEvent; +import com.fullcar.carpool.infra.dto.NotificationDto; import com.fullcar.carpool.presentation.form.dto.request.FormUpdateDto; import com.fullcar.core.exception.CustomException; import com.fullcar.core.response.ErrorCode; +import com.fullcar.member.domain.member.Member; import jakarta.persistence.*; import lombok.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.domain.AbstractAggregateRoot; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @@ -19,8 +23,7 @@ @AllArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) @Table(name = "form") -public class Form { - private static final String REJECT_MESSAGE = "카풀 매칭에 실패했어요. 다른 카풀을 찾아보세요!"; +public class Form extends AbstractAggregateRoot { @EmbeddedId private FormId formId; @@ -60,32 +63,50 @@ public class Form { @LastModifiedDate private LocalDateTime updatedAt; - public void changeFormState(FormUpdateDto formUpdateDto) { + public void changeFormState(FormUpdateDto formUpdateDto, Member passenger) { FormState formState = formUpdateDto.getFormState(); if (formState == FormState.ACCEPT) { - this.accept(formUpdateDto.getContact(), formUpdateDto.getToPassenger()); + this.accept(formUpdateDto.getContact(), formUpdateDto.getToPassenger(), passenger); } else if (formState == FormState.REJECT) { - this.reject(); + this.reject(passenger); } else { throw new CustomException(ErrorCode.INVALID_FORM_STATE); } } - public void accept(String contact, String toPassenger) { + public void accept(String contact, String toPassenger, Member passenger) { this.formState = FormState.ACCEPT; this.resultMessage = ResultMessage.builder() .contact(contact) .toPassenger(toPassenger) .build(); + + registerEvent(new FormStateChangedEvent( + NotificationDto.builder() + .nickName(passenger.getNickname()) + .deviceToken(passenger.getDeviceToken()) + .title(FormMessage.ACCEPT_TITLE.getMessage()) + .body(FormMessage.ACCEPT_BODY.getMessage()) + .build() + )); } - public void reject() { + public void reject(Member passenger) { this.formState = FormState.REJECT; this.resultMessage = ResultMessage.builder() - .toPassenger(REJECT_MESSAGE) + .toPassenger(FormMessage.REJECT_MESSAGE.getMessage()) .build(); + + registerEvent(new FormStateChangedEvent( + NotificationDto.builder() + .nickName(passenger.getNickname()) + .deviceToken(passenger.getDeviceToken()) + .title(FormMessage.REJECT_TITLE.getMessage()) + .body(FormMessage.REJECT_BODY.getMessage()) + .build() + )); } } diff --git a/src/main/java/com/fullcar/carpool/domain/form/event/FormStateChangedEvent.java b/src/main/java/com/fullcar/carpool/domain/form/event/FormStateChangedEvent.java new file mode 100644 index 0000000..c74212c --- /dev/null +++ b/src/main/java/com/fullcar/carpool/domain/form/event/FormStateChangedEvent.java @@ -0,0 +1,11 @@ +package com.fullcar.carpool.domain.form.event; + +import com.fullcar.carpool.infra.dto.NotificationDto; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class FormStateChangedEvent { + private NotificationDto notificationDto; +} diff --git a/src/main/java/com/fullcar/carpool/domain/service/CarpoolCloseService.java b/src/main/java/com/fullcar/carpool/domain/service/CarpoolCloseService.java deleted file mode 100644 index 5592cb4..0000000 --- a/src/main/java/com/fullcar/carpool/domain/service/CarpoolCloseService.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fullcar.carpool.domain.service; - -import com.fullcar.carpool.domain.carpool.Carpool; -import com.fullcar.carpool.domain.form.Form; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class CarpoolCloseService { - - public Carpool closeCarpool(Carpool carpool) { - carpool.close(); - - return carpool; - } - - public List rejectForms(List forms) { - for (Form form : forms) { - form.reject(); - } - - return forms; - } -} diff --git a/src/main/java/com/fullcar/carpool/presentation/carpool/CarpoolController.java b/src/main/java/com/fullcar/carpool/presentation/carpool/CarpoolController.java index c702838..ca24a43 100644 --- a/src/main/java/com/fullcar/carpool/presentation/carpool/CarpoolController.java +++ b/src/main/java/com/fullcar/carpool/presentation/carpool/CarpoolController.java @@ -92,4 +92,20 @@ public ApiResponse> getMyCarpools( carpoolService.getMyCarpoolList(member) ); } + + @Operation(summary = "카풀 마감 API") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "수정 성공") + }) + @PatchMapping("/carpools/{carpoolId}") + public ApiResponse patchCarpool( + @Parameter(hidden = true) + @CurrentMember Member member, + @PathVariable Long carpoolId + ) { + return ApiResponse.success( + SuccessCode.UPDATE_SUCCESS, + carpoolService.closeCarpool(member, new CarpoolId(carpoolId)) + ); + } }