Skip to content

Commit

Permalink
Merge pull request #90 from YAPP-Github/feat/ISSUE-84
Browse files Browse the repository at this point in the history
feat: Carpool close API
  • Loading branch information
Park-Young-Hun authored Feb 15, 2024
2 parents d59157f + 18d8bcb commit c4b6228
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.fullcar.carpool.domain.carpool.CarpoolId;
import com.fullcar.carpool.domain.carpool.CarpoolRepository;
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.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;
Expand All @@ -13,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.*;
Expand All @@ -29,6 +33,8 @@
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;

@Transactional
Expand Down Expand Up @@ -79,4 +85,34 @@ public List<MyCarpoolDto> getMyCarpoolList(Member member) {
.map(carpool -> carpoolMapper.toMyCarpoolDto(carpool, member))
.toList();
}

@Transactional
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<Form> forms = formRepository.findAllByCarpoolIdAndIsDeleted(carpoolId, false);

carpool.close();

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);
}
}
40 changes: 23 additions & 17 deletions src/main/java/com/fullcar/carpool/application/form/FormService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import com.fullcar.carpool.domain.carpool.Carpool;
import com.fullcar.carpool.domain.carpool.CarpoolId;
import com.fullcar.carpool.domain.carpool.CarpoolRepository;
import com.fullcar.carpool.domain.carpool.CarpoolState;
import com.fullcar.carpool.domain.form.*;
import com.fullcar.carpool.infra.NotificationClient;
import com.fullcar.carpool.domain.form.event.FormStateChangedEvent;
import com.fullcar.carpool.domain.service.NotificationService;
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;
Expand All @@ -14,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;
Expand All @@ -29,13 +33,18 @@ public class FormService {
private final CarpoolRepository carpoolRepository;
private final MemberRepository memberRepository; //TODO: Event 기반으로 변경 필요.
private final FormMapper formMapper;
private final NotificationClient pushNotificationClient;
private final NotificationService notificationService;
private final ApplicationEventPublisher eventPublisher;

@Transactional
public FormResponseDto requestForm(Member member, CarpoolId carpoolId, FormRequestDto formRequestDto) {
Carpool carpool = carpoolRepository.findByCarpoolIdAndIsDeletedOrThrow(carpoolId, false);
Member driver = memberRepository.findByIdAndIsDeletedOrThrow(carpool.getDriver().getMemberId(), false);

if (carpool.getCarpoolState() == CarpoolState.CLOSE) {
throw new CustomException(ErrorCode.CANNOT_SEND_TO_CLOSED_CARPOOL);
}

if (carpool.isMyCarpool(member.getId())) {
throw new CustomException(ErrorCode.CANNOT_SEND_TO_OWN_CARPOOL);
}
Expand All @@ -53,7 +62,17 @@ public FormResponseDto requestForm(Member member, CarpoolId carpoolId, FormReque
}

Form form = formMapper.toEntity(member, carpoolId, formRequestDto);
pushNotificationClient.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),
Expand Down Expand Up @@ -95,27 +114,14 @@ public List<FormResponseDto> 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);

if (!carpool.isMyCarpool(member.getId())) {
throw new CustomException(ErrorCode.CANNOT_CHANGE_FORM_STATE);
}

System.out.println(passenger.getDeviceToken());

if (formUpdateDto.getFormState() == FormState.ACCEPT) {
String title = "카풀 매칭에 성공했어요!";
String body = "운전자 정보를 확인해 주세요🚘";
pushNotificationClient.sendNotification(passenger.getNickname(), passenger.getDeviceToken(), title, body);
}
else if (formUpdateDto.getFormState() == FormState.REJECT) {
String title = "카풀 매칭에 실패했어요.";
String body = "다른 카풀을 찾아볼까요?💁🏻‍♀️";
pushNotificationClient.sendNotification(passenger.getNickname(), passenger.getDeviceToken(), title, body);
}
form.changeFormState(formUpdateDto, passenger);

