Skip to content

Commit

Permalink
Fix: 환불하는데 돈이 오히려 차감되던 버그 수정과 시니어 등록, 수정 시 폰 번호 중복 확인 로직 추가 (#166)
Browse files Browse the repository at this point in the history
* fix: 환불하는데 돈이 오히려 차감되던 버그 수정

* feat: 시니어 등록, 수정 시 폰 번호 중복 확인 로직 추가

* remove: 안부전화 수정 api 제거
  • Loading branch information
zzoe2346 authored Nov 6, 2024
1 parent 1f20e6b commit c6a0c0d
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ public interface SeniorRepository extends JpaRepository<Senior, Long> {
Optional<Senior> findByPhoneNumber(String phoneNumber);

List<Senior> findAllByMember(Member member);

boolean existsByPhoneNumber(String phoneNumber);
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public void createSenior(Long memberId, SeniorRequest seniorRequest) {
);
if (member.isSinitto()) throw new BadRequestException("보호자만 이용할 수 있습니다.");

if(seniorRepository.existsByPhoneNumber(seniorRequest.seniorPhoneNumber())) {
throw new BadRequestException("이미 등록되어 있는 전화번호 입니다.");
}

Senior senior = new Senior(seniorRequest.seniorName(), seniorRequest.seniorPhoneNumber(), member);

seniorRepository.save(senior);
Expand Down Expand Up @@ -86,6 +90,10 @@ public void updateSenior(Long memberId, Long seniorId, SeniorRequest seniorReque
() -> new NotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.")
);

if(seniorRepository.existsByPhoneNumber(seniorRequest.seniorPhoneNumber())) {
throw new BadRequestException("이미 등록되어 있는 전화번호 입니다.");
}

senior.updateSenior(seniorRequest.seniorName(), seniorRequest.seniorPhoneNumber());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,6 @@ public ResponseEntity<StringMessageResponse> createHelloCallByGuard(@MemberId Lo
return ResponseEntity.ok(new StringMessageResponse("안부 전화 서비스가 신청되었습니다."));
}

@Operation(summary = "[보호자용] 안부 전화 서비스 수정하기", description = "보호자가 안부 전화 서비스 내용을 수정합니다.")
@PutMapping("/guards/{callId}")
public ResponseEntity<StringMessageResponse> updateHelloCallByGuard(@MemberId Long memberId, @PathVariable Long callId, @RequestBody HelloCallDetailUpdateRequest helloCallDetailUpdateRequest) {

helloCallService.updateHelloCallByGuard(memberId, callId, helloCallDetailUpdateRequest);

return ResponseEntity.ok(new StringMessageResponse("안부 전화 서비스 내용이 수정되었습니다."));
}

@Operation(summary = "[보호자용] 안부 전화 서비스 삭제하기", description = "보호자가 안부 전화 서비스 신청을 취소합니다.")
@DeleteMapping("/guards/{callId}")
public ResponseEntity<StringMessageResponse> deleteHelloCallByGuard(@MemberId Long memberId, @PathVariable Long callId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,33 +122,6 @@ public HelloCallDetailResponse readHelloCallDetail(Long helloCallId) {
helloCall.getSenior().getPhoneNumber(), helloCall.getPrice(), helloCall.getServiceTime());
}

@Transactional
public void updateHelloCallByGuard(Long memberId, Long helloCallId, HelloCallDetailUpdateRequest helloCallDetailUpdateRequest) {
HelloCall helloCall = helloCallRepository.findById(helloCallId)
.orElseThrow(() -> new NotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다."));

Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new NotFoundException("id에 해당하는 멤버를 찾을 수 없습니다."));

helloCall.checkGuardIsCorrect(member);

helloCall.updateHelloCall(helloCallDetailUpdateRequest.startDate(), helloCallDetailUpdateRequest.endDate(),
helloCallDetailUpdateRequest.price(), helloCallDetailUpdateRequest.serviceTime(), helloCallDetailUpdateRequest.requirement());

updateTimeSlots(helloCall, helloCallDetailUpdateRequest.timeSlots());
}

private void updateTimeSlots(HelloCall helloCall, List<HelloCallDetailUpdateRequest.TimeSlot> updatedTimeSlots) {
timeSlotRepository.deleteAllByHelloCall(helloCall);
helloCall.getTimeSlots().clear();

for (HelloCallDetailUpdateRequest.TimeSlot updatedSlot : updatedTimeSlots) {
TimeSlot newTimeSlot = new TimeSlot(updatedSlot.dayName(), updatedSlot.startTime(), updatedSlot.endTime(), helloCall);
timeSlotRepository.save(newTimeSlot);
helloCall.getTimeSlots().add(newTimeSlot);
}
}

@Transactional
public void deleteHellCallByGuard(Long memberId, Long helloCallId) {
HelloCall helloCall = helloCallRepository.findById(helloCallId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public void refundPointByDelete(Long memberId, int price, PointLog.Content conte
throw new BadRequestException("포인트가 부족합니다.");
}

point.deduct(price);
point.earn(price);

pointLogRepository.save(
new PointLog(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ void createSeniorTestWhenSinittoDoThis() {
assertThrows(BadRequestException.class, () -> guardService.createSenior(memberId, seniorRequest));
}

@Test
@DisplayName("createSenior 테스트 - 이미 등록된 번호로 시니어 생성하면 예외를 발생시켜야한다.")
void createSeniorTestFailWhenDuplicatedPhoneNumber() {
// Given
Long memberId = 1L;
Member member = new Member("testName", "01012345678", "[email protected]", false);
SeniorRequest seniorRequest = new SeniorRequest("testSeniorName", "01011111111");
when(memberRepository.findById(memberId)).thenReturn(Optional.of(member));
when(seniorRepository.existsByPhoneNumber("01011111111")).thenReturn(true);

// When, Then
assertThrows(BadRequestException.class, () -> guardService.createSenior(memberId, seniorRequest));
}

@Test
@DisplayName("readSeniors 메소드 테스트")
void readSeniorsTest() {
Expand Down Expand Up @@ -177,6 +191,22 @@ void updateSeniorTest() {
verify(senior, times(1)).updateSenior(request.seniorName(), request.seniorPhoneNumber());
}

@Test
@DisplayName("updateSenior 메소드 테스트 - 이미 등록된 번호로 수정시 예외가 발생해야한다.")
void updateSeniorTestFailWhenDuplicatedPhoneNumber() {
//given
Long memberId = 1L;
Long seniorId = 2L;
Member member = new Member("testName", "01012345678", "[email protected]", true);
Senior senior = mock(Senior.class);
SeniorRequest request = new SeniorRequest("newSeniorName", "01011111111");

when(seniorRepository.findByIdAndMemberId(seniorId, memberId)).thenReturn(Optional.of(senior));
when(seniorRepository.existsByPhoneNumber("01011111111")).thenReturn(true);
//when then
assertThrows(BadRequestException.class, () -> guardService.updateSenior(memberId, seniorId, request));
}

@Test
@DisplayName("deleteSenior 메소드 테스트")
void deleteSeniorTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,42 +192,6 @@ void readHelloCallDetailWhenHelloCallIsNotExist() {
assertThrows(NotFoundException.class, () -> helloCallService.readHelloCallDetail(helloCallId));
}

@Test
@DisplayName("updateHelloCallByGuard 메소드 테스트 - HelloCall이 없을 때")
void updateHelloCallByGuardTestWhenHelloCallIsNotExist() {
//given
Long memberId = 1L;
Long helloCallId = 2L;
List<HelloCallDetailUpdateRequest.TimeSlot> timeSlots = new ArrayList<>();
timeSlots.add(new HelloCallDetailUpdateRequest.TimeSlot("월", LocalTime.now(), LocalTime.now().plusHours(2)));
HelloCallDetailUpdateRequest helloCallDetailUpdateRequest = new HelloCallDetailUpdateRequest(LocalDate.now(), LocalDate.now().plusDays(7), timeSlots, 1000, 10, "testRequirement");

when(helloCallRepository.findById(helloCallId)).thenReturn(Optional.empty());

//when, then
assertThrows(NotFoundException.class, () -> helloCallService.updateHelloCallByGuard(memberId, helloCallId, helloCallDetailUpdateRequest));
}

@Test
@DisplayName("updateHelloCallByGuard 메소드 테스트 - member가 없을 때")
void updateHelloCallByGuardTestWhenMemberIsNotExist() {
//given
Member member = mock(Member.class);
Long memberId = 1L;
Senior senior = new Senior("testSeniorName", "01012345678", member);
Long helloCallId = 2L;
List<HelloCallDetailUpdateRequest.TimeSlot> timeSlots = new ArrayList<>();
timeSlots.add(new HelloCallDetailUpdateRequest.TimeSlot("월", LocalTime.now(), LocalTime.now().plusHours(2)));
HelloCallDetailUpdateRequest helloCallDetailUpdateRequest = new HelloCallDetailUpdateRequest(LocalDate.now(), LocalDate.now().plusDays(7), timeSlots, 1000, 10, "testRequirement");
HelloCall helloCall = new HelloCall(LocalDate.now(), LocalDate.now().plusDays(7), 500, 10, "testRequirement", senior);

when(helloCallRepository.findById(helloCallId)).thenReturn(Optional.of(helloCall));
when(memberRepository.findById(memberId)).thenReturn(Optional.empty());

//when, then
assertThrows(NotFoundException.class, () -> helloCallService.updateHelloCallByGuard(memberId, helloCallId, helloCallDetailUpdateRequest));
}

@Test
@DisplayName("deleteHellCallByGuard 메소드 테스트")
void deleteHellCallByGuardTest() {
Expand Down
120 changes: 120 additions & 0 deletions src/test/java/com/example/sinitto/point/service/PointServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,124 @@ void savePointWithdrawRequest4() {
assertThrows(BadRequestException.class, () -> pointService.savePointWithdrawRequest(1L, 10000));
}
}

@Nested
@DisplayName("포인트 적립 테스트")
class EarnPointTest {
@Test
@DisplayName("포인트 적립 성공한다.")
void earnPoint1() {
//given
Point point = mock(Point.class);
when(pointRepository.findByMemberId(1L)).thenReturn(Optional.of(point));

//when
pointService.earnPoint(1L, 10000, PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN);

//then
verify(point).earn(10000);
verify(pointLogRepository).save(any(PointLog.class));
}

@Test
@DisplayName("멤버에 연관된 포인트가 없으면 예외를 발생시켜야한다.")
void earnPoint2() {
//given
when(pointRepository.findByMemberId(1L)).thenReturn(Optional.empty());


//when then
assertThrows(NotFoundException.class, () -> pointService.earnPoint(1L, 10000, PointLog.Content.COMPLETE_CALLBACK_AND_EARN));
}
}

@Nested
@DisplayName("포인트 차감 테스트")
class DeductPointTest {

@Test
@DisplayName("포인트 차감 성공한다.")
void deductPoint1() {
//given
Point point = mock(Point.class);
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.of(point));
when(point.isSufficientForDeduction(10000)).thenReturn(true);

//when
pointService.deductPoint(1L, 10000, PointLog.Content.SPEND_COMPLETE_CALLBACK);

//then
verify(point).deduct(10000);
verify(pointLogRepository).save(any(PointLog.class));
}

@Test
@DisplayName("멤버에 연관된 포인트가 없으면 예외를 발생시켜야한다.")
void deductPoint2() {
//given
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.empty());

//when then

assertThrows(NotFoundException.class, () -> pointService.deductPoint(1L, 10000, PointLog.Content.SPEND_COMPLETE_CALLBACK));
}

@Test
@DisplayName("포인트가 부족하면 예외를 발생시켜야한다.")
void deductPoint3() {

//given
Point point = mock(Point.class);
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.of(point));
when(point.isSufficientForDeduction(10000)).thenReturn(false);

//when then
assertThrows(BadRequestException.class, () -> pointService.deductPoint(1L, 10000, PointLog.Content.SPEND_COMPLETE_HELLO_CALL));
}
}

@Nested
@DisplayName("포인트 환불 테스트")
class RefundPointByDeleteTest {

@Test
@DisplayName("포인트 환불 성공한다. 성공하면 포인트가 되돌아 온다(적립)")
void refundPointByDelete1() {
//given
Point point = mock(Point.class);
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.of(point));
when(point.isSufficientForDeduction(10000)).thenReturn(true);

//when
pointService.refundPointByDelete(1L, 10000, PointLog.Content.SPEND_CANCEL_HELLO_CALL);

//then
verify(point).earn(10000);
verify(pointLogRepository).save(any(PointLog.class));
}


@Test
@DisplayName("멤버에 연관된 포인트가 없으면 예외를 발생시켜야한다.")
void refundPointByDelete2() {
//given
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.empty());

//when then
assertThrows(NotFoundException.class, () -> pointService.refundPointByDelete(1L, 10000, PointLog.Content.SPEND_CANCEL_HELLO_CALL));
}

@Test
@DisplayName("포인트가 부족하면 예외를 발생시켜야한다.")
void refundPointByDelete3() {
//given
Point point = mock(Point.class);
when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.of(point));
when(point.isSufficientForDeduction(10000)).thenReturn(false);

//when then
assertThrows(BadRequestException.class, () -> pointService.refundPointByDelete(1L, 10000, PointLog.Content.SPEND_CANCEL_HELLO_CALL));
}
}

}

0 comments on commit c6a0c0d

Please sign in to comment.