Skip to content
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
@@ -1,5 +1,7 @@
package be.dash.dashserver.api.core.lesson.dto;

import java.time.LocalDateTime;
import be.dash.dashserver.api.core.member.dto.ApplyStatus;
import be.dash.dashserver.core.domain.common.Genre;
import be.dash.dashserver.core.domain.common.Level;
import be.dash.dashserver.core.domain.lesson.Lesson;
Expand Down Expand Up @@ -27,7 +29,9 @@ public record LessonDetailResponse(
String oldStreetAddress,
long favoriteCount,
boolean bookStatus,
LessonStatus status
LessonStatus status,
ApplyStatus applyStatus,
LocalDateTime createdAt
) {

public LessonDetailResponse(Lesson lesson, boolean booked) {
Expand All @@ -51,6 +55,8 @@ public LessonDetailResponse(Lesson lesson, boolean booked) {
lesson.getLocation().getAddress(),
lesson.getFavoriteCount(),
booked,
LessonStatus.from(lesson));
LessonStatus.from(lesson),
lesson.getApplyStatus(),
lesson.getCreatedAt());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package be.dash.dashserver.core.domain.lesson;

import java.time.LocalDateTime;
import be.dash.dashserver.api.core.member.dto.ApplyStatus;
import be.dash.dashserver.core.domain.common.Genre;
import be.dash.dashserver.core.domain.common.Level;
import be.dash.dashserver.core.domain.teacher.Teacher;
Expand Down Expand Up @@ -74,6 +75,10 @@ public boolean isFull() {
return reservationCount >= maxReservationCount;
}

public ApplyStatus getApplyStatus() {
return ApplyStatus.calculate(rounds.getStartTime(), reservationCount, maxReservationCount);
}

public int calculateDDay() {
return getStartTime().getDayOfYear() - LocalDateTime.now().getDayOfYear();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import be.dash.dashserver.core.domain.reservation.ReservationStatus;
import be.dash.dashserver.core.domain.reservation.Reservations;
import be.dash.dashserver.core.domain.reservation.service.ReservationRepository;
import be.dash.dashserver.core.domain.teacher.Teacher;
import be.dash.dashserver.core.exception.ConflictException;
import be.dash.dashserver.core.exception.ForbiddenException;
import be.dash.dashserver.core.external.MessageSender;
import be.dash.dashserver.core.log.annotation.Trace;
import lombok.RequiredArgsConstructor;

Expand All @@ -33,6 +35,7 @@ public class MemberService {
private final MemberRepository memberRepository;
private final LessonRepository lessonRepository;
private final ReservationRepository reservationRepository;
private final MessageSender messageSender;

@Transactional
public void onboard(OnboardCommand command) {
Expand Down Expand Up @@ -104,10 +107,34 @@ public void cancelMemberReservation(long memberId, long reservationId, Reservati
}
if (request.toCancelReservationCommand().reservationStatus() == PENDING_CANCELLATION) {
reservationRepository.pendingCancel(reservationId);
// 문자 여기서 보내야함.
Lesson lesson = lessonRepository.findLessonsById(reservation.getLessonId());
Member member = memberRepository.findById(memberId);
Teacher teacher = lesson.getTeacher();

sendCancelledByStudent(request, teacher, lesson, member);
}
}

private void sendCancelledByStudent(ReservationCancelRequest request, Teacher teacher, Lesson lesson, Member member) {
String to = teacher.getMember().getPhoneNumber();
String instructorName = teacher.getNickname();
String className = lesson.getName();
String studentName = member.getName();
String studentPhone = member.getPhoneNumber();
String bankName = request.bankName();
String refundAccount = request.accountNumber();

messageSender.sendCancelledByStudent(
to,
instructorName,
className,
studentName,
studentPhone,
bankName,
refundAccount
);
}

public ReservationStatisticsResponse getReservationStatistics(Long memberId) {
return new ReservationStatisticsResponse(
reservationRepository.countUpcomingReservationsByMemberId(memberId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import be.dash.dashserver.core.domain.payment.PaymentClientApi;
import be.dash.dashserver.core.domain.reservation.Reservation;
import be.dash.dashserver.core.domain.reservation.command.CreateReservationCommand;
import be.dash.dashserver.core.domain.teacher.Teacher;
import be.dash.dashserver.core.domain.teacher.service.TeacherRepository;
import be.dash.dashserver.core.exception.ConflictException;
import be.dash.dashserver.core.external.MessageSender;
import be.dash.dashserver.core.log.annotation.Trace;
import lombok.RequiredArgsConstructor;

Expand All @@ -30,6 +32,7 @@ public class ReservationService {
private final TeacherRepository teacherRepository;
private final AccountRepository accountRepository;
private final PaymentClientApi paymentClientApi;
private final MessageSender messageSender;

public Reservation findById(long reservationId) {
return reservationRepository.findById(reservationId);
Expand Down Expand Up @@ -68,10 +71,28 @@ public LessonAccount reserve(long memberId, long lessonId) {
Member member = memberRepository.findById(memberId);
reservationRepository.save(member.getId(), lessonId);
Lesson lesson = lessonRepository.findLessonsById(lessonId);
Teacher teacher = lesson.getTeacher();
Account teacherAccount = accountRepository.findByLessonId(lessonId);
sendClassApply(teacher, lesson, member);
return new LessonAccount(lesson, teacherAccount);
}

private void sendClassApply(Teacher teacher, Lesson lesson, Member member) {
String instructorPhone = teacher.getMember().getPhoneNumber();
String instructorName = teacher.getNickname();
String className = lesson.getName();
String studentName = member.getName();
String studentPhone = member.getPhoneNumber();

messageSender.sendClassApply(
instructorPhone,
instructorName,
className,
studentName,
studentPhone
);
}

private void validateReservationAvailability(long memberId, long lessonId) {
validateOwnerIfTeacher(memberId, lessonId);
if (lessonRepository.isFull(lessonId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import be.dash.dashserver.core.exception.DashException;
import be.dash.dashserver.core.exception.ForbiddenException;
import be.dash.dashserver.core.exception.NotFoundException;
import be.dash.dashserver.core.external.MessageSender;
import be.dash.dashserver.core.log.annotation.Trace;
import lombok.RequiredArgsConstructor;

Expand All @@ -55,6 +56,7 @@ public class TeacherService {
private final JwtTokenGenerator jwtTokenGenerator;
private final TeacherVideoRepository teacherVideoRepository;
private final ReservationRepository reservationRepository;
private final MessageSender messageSender;

public List<TeacherLessonGenres> search(Keyword keyword) {
Teachers teachers = teacherRepository.findTeachersSortByLessonCountsDesc(keyword.getValue());
Expand Down Expand Up @@ -206,19 +208,30 @@ public ChangeApproveStatusResponse changeApproveStatus(Long memberId, Long lesso
if (reservation.getReservationStatus() == ReservationStatus.APPROVED) {
return changeStatusToPendingApprove(lessonId, reservationId);
} else if (reservation.getReservationStatus() == ReservationStatus.PENDING_APPROVAL && !lessonRepository.isFull(lessonId)) {
return changeStatusToApprove(lessonId, reservationId);
return changeStatusToApprove(teacher, lesson, reservation);
} else if (reservation.getReservationStatus() == ReservationStatus.PENDING_APPROVAL && lessonRepository.isFull(lessonId)) {
return new ChangeApproveStatusResponse(true);
}
throw new DashException("승인과 관련된 예약 상태를 변경할 수 없습니다.");
}

private ChangeApproveStatusResponse changeStatusToApprove(Long lessonId, Long reservationId) {
reservationRepository.approve(reservationId);
lessonRepository.increaseReservationCount(lessonId);
private ChangeApproveStatusResponse changeStatusToApprove(Teacher teacher, Lesson lesson, Reservation reservation) {
reservationRepository.approve(reservation.getId());
lessonRepository.increaseReservationCount(lesson.getId());
Member member = memberRepository.findById(reservation.getMemberId());
sendClassConfirmed(teacher, lesson, member);

return new ChangeApproveStatusResponse(false);
}

private void sendClassConfirmed(Teacher teacher, Lesson lesson, Member member) {
String to = member.getPhoneNumber();
String studentName = member.getName();
String instructorName = teacher.getNickname();
String className = lesson.getName();
messageSender.sendClassConfirmed(to, studentName, instructorName, className);
}

private ChangeApproveStatusResponse changeStatusToPendingApprove(Long lessonId, Long reservationId) {
reservationRepository.pendingApprove(reservationId);
lessonRepository.decreaseReservationCount(lessonId);
Expand All @@ -235,7 +248,23 @@ public void changeCancelStatus(Long memberId, Long lessonId, Long reservationId)
reservationRepository.pendingCancel(reservationId);
} else if (reservation.getReservationStatus() == ReservationStatus.PENDING_CANCELLATION) {
reservationRepository.cancel(reservationId);
Member member = memberRepository.findById(reservation.getMemberId());
sendCancelDone(member, teacher, lesson);
}
throw new DashException("취소와 관련된 예약 상태를 변경할 수 없습니다.");
}

private void sendCancelDone(Member member, Teacher teacher, Lesson lesson) {
String to = member.getPhoneNumber(); // 수강생 번호
String studentName = member.getName(); // 수강생 이름
String instructorName = teacher.getNickname(); // 강사 이름
String className = lesson.getName(); // 클래스 이름

messageSender.sendCancelDone(
to,
studentName,
instructorName,
className
);
}
}
11 changes: 11 additions & 0 deletions src/main/java/be/dash/dashserver/core/external/MessageSender.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
package be.dash.dashserver.core.external;

public interface MessageSender {

void sendVerification(String to, String content);

void sendClassApply(String to, String instructorName, String className, String studentName, String studentPhone);

void sendClassConfirmed(String to, String studentName, String instructorName, String className);

void sendCancelledBySystem(String to, String studentName, String instructorName, String className);

void sendCancelledByStudent(String to, String instructorName, String className, String studentName, String studentPhone, String bankName, String refundAccount);

void sendCancelDone(String to, String studentName, String instructorName, String className);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package be.dash.dashserver.external.config.sms;

import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "solapi")
public record SolProperties(String apiKey,
String apiSecret,
String baseUrl,
String from,
String verificationTemplate) {
String verificationTemplate,
Map<String, String> templates) {
}
48 changes: 43 additions & 5 deletions src/main/java/be/dash/dashserver/external/sms/SmsSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,53 @@ public class SmsSender implements MessageSender {

@Override
public void sendVerification(String to, String number) {
String text = String.format(properties.verificationTemplate(), number);
sendMessage(to, text);
}

public void sendClassApply(String to, String instructorName, String className, String studentName, String studentPhone) {
String template = properties.templates().get("class-apply");
String text = String.format(template, instructorName, className, studentName, studentPhone);
sendMessage(to, text);
}

public void sendClassConfirmed(String to, String studentName, String instructorName, String className) {
String template = properties.templates().get("class-confirmed");
String text = String.format(template, studentName, instructorName, className);
sendMessage(to, text);
}

public void sendCancelledBySystem(String to, String studentName, String instructorName, String className) {
String template = properties.templates().get("class-cancelled-by-system");
String text = String.format(template, studentName, instructorName, className);
sendMessage(to, text);
}

public void sendCancelledByStudent(String to, String instructorName, String className, String studentName, String studentPhone, String bankName, String refundAccount) {
String template = properties.templates().get("class-cancelled-by-student");
String text = String.format(template, instructorName, className, studentName, studentPhone, bankName, refundAccount);
sendMessage(to, text);
}

public void sendCancelDone(String to, String studentName, String instructorName, String className) {
String template = properties.templates().get("class-cancel-done");
String text = String.format(template, studentName, instructorName, className);
sendMessage(to, text);
}

private void sendMessage(String to, String text) {
Message message = new Message();
message.setFrom(properties.from());
message.setTo(to);
message.setText(String.format(properties.verificationTemplate(), number));
message.setFrom(properties.from());
message.setTo(to);
message.setText(text);

try {
messageService.send(message);
} catch (NurigoMessageNotReceivedException exception) {
} catch (NurigoMessageNotReceivedException e) {
log.error("Business SMS send failure: {}", e.getMessage());
throw SmsException.failBusiness();
} catch (Exception exception) {
} catch (Exception e) {
log.error("Transient SMS send failure: {}", e.getMessage());
throw SmsException.failTransient();
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,9 @@ solapi:
base-url: https://api.solapi.com
from: ${SOLAPI_SENDER_PHONE}
verification-template: ${SOLAPI_VERIFICATION_TEMPLATE}


templates:
class-apply: "[TEST] %s님의 %s 클래스에 신청자 %s (%s)가 신청했습니다."
class-confirmed: "[TEST] %s님, %s 강사의 %s 수강이 확정되었습니다."
class-cancelled-by-system: "[TEST] %s님, %s 강사의 %s 신청이 자동 취소되었습니다."
class-cancelled-by-student: "[TEST] %s님, %s 클래스 수강생 %s (%s)가 환불 요청 (%s / %s)을 보냈습니다."
class-cancel-done: "[TEST] %s님, %s 강사가 %s 신청을 취소 완료 처리했습니다. 환불 계좌: %s"
7 changes: 6 additions & 1 deletion src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ solapi:
base-url: https://api.base.com
from: 01000000000
verification-template: "template"

templates:
class-apply: "[TEST] %s님의 %s 클래스에 신청자 %s (%s)가 신청했습니다."
class-confirmed: "[TEST] %s님, %s 강사의 %s 수강이 확정되었습니다."
class-cancelled-by-system: "[TEST] %s님, %s 강사의 %s 신청이 자동 취소되었습니다."
class-cancelled-by-student: "[TEST] %s님, %s 클래스 수강생 %s (%s)가 환불 요청 (%s / %s)을 보냈습니다."
class-cancel-done: "[TEST] %s님, %s 강사가 %s 신청을 취소 완료 처리했습니다. 환불 계좌: %s"