return formMapper.toDetailDto(
formRepository.saveAndFlush(form),
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/carpool/Carpool.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ public class Carpool {
public boolean isMyCarpool(MemberId memberId) {
return this.getDriver().getMemberId().getId().equals(memberId.getId());
}

public void close() {
this.carpoolState = CarpoolState.CLOSE;
}
}
37 changes: 29 additions & 8 deletions src/main/java/com/fullcar/carpool/domain/form/Form.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Form> {

@EmbeddedId
private FormId formId;
Expand Down Expand Up @@ -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()
));
}
}
18 changes: 18 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/form/FormMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.fullcar.carpool.domain.form;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum FormMessage {
REJECT_MESSAGE("카풀 매칭에 실패했어요. 다른 카풀을 찾아보세요!"),
REQUEST_TITLE("탑승 요청이 들어왔어요!"),
REQUEST_BODY("탑승자 정보를 확인하고 승인해 주세요🚘"),
ACCEPT_TITLE("카풀 매칭에 성공했어요!"),
ACCEPT_BODY("운전자 정보를 확인해 주세요🚘"),
REJECT_TITLE("카풀 매칭에 실패했어요."),
REJECT_BODY("다른 카풀을 찾아볼까요?💁🏻‍♀️");

private final String message;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ List<Form> findReceivedForm(
@Param("memberId") Long memberId
);

List<Form> findAllByCarpoolIdAndIsDeleted(CarpoolId carpoolId, boolean isDeleted);

default Form findByFormIdAndIsDeletedOrThrow(FormId formId, boolean isDeleted) {
return findByFormIdAndIsDeleted(formId, isDeleted).orElseThrow(
() -> new CustomException(ErrorCode.NOT_EXIST_FORM)
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.fullcar.carpool.domain.service;

import com.fullcar.carpool.infra.dto.NotificationDto;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface NotificationService {
void sendNotification(String nickname, String deviceToken, String title, String body);
void sendNotification(NotificationDto notificationDto);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fullcar.carpool.infra;

import com.fullcar.carpool.domain.service.NotificationService;
import com.fullcar.carpool.infra.dto.NotificationDto;
import com.fullcar.core.exception.CustomException;
import com.fullcar.core.response.ErrorCode;
import com.google.firebase.messaging.FirebaseMessaging;
Expand All @@ -17,14 +18,14 @@ public class NotificationClient implements NotificationService {
private final FirebaseMessaging firebaseMessaging;

@Override
public void sendNotification(String nickname, String deviceToken, String title, String body) {
public void sendNotification(NotificationDto notificationDto) {
Notification notification = Notification.builder()
.setTitle(nickname + "님! " + title)
.setBody(body)
.setTitle(notificationDto.getNickName() + "님! " + notificationDto.getTitle())
.setBody(notificationDto.getBody())
.build();

Message message = Message.builder()
.setToken(deviceToken)
.setToken(notificationDto.getDeviceToken())
.setNotification(notification)
.build();

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/fullcar/carpool/infra/dto/NotificationDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.fullcar.carpool.infra.dto;

import lombok.*;

@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class NotificationDto {
private String nickName;

private String deviceToken;

private String title;

private String body;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.fullcar.carpool.infra.event;

import com.fullcar.carpool.infra.dto.NotificationDto;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class NotificationEvent {
private NotificationDto notificationDto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.fullcar.carpool.infra.event;

import com.fullcar.carpool.domain.form.event.FormStateChangedEvent;
import com.fullcar.carpool.domain.service.NotificationService;
import com.fullcar.carpool.infra.dto.NotificationDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
@EnableAsync
public class NotificationEventListener {
private final NotificationService notificationService;

@Async
@EventListener
public void sendNotification(FormStateChangedEvent formStateChangedEvent) {
notificationService.sendNotification(formStateChangedEvent.getNotificationDto());
log.info("Notification send");
}
}
Loading

0 comments on commit c4b6228

Please sign in to comment.