diff --git a/build.gradle b/build.gradle index e808707a..ad5c49cc 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,8 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2' implementation group: 'com.twilio.sdk', name: 'twilio', version: '10.5.0' implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1' } tasks.named('test') { diff --git a/src/main/java/com/example/sinitto/SinittoApplication.java b/src/main/java/com/example/sinitto/SinittoApplication.java index 36245d70..58305608 100644 --- a/src/main/java/com/example/sinitto/SinittoApplication.java +++ b/src/main/java/com/example/sinitto/SinittoApplication.java @@ -5,10 +5,12 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableJpaAuditing @EnableConfigurationProperties(KakaoProperties.class) +@EnableScheduling public class SinittoApplication { public static void main(String[] args) { diff --git a/src/main/java/com/example/sinitto/auth/dto/KakaoTokenResponse.java b/src/main/java/com/example/sinitto/auth/dto/KakaoTokenResponse.java index 0cd57add..091329c9 100644 --- a/src/main/java/com/example/sinitto/auth/dto/KakaoTokenResponse.java +++ b/src/main/java/com/example/sinitto/auth/dto/KakaoTokenResponse.java @@ -3,12 +3,15 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import jakarta.validation.constraints.NotNull; @JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) public record KakaoTokenResponse( String accessToken, String refreshToken, + @NotNull int expiresIn, + @NotNull int refreshTokenExpiresIn ) { diff --git a/src/main/java/com/example/sinitto/callback/controller/CallbackController.java b/src/main/java/com/example/sinitto/callback/controller/CallbackController.java index e99cb5c2..13dc1ab5 100644 --- a/src/main/java/com/example/sinitto/callback/controller/CallbackController.java +++ b/src/main/java/com/example/sinitto/callback/controller/CallbackController.java @@ -1,6 +1,7 @@ package com.example.sinitto.callback.controller; import com.example.sinitto.callback.dto.CallbackResponse; +import com.example.sinitto.callback.dto.CallbackUsageHistoryResponse; import com.example.sinitto.callback.service.CallbackService; import com.example.sinitto.common.annotation.MemberId; import io.swagger.v3.oas.annotations.Operation; @@ -25,10 +26,10 @@ public CallbackController(CallbackService callbackService) { @Operation(summary = "콜백 전화 리스트 보기(페이지)", description = "시니어가 요청한 콜백전화를 페이징으로 보여줍니다.") @GetMapping - public ResponseEntity> getCallbackList(@MemberId Long memberId, - @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { + public ResponseEntity> getWaitingCallbackList(@MemberId Long memberId, + @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { - return ResponseEntity.ok(callbackService.getCallbacks(memberId, pageable)); + return ResponseEntity.ok(callbackService.getWaitingCallbacks(memberId, pageable)); } @Operation(summary = "진행 상태인 콜백을 완료 대기 상태로 전환(시니또가)", description = "시니또가 수락한 콜백 수행을 완료했을때 이 api 호출하면 완료 대기 상태로 변합니다.") @@ -36,7 +37,7 @@ public ResponseEntity> getCallbackList(@MemberId Long mem public ResponseEntity pendingCompleteCallback(@MemberId Long memberId, @PathVariable Long callbackId) { - callbackService.pendingComplete(memberId, callbackId); + callbackService.changeCallbackStatusToPendingCompleteBySinitto(memberId, callbackId); return ResponseEntity.ok().build(); } @@ -45,7 +46,7 @@ public ResponseEntity pendingCompleteCallback(@MemberId Long memberId, public ResponseEntity completeCallback(@MemberId Long memberId, @PathVariable Long callbackId) { - callbackService.complete(memberId, callbackId); + callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId); return ResponseEntity.ok().build(); } @@ -54,7 +55,7 @@ public ResponseEntity completeCallback(@MemberId Long memberId, public ResponseEntity acceptCallback(@MemberId Long memberId, @PathVariable Long callbackId) { - callbackService.accept(memberId, callbackId); + callbackService.acceptCallbackBySinitto(memberId, callbackId); return ResponseEntity.ok().build(); } @@ -63,14 +64,14 @@ public ResponseEntity acceptCallback(@MemberId Long memberId, public ResponseEntity cancelCallback(@MemberId Long memberId, @PathVariable Long callbackId) { - callbackService.cancel(memberId, callbackId); + callbackService.cancelCallbackAssignmentBySinitto(memberId, callbackId); return ResponseEntity.ok().build(); } @PostMapping("/twilio") public ResponseEntity addCallCheck(@RequestParam("From") String fromNumber) { - return ResponseEntity.ok(callbackService.add(fromNumber)); + return ResponseEntity.ok(callbackService.createCallbackByCall(fromNumber)); } @Operation(summary = "시니또에게 현재 할당된 콜백 조회", description = "현재 시니또 본인에게 할당된 콜백을 조회합니다.") @@ -79,4 +80,20 @@ public ResponseEntity getAcceptedCallback(@MemberId Long membe return ResponseEntity.ok(callbackService.getAcceptedCallback(memberId)); } + + @Operation(summary = "보호자의 콜백 이용 내역 조회", description = "보호자에게 연관된 모든 콜백 내역을 조회합니다. 기본적으로 최신 내역 부터 조회됩니다.") + @GetMapping("/guard/requested") + public ResponseEntity> getAcceptedCallback(@MemberId Long memberId, + @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { + + return ResponseEntity.ok(callbackService.getCallbackHistoryOfGuard(memberId, pageable)); + } + + @Operation(summary = "콜백 단건 조회", description = "콜백 id 로 콜백을 단건 조회합니다.") + @GetMapping("/{callbackId}") + public ResponseEntity getCallback(@PathVariable("callbackId") Long callbackId) { + + return ResponseEntity.ok(callbackService.getCallback(callbackId)); + } + } diff --git a/src/main/java/com/example/sinitto/callback/dto/CallbackUsageHistoryResponse.java b/src/main/java/com/example/sinitto/callback/dto/CallbackUsageHistoryResponse.java new file mode 100644 index 00000000..a13d6509 --- /dev/null +++ b/src/main/java/com/example/sinitto/callback/dto/CallbackUsageHistoryResponse.java @@ -0,0 +1,11 @@ +package com.example.sinitto.callback.dto; + +import java.time.LocalDateTime; + +public record CallbackUsageHistoryResponse( + Long callbackId, + String seniorName, + LocalDateTime postTime, + String status +) { +} diff --git a/src/main/java/com/example/sinitto/callback/entity/Callback.java b/src/main/java/com/example/sinitto/callback/entity/Callback.java index c9425f57..89f67932 100644 --- a/src/main/java/com/example/sinitto/callback/entity/Callback.java +++ b/src/main/java/com/example/sinitto/callback/entity/Callback.java @@ -23,6 +23,7 @@ public class Callback { private Long id; @CreatedDate private LocalDateTime postTime; + private LocalDateTime pendingCompleteTime; @NotNull @Enumerated(EnumType.STRING) private Callback.Status status; @@ -140,6 +141,14 @@ public Long getAssignedMemberId() { return assignedMemberId; } + public LocalDateTime getPendingCompleteTime() { + return pendingCompleteTime; + } + + public void setPendingCompleteTime(LocalDateTime pendingCompleteTime) { + this.pendingCompleteTime = pendingCompleteTime; + } + public enum Status { WAITING, IN_PROGRESS, diff --git a/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java b/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java new file mode 100644 index 00000000..77f44b55 --- /dev/null +++ b/src/main/java/com/example/sinitto/callback/exception/MemberHasInProgressCallbackException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.callback.exception; + +public class MemberHasInProgressCallbackException extends ConflictException { + + public MemberHasInProgressCallbackException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/callback/repository/CallbackRepository.java b/src/main/java/com/example/sinitto/callback/repository/CallbackRepository.java index b34aa1cb..6d8be931 100644 --- a/src/main/java/com/example/sinitto/callback/repository/CallbackRepository.java +++ b/src/main/java/com/example/sinitto/callback/repository/CallbackRepository.java @@ -1,15 +1,26 @@ package com.example.sinitto.callback.repository; import com.example.sinitto.callback.entity.Callback; +import com.example.sinitto.member.entity.Senior; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; public interface CallbackRepository extends JpaRepository { - Page findAll(Pageable pageable); + Page findAllByStatus(Callback.Status status, Pageable pageable); Optional findByAssignedMemberIdAndStatus(Long memberId, Callback.Status status); + + boolean existsByAssignedMemberIdAndStatus(Long memberId, Callback.Status status); + + Page findAllBySeniorIn(List seniors, Pageable pageable); + + List findAllByStatusAndPendingCompleteTimeBefore(Callback.Status status, LocalDateTime dateTime); + + boolean existsBySeniorAndStatusIn(Senior senior, List statuses); } diff --git a/src/main/java/com/example/sinitto/callback/service/CallbackService.java b/src/main/java/com/example/sinitto/callback/service/CallbackService.java index ffced311..300cbc93 100644 --- a/src/main/java/com/example/sinitto/callback/service/CallbackService.java +++ b/src/main/java/com/example/sinitto/callback/service/CallbackService.java @@ -1,6 +1,7 @@ package com.example.sinitto.callback.service; import com.example.sinitto.callback.dto.CallbackResponse; +import com.example.sinitto.callback.dto.CallbackUsageHistoryResponse; import com.example.sinitto.callback.entity.Callback; import com.example.sinitto.callback.exception.*; import com.example.sinitto.callback.repository.CallbackRepository; @@ -9,42 +10,61 @@ import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.exception.PointNotFoundException; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; +import java.time.LocalDateTime; +import java.util.List; @Service public class CallbackService { + private static final int CALLBACK_PRICE = 1500; + private static final int DAYS_FOR_AUTO_COMPLETE = 2; private static final String SUCCESS_MESSAGE = "감사합니다. 잠시만 기다려주세요."; - private static final String FAIL_MESSAGE = "등록된 사용자가 아닙니다. 서비스 이용이 불가합니다."; + private static final String FAIL_MESSAGE_NOT_ENROLLED = "등록된 사용자가 아닙니다. 서비스 이용이 불가합니다."; + private static final String FAIL_MESSAGE_NOT_ENOUGH_POINT = "포인트가 부족합니다. 서비스 이용이 불가합니다."; + private static final String FAIL_MESSAGE_ALREADY_HAS_CALLBACK_IN_PROGRESS_OR_WAITING = "어르신의 요청이 이미 접수되었습니다. 잠시 기다려주시면 연락드리겠습니다."; private final CallbackRepository callbackRepository; private final MemberRepository memberRepository; private final SeniorRepository seniorRepository; + private final PointRepository pointRepository; + private final PointLogRepository pointLogRepository; - public CallbackService(CallbackRepository callbackRepository, MemberRepository memberRepository, SeniorRepository seniorRepository) { + public CallbackService(CallbackRepository callbackRepository, MemberRepository memberRepository, SeniorRepository seniorRepository, PointRepository pointRepository, PointLogRepository pointLogRepository) { this.callbackRepository = callbackRepository; this.memberRepository = memberRepository; this.seniorRepository = seniorRepository; + this.pointRepository = pointRepository; + this.pointLogRepository = pointLogRepository; } @Transactional(readOnly = true) - public Page getCallbacks(Long memberId, Pageable pageable) { + public Page getWaitingCallbacks(Long memberId, Pageable pageable) { checkAuthorization(memberId); - return callbackRepository.findAll(pageable) + return callbackRepository.findAllByStatus(Callback.Status.WAITING, pageable) .map((callback) -> new CallbackResponse(callback.getId(), callback.getSeniorName(), callback.getPostTime(), callback.getStatus(), callback.getSeniorId())); } @Transactional - public void accept(Long memberId, Long callbackId) { + public void acceptCallbackBySinitto(Long memberId, Long callbackId) { checkAuthorization(memberId); + if (callbackRepository.existsByAssignedMemberIdAndStatus(memberId, Callback.Status.IN_PROGRESS)) { + throw new MemberHasInProgressCallbackException("이 요청을 한 시니또는 이미 진행중인 콜백이 있습니다."); + } + Callback callback = getCallbackOrThrow(callbackId); callback.assignMember(memberId); @@ -52,7 +72,7 @@ public void accept(Long memberId, Long callbackId) { } @Transactional - public void pendingComplete(Long memberId, Long callbackId) { + public void changeCallbackStatusToPendingCompleteBySinitto(Long memberId, Long callbackId) { checkAuthorization(memberId); @@ -61,10 +81,11 @@ public void pendingComplete(Long memberId, Long callbackId) { checkAssignment(memberId, callback.getAssignedMemberId()); callback.changeStatusToPendingComplete(); + callback.setPendingCompleteTime(LocalDateTime.now()); } @Transactional - public void complete(Long memberId, Long callbackId) { + public void changeCallbackStatusToCompleteByGuard(Long memberId, Long callbackId) { Callback callback = getCallbackOrThrow(callbackId); @@ -75,11 +96,37 @@ public void complete(Long memberId, Long callbackId) { throw new GuardMismatchException("이 API를 요청한 보호자는 이 콜백을 요청 한 시니어의 보호자가 아닙니다."); } + earnPointForSinitto(callback.getAssignedMemberId()); callback.changeStatusToComplete(); } + private void earnPointForSinitto(Long sinittoMemberId) { + + Point sinittoPoint = pointRepository.findByMemberId(sinittoMemberId) + .orElseThrow(() -> new PointNotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); + + sinittoPoint.earn(CALLBACK_PRICE); + + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), sinittoPoint.getMember(), CALLBACK_PRICE, PointLog.Status.EARN)); + } + + @Scheduled(cron = "0 */10 * * * *") + @Transactional + public void changeOldPendingCompleteToCompleteByPolicy() { + + LocalDateTime referenceDateTimeForComplete = LocalDateTime.now().minusDays(DAYS_FOR_AUTO_COMPLETE); + + List callbacks = callbackRepository.findAllByStatusAndPendingCompleteTimeBefore(Callback.Status.PENDING_COMPLETE, referenceDateTimeForComplete); + + for (Callback callback : callbacks) { + + earnPointForSinitto(callback.getAssignedMemberId()); + callback.changeStatusToComplete(); + } + } + @Transactional - public void cancel(Long memberId, Long callbackId) { + public void cancelCallbackAssignmentBySinitto(Long memberId, Long callbackId) { checkAuthorization(memberId); @@ -91,22 +138,49 @@ public void cancel(Long memberId, Long callbackId) { callback.changeStatusToWaiting(); } - public String add(String fromNumber) { + @Transactional + public String createCallbackByCall(String fromNumber) { String phoneNumber = TwilioHelper.trimPhoneNumber(fromNumber); - Optional seniorOptional = seniorRepository.findByPhoneNumber(phoneNumber); + Senior senior = findSeniorByPhoneNumber(phoneNumber); + if (senior == null) { + return TwilioHelper.convertMessageToTwiML(FAIL_MESSAGE_NOT_ENROLLED); + } - if (seniorOptional.isEmpty()) { - return TwilioHelper.convertMessageToTwiML(FAIL_MESSAGE); + Point point = findPointWithWriteLock(senior.getMember().getId()); + if (point == null || !point.isSufficientForDeduction(CALLBACK_PRICE)) { + return TwilioHelper.convertMessageToTwiML(FAIL_MESSAGE_NOT_ENOUGH_POINT); } - Senior senior = seniorOptional.get(); + if (callbackRepository.existsBySeniorAndStatusIn(senior, List.of(Callback.Status.WAITING, Callback.Status.IN_PROGRESS))) { + return TwilioHelper.convertMessageToTwiML(FAIL_MESSAGE_ALREADY_HAS_CALLBACK_IN_PROGRESS_OR_WAITING); + } + + point.deduct(CALLBACK_PRICE); + + pointLogRepository.save( + new PointLog( + PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), + senior.getMember(), + CALLBACK_PRICE, + PointLog.Status.SPEND_COMPLETE) + ); callbackRepository.save(new Callback(Callback.Status.WAITING, senior)); return TwilioHelper.convertMessageToTwiML(SUCCESS_MESSAGE); } + private Senior findSeniorByPhoneNumber(String phoneNumber) { + return seniorRepository.findByPhoneNumber(phoneNumber) + .orElse(null); + } + + private Point findPointWithWriteLock(Long memberId) { + return pointRepository.findByMemberIdWithWriteLock(memberId) + .orElse(null); + } + public CallbackResponse getAcceptedCallback(Long memberId) { checkAuthorization(memberId); @@ -139,4 +213,26 @@ private void checkAssignment(Long memberId, Long assignedMemberId) { throw new NotAssignedException("이 콜백에 할당된 시니또가 아닙니다"); } } + + @Transactional(readOnly = true) + public Page getCallbackHistoryOfGuard(Long memberId, Pageable pageable) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new NotMemberException("멤버가 아닙니다")); + + List seniors = seniorRepository.findAllByMember(member); + + + return callbackRepository.findAllBySeniorIn(seniors, pageable) + .map(callback -> new CallbackUsageHistoryResponse(callback.getId(), callback.getSeniorName(), callback.getPostTime(), callback.getStatus())); + } + + public CallbackResponse getCallback(Long callbackId) { + + Callback callback = callbackRepository.findById(callbackId) + .orElseThrow(() -> new NotExistCallbackException("해당 콜백 id에 해당하는 콜백이 없습니다.")); + + return new CallbackResponse(callback.getId(), callback.getSeniorName(), callback.getPostTime(), callback.getStatus(), callback.getSeniorId()); + } + } diff --git a/src/main/java/com/example/sinitto/common/config/WebConfig.java b/src/main/java/com/example/sinitto/common/config/WebConfig.java index 0e024405..8cc90f76 100644 --- a/src/main/java/com/example/sinitto/common/config/WebConfig.java +++ b/src/main/java/com/example/sinitto/common/config/WebConfig.java @@ -1,8 +1,14 @@ package com.example.sinitto.common.config; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.core5.util.Timeout; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; @@ -15,16 +21,34 @@ public class WebConfig implements WebMvcConfigurer { private static final int TIME_OUT_DURATION = 5; + private static final int MAX_OPEN_CONNECTIONS = 100; + private static final int CONNECTIONS_PER_IP_PORT_PAIR = 5; @Bean public RestTemplate restTemplate(RestTemplateBuilder builder, RestTemplateResponseErrorHandler errorHandler) { return builder .errorHandler(errorHandler) - .setConnectTimeout(Duration.ofSeconds(TIME_OUT_DURATION)) - .setReadTimeout(Duration.ofSeconds(TIME_OUT_DURATION)) + .requestFactory(this::httpComponentsClientHttpRequestFactory) .build(); } + private HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() { + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); + connectionManager.setMaxTotal(MAX_OPEN_CONNECTIONS); + connectionManager.setDefaultMaxPerRoute(CONNECTIONS_PER_IP_PORT_PAIR); + + CloseableHttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(RequestConfig.custom() + .setResponseTimeout(Timeout.of(Duration.ofSeconds(TIME_OUT_DURATION))) + .setConnectTimeout(Timeout.of(Duration.ofSeconds(TIME_OUT_DURATION))) + .setConnectionRequestTimeout(Timeout.of(Duration.ofSeconds(TIME_OUT_DURATION))) + .build()) + .build(); + + return new HttpComponentsClientHttpRequestFactory(httpClient); + } + @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); diff --git a/src/main/java/com/example/sinitto/common/dummy/InitialData.java b/src/main/java/com/example/sinitto/common/dummy/InitialData.java new file mode 100644 index 00000000..3a19edff --- /dev/null +++ b/src/main/java/com/example/sinitto/common/dummy/InitialData.java @@ -0,0 +1,559 @@ +package com.example.sinitto.common.dummy; + +import com.example.sinitto.auth.service.TokenService; +import com.example.sinitto.callback.entity.Callback; +import com.example.sinitto.callback.repository.CallbackRepository; +import com.example.sinitto.guard.repository.SeniorRepository; +import com.example.sinitto.guardGuideline.entity.GuardGuideline; +import com.example.sinitto.guardGuideline.repository.GuardGuidelineRepository; +import com.example.sinitto.helloCall.entity.HelloCall; +import com.example.sinitto.helloCall.entity.HelloCallTimeLog; +import com.example.sinitto.helloCall.entity.TimeSlot; +import com.example.sinitto.helloCall.repository.HelloCallRepository; +import com.example.sinitto.helloCall.repository.HelloCallTimeLogRepository; +import com.example.sinitto.helloCall.repository.TimeSlotRepository; +import com.example.sinitto.helloCall.service.HelloCallService; +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.entity.Senior; +import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; +import com.example.sinitto.review.entity.Review; +import com.example.sinitto.review.repository.ReviewRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +@Component +public class InitialData implements CommandLineRunner { + + private final MemberRepository memberRepository; + private final SeniorRepository seniorRepository; + private final PointRepository pointRepository; + private final CallbackRepository callbackRepository; + private final SinittoBankInfoRepository sinittoBankInfoRepository; + private final PointLogRepository pointLogRepository; + private final ReviewRepository reviewRepository; + private final GuardGuidelineRepository guardGuidelineRepository; + private final HelloCallRepository helloCallRepository; + private final TimeSlotRepository timeSlotRepository; + private final HelloCallTimeLogRepository helloCallTimeLogRepository; + private final TokenService tokenService; + private final HelloCallService helloCallService; + + + public InitialData(MemberRepository memberRepository, SeniorRepository seniorRepository, + PointRepository pointRepository, CallbackRepository callbackRepository, + SinittoBankInfoRepository sinittoBankInfoRepository, PointLogRepository pointLogRepository, + ReviewRepository reviewRepository, GuardGuidelineRepository guardGuidelineRepository, + HelloCallRepository helloCallRepository, TimeSlotRepository timeSlotRepository, + HelloCallTimeLogRepository helloCallTimeLogRepository, TokenService tokenService, HelloCallService helloCallService) { + this.memberRepository = memberRepository; + this.seniorRepository = seniorRepository; + this.pointRepository = pointRepository; + this.callbackRepository = callbackRepository; + this.sinittoBankInfoRepository = sinittoBankInfoRepository; + this.pointLogRepository = pointLogRepository; + this.reviewRepository = reviewRepository; + this.guardGuidelineRepository = guardGuidelineRepository; + this.helloCallRepository = helloCallRepository; + this.timeSlotRepository = timeSlotRepository; + this.helloCallTimeLogRepository = helloCallTimeLogRepository; + this.tokenService = tokenService; + this.helloCallService = helloCallService; + } + + @Override + public void run(String... args) { + initial(); + saveRefreshTokenToRedis(); + } + + private void saveRefreshTokenToRedis() { + System.out.println("---------------[더미데이터] 멤버별 RefreshToken---------------"); + System.out.printf("시니또1 김철수(MemberId : 1)의 refreshToken : %s%n", tokenService.generateRefreshToken("1chulsoo@example.com")); + System.out.printf("시니또2 김유진(MemberId : 2)의 refreshToken : %s%n", tokenService.generateRefreshToken("2kim@example.com")); + System.out.printf("시니또3 이민호(MemberId : 3)의 refreshToken : %s%n", tokenService.generateRefreshToken("3lee@example.com")); + System.out.printf("시니또4 박소연(MemberId : 4)의 refreshToken : %s%n", tokenService.generateRefreshToken("4park@example.com")); + System.out.printf("시니또5 최진우(MemberId : 5)의 refreshToken : %s%n", tokenService.generateRefreshToken("5choi@example.com")); + System.out.printf("보호자1 정예린(MemberId : 6)의 refreshToken : %s%n", tokenService.generateRefreshToken("6jeong@example.com")); + System.out.printf("보호자2 한상훈(MemberId : 7)의 refreshToken : %s%n", tokenService.generateRefreshToken("7han@example.com")); + System.out.printf("보호자3 오수빈(MemberId : 8)의 refreshToken : %s%n", tokenService.generateRefreshToken("8oh@example.com")); + System.out.printf("보호자4 임지훈(MemberId : 9)의 refreshToken : %s%n", tokenService.generateRefreshToken("9lim@example.com")); + System.out.printf("보호자5 송하늘(MemberId : 10)의 refreshToken : %s%n", tokenService.generateRefreshToken("10song@example.com")); + System.out.println("----------------------------------------------------------"); + } + + private void initial() { + //시니또 + Member memberSinitto1 = memberRepository.save(new Member("김철수", "01012345678", "1chulsoo@example.com", true)); + sinittoBankInfoRepository.save(new SinittoBankInfo("신한은행", "123-23-444-422", memberSinitto1)); + Member memberSinitto2 = memberRepository.save(new Member("김유진", "01023456789", "2kim@example.com", true)); + sinittoBankInfoRepository.save(new SinittoBankInfo("대구은행", "446-5-11-2", memberSinitto2)); + Member memberSinitto3 = memberRepository.save(new Member("이민호", "01034567890", "3lee@example.com", true)); + sinittoBankInfoRepository.save(new SinittoBankInfo("IBK은행", "7-66-8-422", memberSinitto3)); + Member memberSinitto4 = memberRepository.save(new Member("박소연", "01045678901", "4park@example.com", true)); + sinittoBankInfoRepository.save(new SinittoBankInfo("토스뱅크", "777-1-2-3", memberSinitto4)); + Member memberSinitto5 = memberRepository.save(new Member("최진우", "01056789012", "5choi@example.com", true)); + sinittoBankInfoRepository.save(new SinittoBankInfo("기업은행", "96-6-99-45", memberSinitto5)); + + //보호자 + Member guard1 = memberRepository.save(new Member("정예린", "01067890123", "6jeong@example.com", false)); + Member guard2 = memberRepository.save(new Member("한상훈", "01078901234", "7han@example.com", false)); + Member guard3 = memberRepository.save(new Member("오수빈", "01089012345", "8oh@example.com", false)); + Member guard4 = memberRepository.save(new Member("임지훈", "01090123456", "9lim@example.com", false)); + Member guard5 = memberRepository.save(new Member("송하늘", "01001234567", "10song@example.com", false)); + + //시니어 + Senior senior1 = seniorRepository.save(new Senior("권지민", "01013572468", guard1)); + Senior senior2 = seniorRepository.save(new Senior("배정호", "01024681357", guard1)); + Senior senior3 = seniorRepository.save(new Senior("윤수현", "01046809753", guard1)); + Senior senior4 = seniorRepository.save(new Senior("하재민", "01057910864", guard2)); + Senior senior5 = seniorRepository.save(new Senior("민서영", "01068021975", guard2)); + Senior senior6 = seniorRepository.save(new Senior("전진우", "01079132086", guard3)); + Senior senior7 = seniorRepository.save(new Senior("나미래", "01080243197", guard3)); + Senior senior8 = seniorRepository.save(new Senior("임소라", "01091354208", guard4)); + Senior senior9 = seniorRepository.save(new Senior("조예빈", "01002465319", guard4)); + Senior senior10 = seniorRepository.save(new Senior("우지현", "01013576420", guard5)); + Senior senior11 = seniorRepository.save(new Senior("서예진", "01035798642", guard5)); + Senior senior12 = seniorRepository.save(new Senior("이도훈", "01047389557", guard1)); + Senior senior13 = seniorRepository.save(new Senior("정성훈", "01095502346", guard1)); + Senior senior14 = seniorRepository.save(new Senior("이지호", "01099329746", guard1)); + Senior senior15 = seniorRepository.save(new Senior("김강민", "01030957259", guard1)); + Senior senior16 = seniorRepository.save(new Senior("김지훈", "01062479134", guard2)); + Senior senior17 = seniorRepository.save(new Senior("박서연", "01083649205", guard2)); + Senior senior18 = seniorRepository.save(new Senior("홍승현", "01074102368", guard3)); + Senior senior19 = seniorRepository.save(new Senior("이수빈", "01051908364", guard3)); + Senior senior20 = seniorRepository.save(new Senior("최민지", "01096347281", guard4)); + Senior senior21 = seniorRepository.save(new Senior("백승민", "01018539647", guard4)); + Senior senior22 = seniorRepository.save(new Senior("윤지수", "01073214950", guard5)); + Senior senior23 = seniorRepository.save(new Senior("한유정", "01058231946", guard5)); + Senior senior24 = seniorRepository.save(new Senior("전현우", "01031905728", guard1)); + Senior senior25 = seniorRepository.save(new Senior("송예은", "01071489352", guard2)); + Senior senior26 = seniorRepository.save(new Senior("고유민", "01040257193", guard2)); + Senior senior27 = seniorRepository.save(new Senior("황지호", "01062079351", guard3)); + Senior senior28 = seniorRepository.save(new Senior("김도현", "01081724630", guard3)); + Senior senior29 = seniorRepository.save(new Senior("서민재", "01079320584", guard4)); + Senior senior30 = seniorRepository.save(new Senior("오예림", "01091268437", guard5)); + + //포인트와 포인트로그 + pointRepository.save(new Point(50000, memberSinitto1)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), memberSinitto1, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), memberSinitto1, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), memberSinitto1, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), memberSinitto1, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), memberSinitto1, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto1, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, memberSinitto2)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), memberSinitto2, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), memberSinitto2, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), memberSinitto2, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), memberSinitto2, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), memberSinitto2, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto2, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, memberSinitto3)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), memberSinitto3, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), memberSinitto3, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), memberSinitto3, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), memberSinitto3, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), memberSinitto3, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto3, 50000, PointLog.Status.CHARGE_COMPLETE)); + + pointRepository.save(new Point(50000, memberSinitto4)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), memberSinitto4, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), memberSinitto4, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), memberSinitto4, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), memberSinitto4, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), memberSinitto4, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto4, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, memberSinitto5)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), memberSinitto5, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), memberSinitto5, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), memberSinitto5, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), memberSinitto5, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), memberSinitto5, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), memberSinitto5, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, guard1)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard1, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard1, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard1, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard1, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), guard1, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), guard1, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), guard1, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), guard1, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), guard1, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard1, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard1, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard1, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard1, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, guard2)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard2, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard2, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard2, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard2, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), guard2, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), guard2, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), guard2, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), guard2, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), guard2, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard2, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard2, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard2, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard2, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, guard3)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard3, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard3, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard3, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard3, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), guard3, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), guard3, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), guard3, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), guard3, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), guard3, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard3, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard3, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard3, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard3, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, guard4)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard4, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard4, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard4, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard4, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), guard4, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), guard4, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), guard4, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), guard4, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), guard4, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard4, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard4, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard4, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard4, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + pointRepository.save(new Point(50000, guard5)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard5, 50000, PointLog.Status.CHARGE_FAIL)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard5, 50000, PointLog.Status.CHARGE_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard5, 50000, PointLog.Status.CHARGE_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), guard5, 50000, PointLog.Status.CHARGE_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_CALLBACK_AND_EARN.getMessage(), guard5, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), guard5, 50000, PointLog.Status.EARN)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), guard5, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_COMPLETE_CALLBACK.getMessage(), guard5, 50000, PointLog.Status.SPEND_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), guard5, 50000, PointLog.Status.SPEND_CANCEL)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard5, 50000, PointLog.Status.WITHDRAW_REQUEST)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard5, 50000, PointLog.Status.WITHDRAW_WAITING)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard5, 50000, PointLog.Status.WITHDRAW_COMPLETE)); + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), guard5, 50000, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + //콜백 + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior1)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior1)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior1)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior2)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior2)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior2)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior3)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior3)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior3)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior4)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior4)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior4)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior5)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior5)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior5)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior6)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior6)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior6)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior7)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior7)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior7)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior8)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior8)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior8)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior9)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior9)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior9)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior10)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior10)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior10)); + + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior11)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, senior11)); + callbackRepository.save(new Callback(Callback.Status.WAITING, senior11)); + + //리뷰 + reviewRepository.save(new Review(5, 4, 5, "테스트용 리뷰 1", guard1)); + reviewRepository.save(new Review(5, 2, 2, "테스트용 리뷰 2", guard2)); + reviewRepository.save(new Review(2, 3, 1, "테스트용 리뷰 3", guard3)); + reviewRepository.save(new Review(4, 1, 4, "테스트용 리뷰 4", guard4)); + reviewRepository.save(new Review(2, 5, 3, "테스트용 리뷰 5", guard5)); + + //가이드라인 + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "노인복지센터까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 상당구 대성로 172번길 21 (청주시노인종합복지관). 어머니께서 집에서 출발하십니다. 확인 후 택시 호출해주세요. 결제는 어머니께서 직접 현금으로 하십니다.", senior1)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주터미널로 가는 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 흥덕구 가로수로 120 (청주터미널). 어머니는 터미널로 가실 때 주로 오전 시간에 출발하십니다. 확인 후 택시 호출해주세요.", senior1)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주대학교 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대1동 555-1, 목적지: 충청북도 청주시 서원구 청남로 135 (청주대학교 병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 어머니께서 직접 하실 예정입니다.", senior1)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "피자 주문", "가게명: 청주피자 청주지점, 메뉴명: 슈퍼콤보 피자 (라지), 가격: 23000원, 보통 슈퍼콤보 피자를 시키십니다. 혹시 크러스트 추가 원하시면 치즈크러스트로 추가해주세요.", senior1)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 비하로 55 (비하병원). 병원에 갈 때는 보통 오전 10시에 출발하십니다. 결제는 현금으로 하실 예정입니다.", senior2)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주역까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 팔봉로 54 (청주역). 오전 출발 예정이며, 어머니께서 직접 결제하실 예정입니다.", senior2)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "치킨 주문", "가게명: 여수정통치킨 여수점, 메뉴명: 순살후라이드, 가격: 18000원, 주로 순살후라이드를 드시지만 양념이 필요하면 간장양념치킨으로 변경 부탁드립니다.", senior2)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "동네 마트까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 비하동 123-4, 목적지: 충청북도 청주시 흥덕구 마트로 32 (비하동 마트). 장을 볼 때 자주 이용하시며, 결제는 항상 현금으로 하십니다.", senior2)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "충북대병원까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 상당구 중흥로 22 (충북대병원). 병원 예약 시간에 맞춰 오전에 출발합니다. 결제는 현금으로 하실 예정입니다.", senior3)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주공항까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 상당구 용암동 345-6, 목적지: 충청북도 청주시 청원구 내수읍 오창대로 607 (청주국제공항). 항공편에 맞춰 오전에 출발할 예정입니다.", senior3)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "족발 주문", "가게명: 청주족발전문점, 메뉴명: 앞다리 족발 (중), 가격: 29000원, 보통 앞다리 족발을 드시며, 추가 요청사항은 무조건 무김치를 함께 보내달라고 하십니다.", senior3)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "한식당 배달 주문", "가게명: 청주미소한식당, 메뉴명: 된장찌개, 가격: 8000원, 된장찌개를 자주 드시며, 나물 반찬을 추가로 요청하시면 됩니다.", senior3)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 성안길시장까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 상당구 성안길 112 (성안길시장). 시장에 가실 때 보통 점심 직후에 출발하십니다. 결제는 어머니께서 현금으로 하실 예정입니다.", senior4)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주문화재단까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 78-3, 목적지: 충청북도 청주시 흥덕구 공단로 108 (청주문화재단). 문화 활동을 위해 자주 가십니다. 결제는 현금으로 하실 예정입니다.", senior4)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "불고기 백반 주문", "가게명: 청주진가네한식당, 메뉴명: 불고기 백반, 가격: 12000원, 불고기 백반을 즐겨 드시고 반찬 추가는 김치와 나물로 요청하시면 됩니다.", senior4)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "김밥 주문", "가게명: 청주광장김밥, 메뉴명: 참치김밥 2줄, 가격: 8000원, 참치김밥을 2줄 주문하십니다. 혹시 추가 요청사항이 있으면 단무지를 넉넉히 부탁드리세요.", senior4)); + + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "서원구교회까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 성당길 12 (서원구교회). 주일 예배 참석을 위해 교회로 가십니다. 예배 시간 전에 미리 도착할 수 있도록 조정해주세요.", senior5)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.TAXI, "청주 시립도서관까지 택시 이용 가이드라인", "출발지: 충청북도 청주시 흥덕구 복대동 12-34, 목적지: 충청북도 청주시 서원구 수곡로 108 (청주 시립도서관). 주로 설정한 출발지에서 출발하시지만 따로 요청하시면 변경부탁드릴게요.", senior5)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "떡볶이 주문", "가게명: 청주신당떡볶이, 메뉴명: 매운 떡볶이 (중), 가격: 9000원, 매운 떡볶이를 자주 드시지만, 간혹 덜 맵게 요청하시는 경우가 있으니 주문 시 주의해주세요.", senior5)); + guardGuidelineRepository.save(new GuardGuideline(GuardGuideline.Type.DELIVERY, "비빔밥 주문", "가게명: 청주미소한식당, 메뉴명: 돌솥비빔밥, 가격: 11000원, 돌솥비빔밥을 즐겨 드시며 나물은 조금 더 넣어달라고 요청하시면 좋습니다.", senior5)); + + //안부전화 + HelloCall helloCall1 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 5), LocalDate.of(2024, 10, 1), 13000, 10, "어머님께서 매일 아침 등산을 하시는 걸 좋아하세요. 요즘 날씨가 추워졌는데, 건강하게 등산을 잘 다니시는지 여쭤봐 주세요. 등산 이야기를 하면 기분이 좋아지실 거예요.", senior1)); + HelloCall helloCall2 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 2), LocalDate.of(2024, 10, 1), 14000, 10, "어머님께서 손주들 이야기를 굉장히 좋아하십니다. 최근에 손주들이 학교에서 무엇을 하고 있는지 말씀드리면 아주 즐거워하세요. 손주들과 관련된 이야기로 대화를 시작해 주세요.", senior2)); + HelloCall helloCall3 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 10, 5), LocalDate.of(2024, 11, 7), 13000, 15, "아버님은 오래된 한국 영화를 좋아하세요. 요즘 어떤 영화가 재미있었는지 물어보시면, 아마 영화 이야기를 하며 기분 좋게 통화하실 겁니다.", senior3)); + HelloCall helloCall4 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 10, 5), LocalDate.of(2024, 11, 8), 7500, 15, "어머님께서는 정원을 돌보는 것을 좋아하세요. 요즘 날씨 때문에 정원을 돌보시기 어려운지, 새로 심은 꽃들은 잘 자라고 있는지 여쭤봐 주세요.", senior4)); + HelloCall helloCall5 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 10, 5), LocalDate.of(2024, 11, 9), 6000, 5, "아버님께서는 요즘 건강에 많이 신경을 쓰고 계세요. 최근 혈압이나 운동을 잘하고 계신지, 건강 관련해서 대화를 나눠주시면 좋을 것 같아요.", senior5)); + HelloCall helloCall6 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 3), LocalDate.of(2024, 10, 1), 13500, 5, "어머님께서는 옛 친구들 이야기를 좋아하세요. 요즘 친구들과 자주 연락하시거나 만나시는지 물어봐 주시고, 친구들 근황에 대해 여쭤보시면 즐거워하실 겁니다.", senior6)); + HelloCall helloCall7 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 4), LocalDate.of(2024, 10, 1), 15000, 10, "아버님께서는 요즘 책 읽는 것을 좋아하십니다. 최근에 어떤 책을 읽고 계신지 여쭤보시고, 책과 관련된 대화를 이어나가시면 좋을 것 같아요.", senior7)); + HelloCall helloCall8 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 8, 6), LocalDate.of(2024, 10, 1), 7500, 10, "어머님은 전통 음식 만드는 것을 좋아하세요. 최근에 어떤 음식을 만들어 드셨는지, 특히 요즘 김장 준비는 잘하고 계신지 여쭤봐 주세요.", senior8)); + HelloCall helloCall9 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 6, 7), LocalDate.of(2024, 9, 8), 8500, 15, "아버님께서는 요즘 운동을 자주 하려고 하시는데, 날씨가 추워지면서 잘하고 계신지 물어봐 주세요. 운동과 관련된 대화를 나누면 좋을 것 같습니다.", senior12)); + HelloCall helloCall10 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 6, 5), LocalDate.of(2024, 9, 8), 7550, 15, "어머님께서는 최근에 동네 산책을 즐겨 하십니다. 요즘 날씨 때문에 산책이 어려우신지, 산책하시며 만나는 사람들과 근황을 나누고 계신지 물어봐 주시면 좋을 것 같아요.", senior13)); + HelloCall helloCall11 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 6, 5), LocalDate.of(2024, 9, 6), 16550, 5, "아버님께서는 요즘 음악 듣는 시간을 즐기세요. 특히 트로트를 좋아하시는데, 최근에 어떤 노래를 들으셨는지 여쭤봐 주세요. 음악 이야기로 대화를 시작하면 기분 좋으실 거예요.", senior14)); + HelloCall helloCall12 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 2), LocalDate.of(2024, 10, 1), 12500, 10, "어머님께서는 뜨개질을 즐기세요. 요즘 어떤 작품을 만들고 계신지 여쭤보고, 새로운 작품 계획이 있으신지 물어봐 주세요.", senior16)); + HelloCall helloCall13 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 3), LocalDate.of(2024, 10, 2), 14000, 15, "아버님께서는 고전 문학을 좋아하세요. 최근에 읽으신 책이나 추천하실 만한 책이 있으신지 대화를 시작해 주세요.", senior17)); + HelloCall helloCall14 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 4), LocalDate.of(2024, 10, 3), 13500, 10, "어머님께서는 요리를 매우 좋아하십니다. 최근에 어떤 음식을 만드셨는지 여쭤보시면 기분 좋은 대화를 나누실 수 있을 거예요.", senior18)); + HelloCall helloCall15 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 5), LocalDate.of(2024, 10, 4), 14500, 5, "아버님께서는 오래된 추억 이야기를 자주 하세요. 어린 시절의 추억에 대해 물어보시면 즐거운 대화를 이어가실 겁니다.", senior19)); + HelloCall helloCall16 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 6), LocalDate.of(2024, 10, 5), 12000, 15, "어머님께서는 손으로 만드는 공예품을 좋아하세요. 최근에 어떤 작품을 완성하셨는지 이야기 나눠보세요.", senior20)); + HelloCall helloCall17 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 7), LocalDate.of(2024, 10, 6), 15500, 10, "아버님께서는 최근 건강 관리에 신경을 많이 쓰고 계십니다. 운동이나 식단 관련 이야기를 나누시면 좋을 것 같습니다.", senior21)); + HelloCall helloCall18 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 8), LocalDate.of(2024, 10, 7), 16000, 10, "어머님께서는 손주들 사진을 자주 보신다고 합니다. 최근에 손주들이 어떻게 지내고 있는지 물어보시면 기분 좋게 대화하실 거예요.", senior22)); + HelloCall helloCall19 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 9), LocalDate.of(2024, 10, 8), 11000, 15, "아버님께서는 오래된 음악을 즐겨 들으십니다. 좋아하시는 노래나 추억의 음악에 대해 이야기 나눠보세요.", senior23)); + HelloCall helloCall20 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 10), LocalDate.of(2024, 10, 9), 10500, 5, "어머님께서는 식물 기르는 것을 좋아하세요. 최근에 새로운 식물을 들이셨는지, 잘 자라고 있는지 물어봐 주세요.", senior24)); + HelloCall helloCall21 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 11), LocalDate.of(2024, 10, 10), 15000, 15, "아버님께서는 스포츠 경기를 즐겨 보십니다. 최근에 어떤 경기를 보셨는지, 가장 기억에 남는 순간이 무엇인지 물어봐 주세요.", senior25)); + HelloCall helloCall22 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 12), LocalDate.of(2024, 10, 11), 13000, 10, "어머님께서는 주말에 친구들과 산책을 즐기십니다. 요즘 산책이 편하신지, 친구들과 자주 만나시는지 여쭤봐 주세요.", senior26)); + HelloCall helloCall23 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 13), LocalDate.of(2024, 10, 12), 14500, 15, "아버님께서는 바둑 두는 것을 좋아하세요. 최근에 바둑을 두셨는지, 바둑에 대한 이야기를 나누면 좋을 것 같습니다.", senior27)); + HelloCall helloCall24 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 14), LocalDate.of(2024, 10, 13), 12500, 5, "어머님께서는 정원 가꾸는 일을 즐기십니다. 최근에 심은 꽃이나 식물들이 잘 자라고 있는지 물어봐 주세요.", senior28)); + HelloCall helloCall25 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 15), LocalDate.of(2024, 10, 14), 14000, 10, "아버님께서는 요즘 정치에 관심이 많으십니다. 최근 뉴스나 정치 이슈에 대해 대화를 나눠보세요.", senior29)); + HelloCall helloCall26 = helloCallRepository.save(new HelloCall(LocalDate.of(2024, 9, 16), LocalDate.of(2024, 10, 15), 11000, 5, "어머님께서는 손주들 사진을 자주 보신다고 합니다. 최근에 손주들이 어떻게 지내고 있는지 물어보시면 즐거운 대화를 나눌 수 있을 겁니다.", senior30)); + + //안부전화별 타임슬롯 + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall1)); + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(16, 30), LocalTime.of(18, 30), helloCall1)); + timeSlotRepository.save(new TimeSlot("금", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall1)); + + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(10, 0), LocalTime.of(12, 0), helloCall2)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(10, 30), LocalTime.of(12, 30), helloCall2)); + + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall3)); + timeSlotRepository.save(new TimeSlot("화", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall3)); + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall3)); + timeSlotRepository.save(new TimeSlot("목", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall3)); + timeSlotRepository.save(new TimeSlot("금", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall3)); + + timeSlotRepository.save(new TimeSlot("화", LocalTime.of(15, 30), LocalTime.of(17, 30), helloCall4)); + timeSlotRepository.save(new TimeSlot("목", LocalTime.of(16, 30), LocalTime.of(18, 30), helloCall4)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall4)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall4)); + + timeSlotRepository.save(new TimeSlot("화", LocalTime.of(17, 0), LocalTime.of(19, 0), helloCall5)); + timeSlotRepository.save(new TimeSlot("목", LocalTime.of(17, 0), LocalTime.of(19, 0), helloCall5)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(19, 0), LocalTime.of(21, 0), helloCall5)); + + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall6)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall6)); + + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(15, 0), LocalTime.of(17, 0), helloCall7)); + + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(20, 0), LocalTime.of(22, 0), helloCall8)); + timeSlotRepository.save(new TimeSlot("화", LocalTime.of(20, 0), LocalTime.of(22, 0), helloCall8)); + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(20, 0), LocalTime.of(22, 0), helloCall8)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall9)); + timeSlotRepository.save(new TimeSlot("금", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall9)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall9)); + + timeSlotRepository.save(new TimeSlot("월", LocalTime.of(11, 0), LocalTime.of(13, 0), helloCall10)); + timeSlotRepository.save(new TimeSlot("화", LocalTime.of(11, 0), LocalTime.of(13, 0), helloCall10)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall11)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall11)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall11)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall12)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall12)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall12)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall13)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall13)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall13)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall14)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall14)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall14)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall15)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall15)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall15)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall16)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall16)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall16)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall17)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall17)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall17)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall18)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall18)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall18)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall19)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall19)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall19)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall20)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall20)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall20)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall21)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall21)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall21)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall22)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall22)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall22)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall23)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall23)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall23)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall24)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall24)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall24)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall25)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall25)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall25)); + + timeSlotRepository.save(new TimeSlot("수", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall26)); + timeSlotRepository.save(new TimeSlot("토", LocalTime.of(18, 30), LocalTime.of(20, 30), helloCall26)); + timeSlotRepository.save(new TimeSlot("일", LocalTime.of(18, 0), LocalTime.of(20, 0), helloCall26)); + + //시니또 안부전화 할당 + helloCallService.acceptHelloCallBySinitto(memberSinitto1.getId(), helloCall1.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto1.getId(), helloCall2.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto2.getId(), helloCall3.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto2.getId(), helloCall4.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto3.getId(), helloCall5.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto4.getId(), helloCall6.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto4.getId(), helloCall7.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto5.getId(), helloCall8.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto5.getId(), helloCall9.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto2.getId(), helloCall10.getId()); + helloCallService.acceptHelloCallBySinitto(memberSinitto3.getId(), helloCall11.getId()); + + //안부전화 실시 타임로그 + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall1, memberSinitto3, LocalDateTime.of(2024, 8, 5, 18, 30), LocalDateTime.of(2024, 8, 5, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall1, memberSinitto3, LocalDateTime.of(2024, 8, 7, 18, 30), LocalDateTime.of(2024, 8, 7, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall1, memberSinitto1, LocalDateTime.of(2024, 8, 9, 18, 30), LocalDateTime.of(2024, 8, 9, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall1, memberSinitto1, LocalDateTime.of(2024, 8, 11, 18, 30), LocalDateTime.of(2024, 8, 11, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall1, memberSinitto1, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall2, memberSinitto1, LocalDateTime.of(2024, 8, 2, 10, 30), LocalDateTime.of(2024, 8, 2, 10, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall2, memberSinitto1, LocalDateTime.of(2024, 8, 5, 11, 30), LocalDateTime.of(2024, 8, 5, 11, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall3, memberSinitto2, LocalDateTime.of(2024, 10, 8, 18, 30), LocalDateTime.of(2024, 10, 8, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall3, memberSinitto2, LocalDateTime.of(2024, 10, 10, 18, 30), LocalDateTime.of(2024, 10, 10, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall4, memberSinitto2, LocalDateTime.of(2024, 10, 13, 18, 30), LocalDateTime.of(2024, 10, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall4, memberSinitto2, LocalDateTime.of(2024, 10, 13, 18, 30), LocalDateTime.of(2024, 10, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall5, memberSinitto3, LocalDateTime.of(2024, 10, 13, 18, 30), LocalDateTime.of(2024, 10, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall5, memberSinitto3, LocalDateTime.of(2024, 10, 13, 18, 30), LocalDateTime.of(2024, 10, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall6, memberSinitto3, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall6, memberSinitto4, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall7, memberSinitto4, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall7, memberSinitto4, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall8, memberSinitto5, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall8, memberSinitto5, LocalDateTime.of(2024, 8, 13, 18, 30), LocalDateTime.of(2024, 8, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall9, memberSinitto5, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall9, memberSinitto5, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall10, memberSinitto2, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall10, memberSinitto2, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall11, memberSinitto3, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + helloCallTimeLogRepository.save(new HelloCallTimeLog(helloCall11, memberSinitto3, LocalDateTime.of(2024, 6, 13, 18, 30), LocalDateTime.of(2024, 6, 13, 18, 40))); + + } + +} diff --git a/src/main/java/com/example/sinitto/guard/repository/SeniorRepository.java b/src/main/java/com/example/sinitto/guard/repository/SeniorRepository.java index 0f60727a..71309097 100644 --- a/src/main/java/com/example/sinitto/guard/repository/SeniorRepository.java +++ b/src/main/java/com/example/sinitto/guard/repository/SeniorRepository.java @@ -1,5 +1,6 @@ package com.example.sinitto.guard.repository; +import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -14,4 +15,6 @@ public interface SeniorRepository extends JpaRepository { Optional findByIdAndMemberId(Long Id, Long memberId); Optional findByPhoneNumber(String phoneNumber); + + List findAllByMember(Member member); } diff --git a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java index 94ae661f..9cddc806 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java +++ b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java @@ -1,53 +1,57 @@ package com.example.sinitto.guardGuideline.controller; +import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.guardGuideline.dto.GuardGuidelineRequest; import com.example.sinitto.guardGuideline.dto.GuardGuidelineResponse; +import com.example.sinitto.guardGuideline.entity.GuardGuideline; +import com.example.sinitto.guardGuideline.service.GuardGuidelineService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("/api/guardguidelines") -@Tag(name = "[미구현][의논필요]보호자용 가이드라인", description = "보호자가 입력하는 시니어별 가이드라인 관련 API") +@Tag(name = "보호자용 가이드라인", description = "보호자가 입력하는 시니어별 가이드라인 관련 API") public class GuardGuidelineController { + private final GuardGuidelineService guardGuidelineService; + + public GuardGuidelineController(GuardGuidelineService guardGuidelineService) {this.guardGuidelineService = guardGuidelineService;} + @Operation(summary = "가이드라인 추가", description = "보호자가 시니어별 가이드라인을 추가합니다.") @PostMapping - public ResponseEntity addGuideline(@RequestBody GuardGuidelineRequest request) { - // 임시 응답 + public ResponseEntity addGuardGuideline(@MemberId Long memberId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { + guardGuidelineService.addGuardGuideline(memberId, guardGuidelineRequest); return ResponseEntity.ok("가이드라인이 추가되었습니다."); } @Operation(summary = "카테고리에 해당하는 모든 가이드라인 조회", description = "시니또용 앱에서 카테고리에 해당하는 모든 가이드라인들을 요청할 때 필요합니다.") - @GetMapping("/{seniorId}/{typeId}") - public ResponseEntity> getGuidelinesByCategory(@PathVariable Long seniorId, @PathVariable Long typeId) { - // 임시 응답 - return ResponseEntity.ok(new ArrayList<>()); + @GetMapping("/{seniorId}/{type}") + public ResponseEntity> getGuardGuidelinesByCategory(@PathVariable Long seniorId, @PathVariable GuardGuideline.Type type) { + return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesByCategory(seniorId, type)); } @Operation(summary = "가이드라인 수정", description = "보호자가 특정 가이드라인을 수정할 때 필요합니다.") @PutMapping("/{guidelineId}") - public ResponseEntity updateGuideline(@PathVariable Long guidelineId, @RequestBody GuardGuidelineRequest request) { - // 임시 응답 + public ResponseEntity updateGuardGuideline(@MemberId Long memberId, @PathVariable Long guidelineId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { + guardGuidelineService.updateGuardGuideline(memberId, guidelineId, guardGuidelineRequest); return ResponseEntity.ok("가이드라인이 수정되었습니다."); } @Operation(summary = "모든 가이드라인 조회(시니어별로)", description = "보호자가 가이드라인 수정을 위해 시니어별로 모든 가이드라인을 요청할 때 필요합니다.") @GetMapping("/{seniorId}") - public ResponseEntity> getAllGuidelinesBySenior(@PathVariable Long seniorId) { - // 임시 응답 - return ResponseEntity.ok(new ArrayList<>()); + public ResponseEntity> getAllGuardGuidelinesBySenior(@PathVariable Long seniorId) { + + return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesBySenior(seniorId)); } @Operation(summary = "특정 가이드라인 조회", description = "보호자용 API입니다.") @GetMapping("/{guidelineId}") - public ResponseEntity getGuideline(@PathVariable Long guidelineId) { - // 임시 응답 - return ResponseEntity.ok(new GuardGuidelineResponse(null, null)); + public ResponseEntity getGuardGuideline(@PathVariable Long guidelineId) { + return ResponseEntity.ok(guardGuidelineService.readGuardGuideline(guidelineId)); } } diff --git a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java new file mode 100644 index 00000000..c7543ec9 --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineControllerAdvice.java @@ -0,0 +1,33 @@ +package com.example.sinitto.guardGuideline.controller; + +import com.example.sinitto.guardGuideline.exception.GuardGuidelineNotFoundException; +import com.example.sinitto.guardGuideline.exception.SeniorAndGuardMemberMismatchException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.net.URI; + +@RestControllerAdvice(basePackages = "com.example.sinitto.guardGuideline") +public class GuardGuidelineControllerAdvice { + + @ExceptionHandler(GuardGuidelineNotFoundException.class) + public ResponseEntity handleGuardGuidelineNotFoundException(GuardGuidelineNotFoundException e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); + problemDetail.setType(URI.create("/error/guideline-not-found")); + problemDetail.setTitle("Guideline Not Found"); + + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); + } + + @ExceptionHandler(SeniorAndGuardMemberMismatchException.class) + public ResponseEntity handleSeniorAndGuardMemberMismatchException(SeniorAndGuardMemberMismatchException e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); + problemDetail.setType(URI.create("/error/member-mismatch")); + problemDetail.setTitle("Senior and Guard Member Mismatch"); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetail); + } +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java index 05d6635d..a30db103 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java +++ b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineRequest.java @@ -1,4 +1,10 @@ package com.example.sinitto.guardGuideline.dto; -public record GuardGuidelineRequest() { -} +import com.example.sinitto.guardGuideline.entity.GuardGuideline; + +public record GuardGuidelineRequest( + Long seniorId, + GuardGuideline.Type type, + String title, + String content +) {} diff --git a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java index a820d21a..06ebce6a 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java +++ b/src/main/java/com/example/sinitto/guardGuideline/dto/GuardGuidelineResponse.java @@ -1,6 +1,9 @@ package com.example.sinitto.guardGuideline.dto; +import com.example.sinitto.guardGuideline.entity.GuardGuideline; + public record GuardGuidelineResponse( + GuardGuideline.Type type, String title, String content) { } diff --git a/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideLine.java b/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideLine.java deleted file mode 100644 index 686e1287..00000000 --- a/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideLine.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.example.sinitto.guardGuideline.entity; - -import com.example.sinitto.member.entity.Senior; -import jakarta.persistence.*; -import jakarta.validation.constraints.NotNull; -import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; - -@Entity -public class GuardGuideLine { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @NotNull - private String content; - @NotNull - private String type; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "senior_id") - @NotNull - @OnDelete(action = OnDeleteAction.CASCADE) - private Senior senior; - -} diff --git a/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideline.java b/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideline.java new file mode 100644 index 00000000..0bf66eec --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/entity/GuardGuideline.java @@ -0,0 +1,70 @@ +package com.example.sinitto.guardGuideline.entity; + +import com.example.sinitto.member.entity.Senior; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +@Entity +public class GuardGuideline { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @NotNull + @Enumerated(EnumType.STRING) + private Type type; + @NotNull + private String title; + @NotNull + private String content; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "senior_id") + @NotNull + @OnDelete(action = OnDeleteAction.CASCADE) + private Senior senior; + + protected GuardGuideline() { + } + + public GuardGuideline(Type type, String title, String content, Senior senior) { + this.type = type; + this.title = title; + this.content = content; + this.senior = senior; + } + + + public void updateGuardGuideline(Type type, String title, String content) { + this.type = type; + this.title = title; + this.content = content; + } + + public Long getId() { + return id; + } + + public Type getType() { + return type; + } + + public String getTitle() { + return title; + } + + public String getContent() { + return content; + } + + public Senior getSenior() { + return senior; + } + + + public enum Type { + TAXI, + DELIVERY + } +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java b/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java new file mode 100644 index 00000000..c488a16d --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/exception/GuardGuidelineNotFoundException.java @@ -0,0 +1,5 @@ +package com.example.sinitto.guardGuideline.exception; + +public class GuardGuidelineNotFoundException extends RuntimeException { + public GuardGuidelineNotFoundException(String message) {super(message);} +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java b/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java new file mode 100644 index 00000000..87d643de --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/exception/SeniorAndGuardMemberMismatchException.java @@ -0,0 +1,7 @@ +package com.example.sinitto.guardGuideline.exception; + +public class SeniorAndGuardMemberMismatchException extends RuntimeException { + public SeniorAndGuardMemberMismatchException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepository.java b/src/main/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepository.java new file mode 100644 index 00000000..73315648 --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepository.java @@ -0,0 +1,15 @@ +package com.example.sinitto.guardGuideline.repository; + +import com.example.sinitto.guardGuideline.entity.GuardGuideline; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + + +@Repository +public interface GuardGuidelineRepository extends JpaRepository { + List findBySeniorId(Long seniorId); + + List findBySeniorIdAndType(Long seniorId, GuardGuideline.Type type); +} diff --git a/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java b/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java new file mode 100644 index 00000000..c1e36b91 --- /dev/null +++ b/src/main/java/com/example/sinitto/guardGuideline/service/GuardGuidelineService.java @@ -0,0 +1,86 @@ +package com.example.sinitto.guardGuideline.service; + + +import com.example.sinitto.guard.exception.SeniorNotFoundException; +import com.example.sinitto.guard.repository.SeniorRepository; +import com.example.sinitto.guardGuideline.dto.GuardGuidelineRequest; +import com.example.sinitto.guardGuideline.dto.GuardGuidelineResponse; +import com.example.sinitto.guardGuideline.entity.GuardGuideline; +import com.example.sinitto.guardGuideline.entity.GuardGuideline.Type; +import com.example.sinitto.guardGuideline.exception.GuardGuidelineNotFoundException; +import com.example.sinitto.guardGuideline.exception.SeniorAndGuardMemberMismatchException; +import com.example.sinitto.guardGuideline.repository.GuardGuidelineRepository; +import com.example.sinitto.member.entity.Senior; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class GuardGuidelineService { + + private final GuardGuidelineRepository guardGuidelineRepository; + private final SeniorRepository seniorRepository; + + public GuardGuidelineService (GuardGuidelineRepository guardGuidelineRepository, SeniorRepository seniorRepository){ + this.guardGuidelineRepository = guardGuidelineRepository; + this.seniorRepository = seniorRepository; + } + + @Transactional + public void addGuardGuideline(Long memberId, GuardGuidelineRequest guardGuidelineRequest) { + Senior senior = seniorRepository.findById(guardGuidelineRequest.seniorId()).orElseThrow( + () -> new SeniorNotFoundException("시니어를 찾을 수 없습니다.") + ); + if (senior.isNotGuard(memberId)) { + throw new SeniorAndGuardMemberMismatchException("해당 Guard의 Senior가 아닙니다."); + } + + guardGuidelineRepository.save(new GuardGuideline(guardGuidelineRequest.type(), guardGuidelineRequest.title(), guardGuidelineRequest.content(), senior)); + } + + @Transactional(readOnly = true) + public List readAllGuardGuidelinesByCategory(Long seniorId, Type type){ + List guardGuidelines = guardGuidelineRepository.findBySeniorIdAndType(seniorId, type); + + return guardGuidelines.stream() + .map(m -> new GuardGuidelineResponse(m.getType(), m.getTitle(), m.getContent())) + .toList(); + } + + @Transactional + public void updateGuardGuideline(Long memberId, Long guidelineId, GuardGuidelineRequest guardGuidelineRequest) { + GuardGuideline guardGuideline = guardGuidelineRepository.findById(guidelineId).orElseThrow( + ()-> new GuardGuidelineNotFoundException("해당 가이드라인이 존재하지 않습니다.") + ); + + Senior senior = seniorRepository.findById(guardGuidelineRequest.seniorId()).orElseThrow( + () -> new SeniorNotFoundException("시니어를 찾을 수 없습니다.") + ); + + if (senior.isNotGuard(memberId)) { + throw new SeniorAndGuardMemberMismatchException("해당 Guard의 Senior가 아닙니다."); + } + + guardGuideline.updateGuardGuideline(guardGuidelineRequest.type(), guardGuidelineRequest.title(), guardGuidelineRequest.content()); + } + + @Transactional(readOnly = true) + public List readAllGuardGuidelinesBySenior(Long seniorId){ + List guardGuidelines = guardGuidelineRepository.findBySeniorId(seniorId); + + return guardGuidelines.stream() + .map(m -> new GuardGuidelineResponse(m.getType(), m.getTitle(), m.getContent())) + .toList(); + } + + @Transactional(readOnly = true) + public GuardGuidelineResponse readGuardGuideline(Long guidelineId){ + GuardGuideline guardGuideline = guardGuidelineRepository.findById(guidelineId).orElseThrow( + ()-> new GuardGuidelineNotFoundException("해당 가이드라인이 존재하지 않습니다.") + ); + + return new GuardGuidelineResponse(guardGuideline.getType(), guardGuideline.getTitle(), guardGuideline.getContent()); + } + +} diff --git a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java b/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java index 5c29a028..fd8ba62c 100644 --- a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java +++ b/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java @@ -132,13 +132,13 @@ public ResponseEntity writeHelloCallEndTimeBySinitto(@Mem @PostMapping("/reports") public ResponseEntity createHelloCallReport(@MemberId Long memberId, @RequestBody HelloCallReportRequest request) { - helloCallService.SendReportBySinitto(memberId, request); + helloCallService.sendReportBySinitto(memberId, request); return ResponseEntity.status(HttpStatus.CREATED).body(new StringMessageResponse("소통 보고서가 작성되었습니다.")); } @Operation(summary = "[보호자용] 완료 대기 상태 안부전화 완료 처리", description = "보호자가 완료 대기 상태인 안부전화의 상태를 완료로 변경합니다.") - @PostMapping("/complete/{callId}") + @PutMapping("/complete/{callId}") public ResponseEntity completeHelloCall(@MemberId Long memberId, @PathVariable Long callId) { helloCallService.makeCompleteHelloCallByGuard(memberId, callId); diff --git a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailResponse.java b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailResponse.java index 0719bb6d..54ff2022 100644 --- a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailResponse.java +++ b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailResponse.java @@ -1,11 +1,39 @@ package com.example.sinitto.helloCall.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; import java.time.LocalTime; import java.util.List; +@Schema(example = """ + { + "startDate": "2024-08-05", + "endDate": "2024-10-01", + "timeSlots": [ + { + "dayName": "월", + "startTime": "18:00", + "endTime": "20:00" + }, + { + "dayName": "수", + "startTime": "16:30", + "endTime": "18:30" + }, + { + "dayName": "금", + "startTime": "18:00", + "endTime": "20:00" + } + ], + "requirement": "어머님께서 매일 아침 등산을 하시는 걸 좋아하세요. 요즘 날씨가 추워졌는데, 건강하게 등산을 잘 다니시는지 여쭤봐 주세요. 등산 이야기를 하면 기분이 좋아지실 거예요.", + "seniorName": "권지민", + "seniorPhoneNumber": "01013572468", + "price": 13000 + } + """) public record HelloCallDetailResponse( LocalDate startDate, LocalDate endDate, @@ -17,9 +45,9 @@ public record HelloCallDetailResponse( ) { public record TimeSlot( String dayName, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime startTime, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime endTime) { } } diff --git a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailUpdateRequest.java b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailUpdateRequest.java index 9297d4d7..c01408a8 100644 --- a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailUpdateRequest.java +++ b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallDetailUpdateRequest.java @@ -1,11 +1,33 @@ package com.example.sinitto.helloCall.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; import java.time.LocalTime; import java.util.List; +@Schema(description = "HelloCall 가격 요청", example = """ + { + "startDate": "2024-10-01", + "endDate": "2024-10-08", + "timeSlots": [ + { + "dayName": "수", + "startTime": "18:00", + "endTime": "20:00" + }, + { + "dayName": "금", + "startTime": "18:00", + "endTime": "20:00" + } + ], + "price": 500, + "serviceTime": 10, + "requirement": "어머님께서 매일 아침 등산을 하시는 걸 좋아하세요. 요즘 날씨가 추워졌는데, 건강하게 등산을 잘 다니시는지 여쭤봐 주세요. 등산 이야기를 하면 기분이 좋아지실 거예요." + } + """) public record HelloCallDetailUpdateRequest( LocalDate startDate, LocalDate endDate, @@ -16,9 +38,9 @@ public record HelloCallDetailUpdateRequest( ) { public record TimeSlot( String dayName, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime startTime, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime endTime) { } } diff --git a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallPriceRequest.java b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallPriceRequest.java index 1ca35f49..8214e309 100644 --- a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallPriceRequest.java +++ b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallPriceRequest.java @@ -1,11 +1,31 @@ package com.example.sinitto.helloCall.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; import java.time.LocalTime; import java.util.List; +@Schema(example = """ + { + "startDate": "2024-10-01", + "endDate": "2024-10-08", + "timeSlots": [ + { + "dayName": "수", + "startTime": "18:00", + "endTime": "20:00" + }, + { + "dayName": "금", + "startTime": "18:00", + "endTime": "20:00" + } + ], + "serviceTime": 10 + } + """) public record HelloCallPriceRequest( LocalDate startDate, LocalDate endDate, @@ -14,9 +34,9 @@ public record HelloCallPriceRequest( ) { public record TimeSlot( String dayName, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime startTime, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime endTime) { } } diff --git a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallRequest.java b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallRequest.java index 427cf7de..dfe00a36 100644 --- a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallRequest.java +++ b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallRequest.java @@ -1,11 +1,34 @@ package com.example.sinitto.helloCall.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; import java.time.LocalTime; import java.util.List; +@Schema(example = """ + { + "seniorId": 15, + "startDate": "2024-10-01", + "endDate": "2024-10-08", + "timeSlots": [ + { + "dayName": "수", + "startTime": "18:00", + "endTime": "20:00" + }, + { + "dayName": "금", + "startTime": "18:00", + "endTime": "20:00" + } + ], + "price": 500, + "serviceTime": 10, + "requirement": "어머님께서 매일 아침 등산을 하시는 걸 좋아하세요. 요즘 날씨가 추워졌는데, 건강하게 등산을 잘 다니시는지 여쭤봐 주세요. 등산 이야기를 하면 기분이 좋아지실 거예요." + } + """) public record HelloCallRequest( Long seniorId, LocalDate startDate, @@ -17,9 +40,9 @@ public record HelloCallRequest( ) { public record TimeSlot( String dayName, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime startTime, - @JsonFormat(pattern = "kk:mm") + @JsonFormat(pattern = "HH:mm") LocalTime endTime) { } } diff --git a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallTimeResponse.java b/src/main/java/com/example/sinitto/helloCall/dto/HelloCallTimeResponse.java deleted file mode 100644 index 62c78f27..00000000 --- a/src/main/java/com/example/sinitto/helloCall/dto/HelloCallTimeResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.sinitto.helloCall.dto; - -import java.time.LocalDateTime; - -public record HelloCallTimeResponse( - LocalDateTime DateAndTime -) { -} diff --git a/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java b/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java index 68baedfd..47877d29 100644 --- a/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java +++ b/src/main/java/com/example/sinitto/helloCall/entity/HelloCall.java @@ -5,7 +5,6 @@ import com.example.sinitto.helloCall.exception.TimeRuleException; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.entity.Sinitto; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; @@ -44,8 +43,8 @@ public class HelloCall { @OneToMany(mappedBy = "helloCall", cascade = CascadeType.REMOVE) private List timeSlots = new ArrayList<>(); @ManyToOne - @JoinColumn(name = "sinitto_id") - private Sinitto sinitto; + @JoinColumn(name = "member_id") + private Member member; @OneToMany(mappedBy = "helloCall", cascade = CascadeType.REMOVE) private List helloCallTimeLogs = new ArrayList<>(); @@ -102,12 +101,12 @@ public int getServiceTime() { return serviceTime; } - public Sinitto getSinitto() { - return sinitto; + public Member getMember() { + return member; } - public void setSinitto(Sinitto sinitto) { - this.sinitto = sinitto; + public void setMember(Member member) { + this.member = member; } public String getReport() { @@ -118,33 +117,19 @@ public void setReport(String report) { this.report = report; } - public String getSinittoName() { - return this.sinitto.getMember().getName(); - } - - public List getHelloCallTimeLogs() { - return helloCallTimeLogs; - } - - public boolean checkUnAuthorization(Member member) { - return !this.senior.getMember().equals(member); + public String getMemberName() { + return this.member.getName(); } public void checkStatusIsWaiting() { - if (!this.status.equals(Status.WAITING)) { + if (status.canNotModifyOrDelete()) { throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 삭제가 가능합니다."); } } - public void checkSiniitoIsSame(Sinitto sinitto) { - if (!this.sinitto.equals(sinitto)) { - throw new UnauthorizedException("안부전화 서비스 리포트를 작성할 권한이 없습니다."); - } - } - public void checkGuardIsCorrect(Member member) { if (!this.senior.getMember().equals(member)) { - throw new UnauthorizedException("해당 시니어의 안부전화를 신청한 보호자가 아닙니다."); + throw new UnauthorizedException("해당 시니어의 안부전화를 신청한 보호자가 아닙니다. 권한이 없습니다."); } } @@ -156,36 +141,42 @@ public boolean checkReportIsNotNull() { return this.report != null; } + public void checkMemberIsRightSinitto(Member member) { + if (this.member == null || !this.member.equals(member)) { + throw new UnauthorizedException("해당 안부전화를 수행하는 시니또가 아닙니다."); + } + } + public void changeStatusToInProgress() { - if (!this.status.equals(Status.WAITING)) { - throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); + if (status.canNotProgressStatus(Status.IN_PROGRESS)) { + throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.IN_PROGRESS; } public void changeStatusToWaiting() { - if (!this.status.equals(Status.IN_PROGRESS)) { - throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 진행중 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); + if (status.canNotRollBackStatus()) { + throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 진행중 상태로 돌아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.WAITING; } public void changeStatusToPendingComplete() { - if (!this.status.equals(Status.IN_PROGRESS)) { - throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 완료 대기 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); + if (status.canNotProgressStatus(Status.PENDING_COMPLETE)) { + throw new InvalidStatusException("안부전화 서비스가 수행중일 때만 완료 대기 상태로 나아갈 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.PENDING_COMPLETE; } public void changeStatusToComplete() { - if (!this.status.equals(Status.PENDING_COMPLETE)) { + if (status.canNotProgressStatus(Status.COMPLETE)) { throw new InvalidStatusException("안부전화 서비스가 완료 대기 일때만 완료 상태로 변경할 수 있습니다. 현재 상태 : " + this.status); } this.status = Status.COMPLETE; } public void updateHelloCall(LocalDate startDate, LocalDate endDate, int price, int serviceTime, String requirement) { - if (!this.status.equals(Status.WAITING)) { + if (status.canNotModifyOrDelete()) { throw new InvalidStatusException("안부전화 서비스가 수행 대기중일 때만 수정이 가능합니다."); } if (startDate.isAfter(endDate)) { @@ -202,6 +193,23 @@ public enum Status { WAITING, IN_PROGRESS, PENDING_COMPLETE, - COMPLETE + COMPLETE; + + public boolean canNotProgressStatus(Status newStatus) { + return !switch (this) { + case WAITING -> newStatus.equals(IN_PROGRESS); + case IN_PROGRESS -> newStatus.equals(PENDING_COMPLETE); + case PENDING_COMPLETE -> newStatus.equals(COMPLETE); + default -> false; + }; + } + + public boolean canNotRollBackStatus() { + return !this.equals(IN_PROGRESS); + } + + public boolean canNotModifyOrDelete() { + return !this.equals(WAITING); + } } } diff --git a/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java b/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java index fd38b036..4b1a3bdc 100644 --- a/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java +++ b/src/main/java/com/example/sinitto/helloCall/entity/HelloCallTimeLog.java @@ -1,6 +1,6 @@ package com.example.sinitto.helloCall.entity; -import com.example.sinitto.member.entity.Sinitto; +import com.example.sinitto.member.entity.Member; import jakarta.persistence.*; import java.time.LocalDateTime; @@ -18,18 +18,18 @@ public class HelloCallTimeLog { private HelloCall helloCall; @ManyToOne @JoinColumn(name = "sinitto_id") - private Sinitto sinitto; + private Member member; - public HelloCallTimeLog(HelloCall helloCall, Sinitto sinitto) { + public HelloCallTimeLog(HelloCall helloCall, Member member) { this.helloCall = helloCall; - this.sinitto = sinitto; + this.member = member; } - public HelloCallTimeLog(HelloCall helloCall, Sinitto sinitto, LocalDateTime startDateAndTime, LocalDateTime endDateAndTime) { + public HelloCallTimeLog(HelloCall helloCall, Member member, LocalDateTime startDateAndTime, LocalDateTime endDateAndTime) { this.helloCall = helloCall; this.startDateAndTime = startDateAndTime; this.endDateAndTime = endDateAndTime; - this.sinitto = sinitto; + this.member = member; } protected HelloCallTimeLog() { @@ -52,14 +52,14 @@ public void setEndDateAndTime(LocalDateTime endDateAndTime) { } public String getSinittoName() { - return this.sinitto.getMember().getName(); + return this.member.getName(); } public HelloCall getHelloCall() { return helloCall; } - public Sinitto getSinitto() { - return sinitto; + public Member getSinitto() { + return member; } } diff --git a/src/main/java/com/example/sinitto/helloCall/repository/HelloCallRepository.java b/src/main/java/com/example/sinitto/helloCall/repository/HelloCallRepository.java index f166ab30..f6b68832 100644 --- a/src/main/java/com/example/sinitto/helloCall/repository/HelloCallRepository.java +++ b/src/main/java/com/example/sinitto/helloCall/repository/HelloCallRepository.java @@ -1,8 +1,8 @@ package com.example.sinitto.helloCall.repository; import com.example.sinitto.helloCall.entity.HelloCall; +import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.entity.Sinitto; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -14,7 +14,7 @@ public interface HelloCallRepository extends JpaRepository { Optional findBySenior(Senior senior); - List findAllBySinitto(Sinitto sinitto); + List findAllByMember(Member member); List findAllBySeniorIn(List seniors); diff --git a/src/main/java/com/example/sinitto/helloCall/repository/HelloCallTimeLogRepository.java b/src/main/java/com/example/sinitto/helloCall/repository/HelloCallTimeLogRepository.java index 09c0dfb6..af647940 100644 --- a/src/main/java/com/example/sinitto/helloCall/repository/HelloCallTimeLogRepository.java +++ b/src/main/java/com/example/sinitto/helloCall/repository/HelloCallTimeLogRepository.java @@ -2,16 +2,16 @@ import com.example.sinitto.helloCall.entity.HelloCall; import com.example.sinitto.helloCall.entity.HelloCallTimeLog; -import com.example.sinitto.member.entity.Sinitto; +import com.example.sinitto.member.entity.Member; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; import java.util.Optional; public interface HelloCallTimeLogRepository extends JpaRepository { - Optional findBySinittoAndAndHelloCallId(Sinitto sinitto, Long helloCallId); - List findAllByHelloCallId(Long helloCallId); - Optional findTopBySinittoAndHelloCallOrderByStartDateAndTimeDesc(Sinitto sinitto, HelloCall helloCall); + Optional findByMemberAndHelloCallId(Member member, Long helloCallId); + + Optional findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(Member member, HelloCall helloCall); } diff --git a/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java b/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java index 307c3a61..7eed19b3 100644 --- a/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java +++ b/src/main/java/com/example/sinitto/helloCall/service/HelloCallService.java @@ -16,11 +16,14 @@ import com.example.sinitto.helloCall.repository.TimeSlotRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.entity.Sinitto; import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; -import com.example.sinitto.sinitto.exception.SinittoNotFoundException; -import com.example.sinitto.sinitto.repository.SinittoRepository; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.exception.NotEnoughPointException; +import com.example.sinitto.point.exception.PointNotFoundException; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -39,25 +42,27 @@ public class HelloCallService { private final TimeSlotRepository timeSlotRepository; private final SeniorRepository seniorRepository; private final MemberRepository memberRepository; - private final SinittoRepository sinittoRepository; private final HelloCallTimeLogRepository helloCallTimeLogRepository; + private final PointRepository pointRepository; + private final PointLogRepository pointLogRepository; public HelloCallService(HelloCallRepository helloCallRepository, TimeSlotRepository timeSlotRepository, - SeniorRepository seniorRepository, MemberRepository memberRepository, SinittoRepository sinittoRepository, - HelloCallTimeLogRepository helloCallTimeLogRepository) { + SeniorRepository seniorRepository, MemberRepository memberRepository, HelloCallTimeLogRepository helloCallTimeLogRepository, + PointRepository pointRepository, PointLogRepository pointLogRepository) { this.helloCallRepository = helloCallRepository; this.timeSlotRepository = timeSlotRepository; this.seniorRepository = seniorRepository; this.memberRepository = memberRepository; - this.sinittoRepository = sinittoRepository; this.helloCallTimeLogRepository = helloCallTimeLogRepository; + this.pointRepository = pointRepository; + this.pointLogRepository = pointLogRepository; } @Transactional public void createHelloCallByGuard(Long memberId, HelloCallRequest helloCallRequest) { Senior senior = seniorRepository.findByIdAndMemberId(helloCallRequest.seniorId(), memberId) - .orElseThrow(() -> new SeniorNotFoundException("시니어를 찾을 수 없습니다.")); + .orElseThrow(() -> new SeniorNotFoundException("보호자님과 연관된 시니어가 아니거나, 시니어를 찾을 수 없습니다.")); if (helloCallRepository.existsBySeniorAndStatusIn(senior, List.of(HelloCall.Status.WAITING, HelloCall.Status.IN_PROGRESS))) { throw new HelloCallAlreadyExistsException("이미 해당 시니어에게 할당되어 대기중 또는 진행중인 안부 전화 서비스가 존재합니다."); @@ -72,6 +77,23 @@ public void createHelloCallByGuard(Long memberId, HelloCallRequest helloCallRequ timeSlotRequest.endTime(), savedHelloCall); timeSlotRepository.save(timeSlot); } + + Point point = pointRepository.findByMemberIdWithWriteLock(memberId) + .orElseThrow(() -> new PointNotFoundException("멤버에 연관된 포인트가 없습니다.")); + + if (!point.isSufficientForDeduction(helloCall.getPrice())) { + throw new NotEnoughPointException("포인트가 부족합니다."); + } + + point.deduct(helloCall.getPrice()); + + pointLogRepository.save( + new PointLog( + PointLog.Content.SPEND_COMPLETE_HELLO_CALL.getMessage(), + senior.getMember(), + helloCall.getPrice(), + PointLog.Status.SPEND_COMPLETE + )); } @Transactional @@ -132,9 +154,7 @@ public void updateHelloCallByGuard(Long memberId, Long helloCallId, HelloCallDet Member member = memberRepository.findById(memberId) .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); - if (helloCall.checkUnAuthorization(member)) { - throw new UnauthorizedException("안부전화 정보를 수정할 권한이 없습니다."); - } + helloCall.checkGuardIsCorrect(member); helloCall.updateHelloCall(helloCallDetailUpdateRequest.startDate(), helloCallDetailUpdateRequest.endDate(), helloCallDetailUpdateRequest.price(), helloCallDetailUpdateRequest.serviceTime(), helloCallDetailUpdateRequest.requirement()); @@ -161,9 +181,20 @@ public void deleteHellCallByGuard(Long memberId, Long helloCallId) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); - if (helloCall.checkUnAuthorization(member)) { - throw new UnauthorizedException("안부전화 신청을 취소할 권한이 없습니다."); - } + helloCall.checkGuardIsCorrect(member); + + Point point = pointRepository.findByMemberIdWithWriteLock(memberId) + .orElseThrow(() -> new PointNotFoundException("멤버에 연관된 포인트가 없습니다.")); + + point.earn(helloCall.getPrice()); + + pointLogRepository.save( + new PointLog( + PointLog.Content.SPEND_CANCEL_HELLO_CALL.getMessage(), + member, + helloCall.getPrice(), + PointLog.Status.SPEND_CANCEL) + ); helloCall.checkStatusIsWaiting(); helloCallRepository.delete(helloCall); @@ -177,9 +208,7 @@ public List readHelloCallTimeLogByGuard(Long memberId, Member member = memberRepository.findById(memberId) .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); - if (helloCall.checkUnAuthorization(member)) { - throw new UnauthorizedException("안부전화 로그를 조회할 권한이 없습니다."); - } + helloCall.checkGuardIsCorrect(member); List helloCallTimeLogs = helloCallTimeLogRepository.findAllByHelloCallId(helloCallId); @@ -209,7 +238,7 @@ public HelloCallReportResponse readHelloCallReportByGuard(Long memberId, Long he } return new HelloCallReportResponse(helloCall.getStartDate(), - helloCall.getEndDate(), helloCall.getSinittoName(), helloCall.getReport()); + helloCall.getEndDate(), helloCall.getMemberName(), helloCall.getReport()); } @Transactional @@ -224,11 +253,19 @@ public void makeCompleteHelloCallByGuard(Long memberId, Long helloCallId) { helloCall.changeStatusToComplete(); - Sinitto earnedSinitto = helloCall.getSinitto(); + Point sinittoPoint = pointRepository.findByMember(helloCall.getMember()) + .orElseThrow(() -> new PointNotFoundException("포인트 적립 받을 시니또와 연관된 포인트가 없습니다")); - //earnedSinitto에게 포인트 지급 로직 필요합니다. - } + sinittoPoint.earn(helloCall.getPrice()); + pointLogRepository.save( + new PointLog( + PointLog.Content.COMPLETE_HELLO_CALL_AND_EARN.getMessage(), + sinittoPoint.getMember(), + helloCall.getPrice(), + PointLog.Status.EARN) + ); + } @Transactional(readOnly = true) public List readAllHelloCallReportByAdmin() { @@ -239,7 +276,7 @@ public List readAllHelloCallReportByAdmin() { for (HelloCall helloCall : helloCalls) { if (helloCall.checkReportIsNotNull()) { HelloCallReportResponse response = new HelloCallReportResponse(helloCall.getStartDate(), - helloCall.getEndDate(), helloCall.getSinittoName(), helloCall.getReport()); + helloCall.getEndDate(), helloCall.getMemberName(), helloCall.getReport()); helloCallReportResponses.add(response); } } @@ -251,45 +288,52 @@ public void acceptHelloCallBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); - Sinitto sinitto = sinittoRepository.findByMemberId(memberId) - .orElseThrow(() -> new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다.")); + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버가 없습니다.")); + + if (!member.isSinitto()) { + throw new UnauthorizedException("시니또가 아닙니다."); + } helloCall.changeStatusToInProgress(); - helloCall.setSinitto(sinitto); + helloCall.setMember(member); } @Transactional - public HelloCallTimeResponse writeHelloCallStartTimeBySinitto(Long memberId, Long helloCallId) { + public void writeHelloCallStartTimeBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); - Sinitto sinitto = sinittoRepository.findByMemberId(memberId) - .orElseThrow(() -> new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다.")); + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + + helloCall.checkMemberIsRightSinitto(member); Optional recentLog = helloCallTimeLogRepository - .findTopBySinittoAndHelloCallOrderByStartDateAndTimeDesc(sinitto, helloCall); + .findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(member, helloCall); if (recentLog.isPresent() && recentLog.get().getEndDateAndTime() == null) { throw new TimeLogSequenceException("이미 시작된 안부전화가 있습니다. 종료를 먼저 완료해주세요."); } - HelloCallTimeLog helloCallTimeLog = new HelloCallTimeLog(helloCall, sinitto); + HelloCallTimeLog helloCallTimeLog = new HelloCallTimeLog(helloCall, member); helloCallTimeLog.setStartDateAndTime(LocalDateTime.now()); - HelloCallTimeLog savedHelloCallTimeLog = helloCallTimeLogRepository.save(helloCallTimeLog); - return new HelloCallTimeResponse(savedHelloCallTimeLog.getStartDateAndTime()); + helloCallTimeLogRepository.save(helloCallTimeLog); } @Transactional - public HelloCallTimeResponse writeHelloCallEndTimeBySinitto(Long memberId, Long helloCallId) { + public void writeHelloCallEndTimeBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); - Sinitto sinitto = sinittoRepository.findByMemberId(memberId) - .orElseThrow(() -> new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다.")); + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + + helloCall.checkMemberIsRightSinitto(member); HelloCallTimeLog helloCallTimeLog = helloCallTimeLogRepository - .findTopBySinittoAndHelloCallOrderByStartDateAndTimeDesc(sinitto, helloCall) + .findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(member, helloCall) .orElseThrow(() -> new HelloCallNotFoundException("안부전화 로그를 찾을 수 없습니다.")); if (helloCallTimeLog.getEndDateAndTime() != null) { @@ -297,8 +341,6 @@ public HelloCallTimeResponse writeHelloCallEndTimeBySinitto(Long memberId, Long } helloCallTimeLog.setEndDateAndTime(LocalDateTime.now()); - - return new HelloCallTimeResponse(helloCallTimeLog.getEndDateAndTime()); } @Transactional @@ -306,23 +348,25 @@ public void cancelHelloCallBySinitto(Long memberId, Long helloCallId) { HelloCall helloCall = helloCallRepository.findById(helloCallId) .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); - if (!sinittoRepository.existsByMemberId(memberId)) { - throw new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다."); - } + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + + helloCall.checkMemberIsRightSinitto(member); helloCall.changeStatusToWaiting(); - helloCall.setSinitto(null); + helloCall.setMember(null); } @Transactional - public void SendReportBySinitto(Long memberId, HelloCallReportRequest helloCallReportRequest) { + public void sendReportBySinitto(Long memberId, HelloCallReportRequest helloCallReportRequest) { HelloCall helloCall = helloCallRepository.findById(helloCallReportRequest.helloCallId()) .orElseThrow(() -> new HelloCallNotFoundException("id에 해당하는 안부전화 정보를 찾을 수 없습니다.")); - Sinitto sinitto = sinittoRepository.findByMemberId(memberId) - .orElseThrow(() -> new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다.")); + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); + + helloCall.checkMemberIsRightSinitto(member); - helloCall.checkSiniitoIsSame(sinitto); if (helloCall.checkIsNotAfterEndDate()) { throw new CompletionConditionNotFulfilledException("서비스 종료 날짜보다 이른 날짜에 종료할 수 없습니다."); } @@ -333,10 +377,10 @@ public void SendReportBySinitto(Long memberId, HelloCallReportRequest helloCallR @Transactional(readOnly = true) public List readOwnHelloCallBySinitto(Long memberId) { - Sinitto sinitto = sinittoRepository.findByMemberId(memberId) - .orElseThrow(() -> new SinittoNotFoundException("id에 해당하는 시니또를 찾을 수 없습니다.")); + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("id에 해당하는 멤버를 찾을 수 없습니다.")); - List helloCalls = helloCallRepository.findAllBySinitto(sinitto); + List helloCalls = helloCallRepository.findAllByMember(member); List helloCallResponses = new ArrayList<>(); @@ -349,5 +393,4 @@ public List readOwnHelloCallBySinitto(Long memberId) { return helloCallResponses; } - } diff --git a/src/main/java/com/example/sinitto/member/entity/Member.java b/src/main/java/com/example/sinitto/member/entity/Member.java index 29139b03..8093d9b2 100644 --- a/src/main/java/com/example/sinitto/member/entity/Member.java +++ b/src/main/java/com/example/sinitto/member/entity/Member.java @@ -37,6 +37,11 @@ public void updateMember(String name, String email, String phoneNumber) { this.phoneNumber = phoneNumber; } + public String getDepositMessage() { + + return name.substring(0, 3) + phoneNumber.substring(phoneNumber.length() - 4); + } + public Long getId() { return id; } diff --git a/src/main/java/com/example/sinitto/member/entity/Senior.java b/src/main/java/com/example/sinitto/member/entity/Senior.java index bba956e3..a2bd2e21 100644 --- a/src/main/java/com/example/sinitto/member/entity/Senior.java +++ b/src/main/java/com/example/sinitto/member/entity/Senior.java @@ -31,6 +31,10 @@ public Senior(String name, String phoneNumber, Member member) { protected Senior() { } + public boolean isNotGuard(Long memberId) { + return !this.member.getId().equals(memberId); + } + public void updateSenior(String name, String phoneNumber) { this.name = name; this.phoneNumber = phoneNumber; diff --git a/src/main/java/com/example/sinitto/member/service/MemberService.java b/src/main/java/com/example/sinitto/member/service/MemberService.java index 324f0a6f..f473aa17 100644 --- a/src/main/java/com/example/sinitto/member/service/MemberService.java +++ b/src/main/java/com/example/sinitto/member/service/MemberService.java @@ -12,6 +12,8 @@ import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.exception.NotUniqueException; import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.repository.PointRepository; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -24,15 +26,15 @@ public class MemberService implements MemberIdProvider { private final TokenService tokenService; private final KakaoApiService kakaoApiService; private final KakaoTokenService kakaoTokenService; + private final PointRepository pointRepository; private final RedisTemplate redisTemplate; - - public MemberService(MemberRepository memberRepository, TokenService tokenService, KakaoApiService kakaoApiService, KakaoTokenService kakaoTokenService - ,RedisTemplate redisTemplate) { + public MemberService(MemberRepository memberRepository, TokenService tokenService, KakaoApiService kakaoApiService, KakaoTokenService kakaoTokenService, PointRepository pointRepository, RedisTemplate redisTemplate) { this.memberRepository = memberRepository; this.tokenService = tokenService; this.kakaoApiService = kakaoApiService; this.kakaoTokenService = kakaoTokenService; + this.pointRepository = pointRepository; this.redisTemplate = redisTemplate; } @@ -75,6 +77,8 @@ public RegisterResponse registerNewMember(String name, String phoneNumber, Strin Member newMember = new Member(name, phoneNumber, email, isSinitto); memberRepository.save(newMember); + pointRepository.save(new Point(0, newMember)); + String accessToken = tokenService.generateAccessToken(email); String refreshToken = tokenService.generateRefreshToken(email); diff --git a/src/main/java/com/example/sinitto/point/controller/PointAdminController.java b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java new file mode 100644 index 00000000..ae8b530e --- /dev/null +++ b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java @@ -0,0 +1,107 @@ +package com.example.sinitto.point.controller; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.exception.MemberNotFoundException; +import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.dto.PointLogWithBankInfo; +import com.example.sinitto.point.dto.PointLogWithDepositMessage; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.service.PointAdminService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.ArrayList; +import java.util.List; + +@Controller +public class PointAdminController { + + private final PointAdminService pointAdminService; + private final MemberRepository memberRepository; + + public PointAdminController(PointAdminService pointAdminService, MemberRepository memberRepository) { + this.pointAdminService = pointAdminService; + this.memberRepository = memberRepository; + } + + @GetMapping("/admin/point/charge") + public String showAllChargeRequest(Model model) { + + List pointLogs = pointAdminService.readAllNotCompletedPointChargeRequest(); + List logWithDepositMessages = new ArrayList<>(); + + for (PointLog pointLog : pointLogs) { + Member member = memberRepository.findById(pointLog.getMember().getId()) + .orElseThrow(() -> new MemberNotFoundException("멤버를 찾을 수 없습니다")); + + PointLogWithDepositMessage pointLogWithDepositMessage = new PointLogWithDepositMessage( + pointLog.getId(), + pointLog.getPrice(), + pointLog.getPostTime(), + pointLog.getStatus(), + member.getDepositMessage() + ); + + logWithDepositMessages.add(pointLogWithDepositMessage); + } + model.addAttribute("logWithDepositMessages", logWithDepositMessages); + + return "point/charge"; + } + + @PostMapping("/admin/point/charge/waiting/{pointLogId}") + public String changeToWaiting(@PathVariable Long pointLogId) { + + pointAdminService.changeChargeLogToWaiting(pointLogId); + return "redirect:/admin/point/charge"; + } + + @PostMapping("/admin/point/charge/complete/{pointLogId}") + public String changeToCompleteAndEarn(@PathVariable Long pointLogId) { + + pointAdminService.earnPointAndChangeToChargeComplete(pointLogId); + return "redirect:/admin/point/charge"; + } + + @PostMapping("/admin/point/charge/fail/{pointLogId}") + public String changeToFail(@PathVariable Long pointLogId) { + + pointAdminService.changeChargeLogToFail(pointLogId); + return "redirect:/admin/point/charge"; + } + + @GetMapping("/admin/point/withdraw") + public String showAllWithdrawRequest(Model model) { + + List logWithBankInfos = pointAdminService.getPointLogWithBankInfo(); + + model.addAttribute("logWithBankInfos", logWithBankInfos); + + return "point/withdraw"; + } + + @PostMapping("/admin/point/withdraw/waiting/{pointLogId}") + public String changeWithdrawLogToWaiting(@PathVariable Long pointLogId) { + + pointAdminService.changeWithdrawLogToWaiting(pointLogId); + return "redirect:/admin/point/withdraw"; + } + + @PostMapping("/admin/point/withdraw/complete/{pointLogId}") + public String changeWithdrawLogToCompleteAndEarn(@PathVariable Long pointLogId) { + + pointAdminService.changeWithdrawLogToComplete(pointLogId); + return "redirect:/admin/point/withdraw"; + } + + @PostMapping("/admin/point/withdraw/fail/{pointLogId}") + public String changeWithdrawLogToFail(@PathVariable Long pointLogId) { + + pointAdminService.changeWithdrawLogToFail(pointLogId); + return "redirect:/admin/point/withdraw"; + } + +} diff --git a/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java b/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java new file mode 100644 index 00000000..c6d6c4c3 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/controller/PointAdminControllerAdvice.java @@ -0,0 +1,43 @@ +package com.example.sinitto.point.controller; + +import com.example.sinitto.point.exception.InvalidPointLogStatusException; +import com.example.sinitto.point.exception.PointLogNotFoundException; +import com.example.sinitto.point.exception.PointNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.net.URI; + +@ControllerAdvice(basePackages = "com.example.sinitto.point") +public class PointAdminControllerAdvice { + + @ExceptionHandler(PointNotFoundException.class) + public ResponseEntity handlePointNotFoundException(PointNotFoundException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); + problemDetail.setType(URI.create("/errors/not-found")); + problemDetail.setTitle("Not Found"); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); + } + + @ExceptionHandler(InvalidPointLogStatusException.class) + public ResponseEntity handleInvalidPointStatusException(InvalidPointLogStatusException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); + problemDetail.setType(URI.create("/errors/conflict")); + problemDetail.setTitle("Conflict"); + return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); + } + + @ExceptionHandler(PointLogNotFoundException.class) + public ResponseEntity handlePointLogNotFoundException(PointLogNotFoundException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); + problemDetail.setType(URI.create("/errors/not-found")); + problemDetail.setTitle("Not Found"); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); + } +} diff --git a/src/main/java/com/example/sinitto/point/controller/PointController.java b/src/main/java/com/example/sinitto/point/controller/PointController.java index 1fe64765..4806f7a4 100644 --- a/src/main/java/com/example/sinitto/point/controller/PointController.java +++ b/src/main/java/com/example/sinitto/point/controller/PointController.java @@ -1,54 +1,61 @@ package com.example.sinitto.point.controller; +import com.example.sinitto.common.annotation.MemberId; +import com.example.sinitto.point.dto.PointChargeResponse; import com.example.sinitto.point.dto.PointLogResponse; import com.example.sinitto.point.dto.PointRequest; import com.example.sinitto.point.dto.PointResponse; +import com.example.sinitto.point.service.PointService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; -import java.util.List; - @RestController @RequestMapping("/api/points") -@Tag(name = "[미구현]포인트", description = "포인트 API") +@Tag(name = "포인트", description = "포인트 API") public class PointController { - @Operation(summary = "포인트 추가", description = "(임시) 관리자가 직접 추가 - 이후 외부 결제 api 연동") - @PutMapping("/add") - public ResponseEntity addPoints(@RequestBody PointRequest request) { - // 임시 응답 - return ResponseEntity.ok("포인트가 추가되었습니다."); - } + private final PointService pointService; - @Operation(summary = "포인트 차감", description = "요청사항 등록 시 포인트를 차감합니다.") - @PutMapping("/deduct") - public ResponseEntity deductPoints(@RequestBody PointRequest request) { - // 임시 응답 - return ResponseEntity.ok("포인트가 차감되었습니다."); + public PointController(PointService pointService) { + this.pointService = pointService; } @Operation(summary = "포인트 조회", description = "시니또, 보호자가 본인의 포인트를 조회합니다.") @GetMapping() - public ResponseEntity getPoint() { - // 임시 응답 - return ResponseEntity.ok(new PointResponse(1000)); + public ResponseEntity getPoint(@MemberId Long memberId) { + + return ResponseEntity.ok(pointService.getPoint(memberId)); + } + + @Operation(summary = "포인트 충전 요청", description = "관리자가 직접 추가 - 바로 충전 되는거 아님. 신청->대기->완료 완료시점에 충전 됨") + @PutMapping("/charge") + public ResponseEntity savePointChargeRequest(@MemberId Long memberId, + @RequestBody PointRequest request) { + + return ResponseEntity.ok(pointService.savePointChargeRequest(memberId, request.price())); } @Operation(summary = "포인트 출금 요청", description = "시니또가 포인트 출금을 요청합니다.") @PostMapping("/withdraw") - public ResponseEntity requestPointWithdraw(@RequestBody PointRequest request) { - // 임시 응답 - return ResponseEntity.ok("포인트 출금 요청이 완료되었습니다."); + public ResponseEntity savePointWithdrawRequest(@MemberId Long memberId, + @RequestBody PointRequest request) { + + pointService.savePointWithdrawRequest(memberId, request.price()); + return ResponseEntity.ok().build(); } @Operation(summary = "포인트 로그 조회", description = "포인트 로그를 조회합니다.") @GetMapping("/logs") - public ResponseEntity> getPointLogs() { - // 임시 응답 - return ResponseEntity.ok(new ArrayList<>()); + public ResponseEntity> getPointLogs(@MemberId Long memberId, + @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { + + return ResponseEntity.ok(pointService.getPointLogs(memberId, pageable)); } } diff --git a/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java b/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java new file mode 100644 index 00000000..893451f7 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/controller/PointControllerAdvice.java @@ -0,0 +1,33 @@ +package com.example.sinitto.point.controller; + +import com.example.sinitto.point.exception.NotEnoughPointException; +import com.example.sinitto.point.exception.PointNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.net.URI; + +@RestControllerAdvice(basePackages = "com.example.sinitto.point") +public class PointControllerAdvice { + + @ExceptionHandler(PointNotFoundException.class) + public ResponseEntity handlePointNotFoundException(PointNotFoundException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); + problemDetail.setType(URI.create("/errors/not-found")); + problemDetail.setTitle("Not Found"); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); + } + + @ExceptionHandler(NotEnoughPointException.class) + public ResponseEntity handleNotEnoughPointException(NotEnoughPointException e) { + + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, e.getMessage()); + problemDetail.setType(URI.create("/errors/conflict")); + problemDetail.setTitle("Conflict"); + return ResponseEntity.status(HttpStatus.CONFLICT).body(problemDetail); + } +} diff --git a/src/main/java/com/example/sinitto/point/dto/PointChargeResponse.java b/src/main/java/com/example/sinitto/point/dto/PointChargeResponse.java new file mode 100644 index 00000000..63916b11 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/dto/PointChargeResponse.java @@ -0,0 +1,6 @@ +package com.example.sinitto.point.dto; + +public record PointChargeResponse( + String depositMessage +) { +} diff --git a/src/main/java/com/example/sinitto/point/dto/PointLogResponse.java b/src/main/java/com/example/sinitto/point/dto/PointLogResponse.java index 2eea0f96..f563100c 100644 --- a/src/main/java/com/example/sinitto/point/dto/PointLogResponse.java +++ b/src/main/java/com/example/sinitto/point/dto/PointLogResponse.java @@ -1,10 +1,13 @@ package com.example.sinitto.point.dto; +import com.example.sinitto.point.entity.PointLog; + import java.time.LocalDateTime; public record PointLogResponse( LocalDateTime postTime, - String requirementContent, + String content, int price, - String type) { + PointLog.Status status +) { } diff --git a/src/main/java/com/example/sinitto/point/dto/PointLogWithBankInfo.java b/src/main/java/com/example/sinitto/point/dto/PointLogWithBankInfo.java new file mode 100644 index 00000000..c169564a --- /dev/null +++ b/src/main/java/com/example/sinitto/point/dto/PointLogWithBankInfo.java @@ -0,0 +1,15 @@ +package com.example.sinitto.point.dto; + +import com.example.sinitto.point.entity.PointLog; + +import java.time.LocalDateTime; + +public record PointLogWithBankInfo( + Long pointLogId, + int price, + LocalDateTime postTime, + PointLog.Status status, + String bankName, + String bankAccountNumber +) { +} diff --git a/src/main/java/com/example/sinitto/point/dto/PointLogWithDepositMessage.java b/src/main/java/com/example/sinitto/point/dto/PointLogWithDepositMessage.java new file mode 100644 index 00000000..1c57f776 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/dto/PointLogWithDepositMessage.java @@ -0,0 +1,14 @@ +package com.example.sinitto.point.dto; + +import com.example.sinitto.point.entity.PointLog; + +import java.time.LocalDateTime; + +public record PointLogWithDepositMessage( + Long pointLogId, + int price, + LocalDateTime postTime, + PointLog.Status status, + String depositMessage +) { +} diff --git a/src/main/java/com/example/sinitto/point/dto/PointRequest.java b/src/main/java/com/example/sinitto/point/dto/PointRequest.java index 7e637dab..ea697a7a 100644 --- a/src/main/java/com/example/sinitto/point/dto/PointRequest.java +++ b/src/main/java/com/example/sinitto/point/dto/PointRequest.java @@ -1,5 +1,6 @@ package com.example.sinitto.point.dto; public record PointRequest( - int price) { + int price +) { } diff --git a/src/main/java/com/example/sinitto/point/dto/PointResponse.java b/src/main/java/com/example/sinitto/point/dto/PointResponse.java index a90d8582..9849c32e 100644 --- a/src/main/java/com/example/sinitto/point/dto/PointResponse.java +++ b/src/main/java/com/example/sinitto/point/dto/PointResponse.java @@ -1,5 +1,6 @@ package com.example.sinitto.point.dto; public record PointResponse( - int price) { + int price +) { } diff --git a/src/main/java/com/example/sinitto/point/entity/Point.java b/src/main/java/com/example/sinitto/point/entity/Point.java index f53d09cc..5eab55b1 100644 --- a/src/main/java/com/example/sinitto/point/entity/Point.java +++ b/src/main/java/com/example/sinitto/point/entity/Point.java @@ -1,6 +1,7 @@ package com.example.sinitto.point.entity; import com.example.sinitto.member.entity.Member; +import com.example.sinitto.point.exception.NotEnoughPointException; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; @@ -20,4 +21,39 @@ public class Point { @OnDelete(action = OnDeleteAction.CASCADE) private Member member; + public Point(int price, Member member) { + this.price = price; + this.member = member; + } + + protected Point() { + + } + + public int getPrice() { + return price; + } + + public Member getMember() { + return member; + } + + public void earn(int priceToAdd) { + + this.price += priceToAdd; + } + + public void deduct(int priceToDeduct) { + + if (this.price < priceToDeduct) { + throw new NotEnoughPointException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", this.price)); + } + + this.price -= priceToDeduct; + } + + public boolean isSufficientForDeduction(int priceToDeduct) { + + return this.price >= priceToDeduct; + } } diff --git a/src/main/java/com/example/sinitto/point/entity/PointLog.java b/src/main/java/com/example/sinitto/point/entity/PointLog.java index edcf6d40..440acca6 100644 --- a/src/main/java/com/example/sinitto/point/entity/PointLog.java +++ b/src/main/java/com/example/sinitto/point/entity/PointLog.java @@ -1,6 +1,7 @@ package com.example.sinitto.point.entity; import com.example.sinitto.member.entity.Member; +import com.example.sinitto.point.exception.InvalidPointLogStatusException; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; @@ -18,15 +19,137 @@ public class PointLog { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotNull + private String content; + @NotNull private int price; @CreatedDate private LocalDateTime postTime; @NotNull - private String type; + @Enumerated(EnumType.STRING) + private PointLog.Status status; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") @NotNull @OnDelete(action = OnDeleteAction.CASCADE) private Member member; + + public PointLog(String content, Member member, int price, Status status) { + this.content = content; + this.member = member; + this.price = price; + this.status = status; + } + + protected PointLog() { + + } + + public void changeStatusToChargeWaiting() { + + checkStatusChange(Status.CHARGE_REQUEST); + + this.status = Status.CHARGE_WAITING; + } + + public void changeStatusToChargeComplete() { + + checkStatusChange(Status.CHARGE_WAITING); + + this.status = Status.CHARGE_COMPLETE; + } + + public void changeStatusToChargeFail() { + + checkStatusChange(Status.CHARGE_WAITING); + + this.status = Status.CHARGE_FAIL; + } + + public void changeStatusToWithdrawWaiting() { + + checkStatusChange(Status.WITHDRAW_REQUEST); + + this.status = Status.WITHDRAW_WAITING; + } + + public void changeStatusToWithdrawComplete() { + + checkStatusChange(Status.WITHDRAW_WAITING); + + this.status = Status.WITHDRAW_COMPLETE; + } + + public void changeStatusToWithdrawFail() { + + checkStatusChange(Status.WITHDRAW_WAITING); + + this.status = Status.WITHDRAW_FAIL_AND_RESTORE_POINT; + } + + private void checkStatusChange(Status wantStatus) { + + if (this.status != wantStatus) { + throw new InvalidPointLogStatusException(String.format("현재 %s 상태입니다. 이 상태에서는 %s 로의 전환이 불가합니다.", this.status, wantStatus)); + } + } + + public Long getId() { + return id; + } + + public Member getMember() { + return member; + } + + public LocalDateTime getPostTime() { + return postTime; + } + + public int getPrice() { + return price; + } + + public Status getStatus() { + return status; + } + + public String getContent() { + return content; + } + + public enum Status { + EARN, + SPEND_COMPLETE, + SPEND_CANCEL, + WITHDRAW_REQUEST, + WITHDRAW_WAITING, + WITHDRAW_COMPLETE, + WITHDRAW_FAIL_AND_RESTORE_POINT, + CHARGE_REQUEST, + CHARGE_WAITING, + CHARGE_COMPLETE, + CHARGE_FAIL + } + + public enum Content { + COMPLETE_CALLBACK_AND_EARN("콜백 완료로 인한 포인트 적립"), + COMPLETE_HELLO_CALL_AND_EARN("안부 전화 완료로 인한 포인트 적립"), + SPEND_COMPLETE_CALLBACK("콜백 신청으로 인한 포인트 차감"), + SPEND_COMPLETE_HELLO_CALL("안부전화 신청으로 인한 포인트 차감"), + SPEND_CANCEL_HELLO_CALL("안부전화 신청 취소로 인한 포인트 환불"), + CHARGE_REQUEST("포인트 충전"), + WITHDRAW_REQUEST("포인트 출금"); + + private final String message; + + Content(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + } diff --git a/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java b/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java new file mode 100644 index 00000000..344141cb --- /dev/null +++ b/src/main/java/com/example/sinitto/point/exception/InvalidPointLogStatusException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.point.exception; + +public class InvalidPointLogStatusException extends RuntimeException { + + public InvalidPointLogStatusException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java b/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java new file mode 100644 index 00000000..882f119a --- /dev/null +++ b/src/main/java/com/example/sinitto/point/exception/NotEnoughPointException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.point.exception; + +public class NotEnoughPointException extends RuntimeException { + + public NotEnoughPointException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java b/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java new file mode 100644 index 00000000..809503c3 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/exception/PointLogNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.point.exception; + +public class PointLogNotFoundException extends RuntimeException { + + public PointLogNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java b/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java new file mode 100644 index 00000000..732e19cc --- /dev/null +++ b/src/main/java/com/example/sinitto/point/exception/PointNotFoundException.java @@ -0,0 +1,8 @@ +package com.example.sinitto.point.exception; + +public class PointNotFoundException extends RuntimeException { + + public PointNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/point/repository/PointLogRepository.java b/src/main/java/com/example/sinitto/point/repository/PointLogRepository.java new file mode 100644 index 00000000..665e0fc5 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/repository/PointLogRepository.java @@ -0,0 +1,16 @@ +package com.example.sinitto.point.repository; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.point.entity.PointLog; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PointLogRepository extends JpaRepository { + + Page findAllByMember(Member member, Pageable pageable); + + List findAllByStatusInOrderByPostTimeDesc(List statuses); +} diff --git a/src/main/java/com/example/sinitto/point/repository/PointRepository.java b/src/main/java/com/example/sinitto/point/repository/PointRepository.java new file mode 100644 index 00000000..1f3a9aa7 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/repository/PointRepository.java @@ -0,0 +1,21 @@ +package com.example.sinitto.point.repository; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.point.entity.Point; +import jakarta.persistence.LockModeType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface PointRepository extends JpaRepository { + + Optional findByMember(Member member); + + Optional findByMemberId(Long memberId); + + @Lock(LockModeType.PESSIMISTIC_WRITE) + @Query("SELECT p FROM Point p WHERE p.member.id = :memberId") + Optional findByMemberIdWithWriteLock(Long memberId); +} diff --git a/src/main/java/com/example/sinitto/point/service/PointAdminService.java b/src/main/java/com/example/sinitto/point/service/PointAdminService.java new file mode 100644 index 00000000..940dccf3 --- /dev/null +++ b/src/main/java/com/example/sinitto/point/service/PointAdminService.java @@ -0,0 +1,121 @@ +package com.example.sinitto.point.service; + +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.point.dto.PointLogWithBankInfo; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.exception.PointLogNotFoundException; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class PointAdminService { + + private final PointLogRepository pointLogRepository; + private final PointRepository pointRepository; + private final SinittoBankInfoRepository sinittoBankInfoRepository; + + public PointAdminService(PointLogRepository pointLogRepository, PointRepository pointRepository, SinittoBankInfoRepository sinittoBankInfoRepository) { + this.pointLogRepository = pointLogRepository; + this.pointRepository = pointRepository; + this.sinittoBankInfoRepository = sinittoBankInfoRepository; + } + + public List readAllNotCompletedPointChargeRequest() { + + return pointLogRepository.findAllByStatusInOrderByPostTimeDesc(List.of(PointLog.Status.CHARGE_WAITING, PointLog.Status.CHARGE_REQUEST, PointLog.Status.CHARGE_COMPLETE, PointLog.Status.CHARGE_FAIL)); + } + + @Transactional + public void changeChargeLogToWaiting(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다")); + + pointLog.changeStatusToChargeWaiting(); + } + + @Transactional + public void earnPointAndChangeToChargeComplete(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + + Point point = pointRepository.findByMember(pointLog.getMember()) + .orElseThrow(() -> new PointLogNotFoundException("포인트를 찾을 수 없습니다.")); + + pointLog.changeStatusToChargeComplete(); + point.earn(pointLog.getPrice()); + } + + @Transactional + public void changeChargeLogToFail(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + + pointLog.changeStatusToChargeFail(); + } + + @Transactional + public void changeWithdrawLogToWaiting(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + + pointLog.changeStatusToWithdrawWaiting(); + } + + @Transactional + public void changeWithdrawLogToComplete(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + + pointLog.changeStatusToWithdrawComplete(); + } + + @Transactional + public void changeWithdrawLogToFail(Long pointLogId) { + + PointLog pointLog = pointLogRepository.findById(pointLogId) + .orElseThrow(() -> new PointLogNotFoundException("포인트 로그를 찾을 수 없습니다.")); + + Point point = pointRepository.findByMember(pointLog.getMember()) + .orElseThrow(() -> new PointLogNotFoundException("포인트를 찾을 수 없습니다.")); + + point.earn(pointLog.getPrice()); + + pointLog.changeStatusToWithdrawFail(); + } + + @Transactional(readOnly = true) + public List getPointLogWithBankInfo() { + + List withdrawPointLogs = pointLogRepository.findAllByStatusInOrderByPostTimeDesc(List.of(PointLog.Status.WITHDRAW_REQUEST, PointLog.Status.WITHDRAW_WAITING, PointLog.Status.WITHDRAW_COMPLETE, PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT)); + + List logWithBankInfos = new ArrayList<>(); + + for (PointLog pointLog : withdrawPointLogs) { + SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(pointLog.getMember().getId()) + .orElse(new SinittoBankInfo("등록된 계좌 없음", "등록된 계좌 없음", null)); + + PointLogWithBankInfo pointLogWithBankInfo = new PointLogWithBankInfo( + pointLog.getId(), + pointLog.getPrice(), + pointLog.getPostTime(), + pointLog.getStatus(), + sinittoBankInfo.getBankName(), + sinittoBankInfo.getAccountNumber() + ); + logWithBankInfos.add(pointLogWithBankInfo); + } + return logWithBankInfos; + } +} diff --git a/src/main/java/com/example/sinitto/point/service/PointService.java b/src/main/java/com/example/sinitto/point/service/PointService.java new file mode 100644 index 00000000..0348aeda --- /dev/null +++ b/src/main/java/com/example/sinitto/point/service/PointService.java @@ -0,0 +1,102 @@ +package com.example.sinitto.point.service; + +import com.example.sinitto.callback.exception.NotSinittoException; +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.exception.MemberNotFoundException; +import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.dto.PointChargeResponse; +import com.example.sinitto.point.dto.PointLogResponse; +import com.example.sinitto.point.dto.PointResponse; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.exception.NotEnoughPointException; +import com.example.sinitto.point.exception.PointNotFoundException; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; +import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class PointService { + + public static final double WITHDRAWAL_FEE_RATE = 0.8; + private final MemberRepository memberRepository; + private final PointRepository pointRepository; + private final PointLogRepository pointLogRepository; + private final SinittoBankInfoRepository sinittoBankInfoRepository; + + public PointService(MemberRepository memberRepository, PointRepository pointRepository, PointLogRepository pointLogRepository, SinittoBankInfoRepository sinittoBankInfoRepository) { + this.memberRepository = memberRepository; + this.pointRepository = pointRepository; + this.pointLogRepository = pointLogRepository; + this.sinittoBankInfoRepository = sinittoBankInfoRepository; + } + + public PointResponse getPoint(Long memberId) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + + Point point = pointRepository.findByMember(member) + .orElseThrow(() -> new PointNotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); + + return new PointResponse(point.getPrice()); + } + + public Page getPointLogs(Long memberId, Pageable pageable) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + + return pointLogRepository.findAllByMember(member, pageable) + .map(pointLog -> new PointLogResponse( + pointLog.getPostTime(), + pointLog.getContent(), + pointLog.getPrice(), + pointLog.getStatus() + )); + } + + @Transactional + public PointChargeResponse savePointChargeRequest(Long memberId, int price) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + + pointLogRepository.save(new PointLog(PointLog.Content.CHARGE_REQUEST.getMessage(), member, price, PointLog.Status.CHARGE_REQUEST)); + + return new PointChargeResponse(member.getDepositMessage()); + } + + @Transactional + public void savePointWithdrawRequest(Long memberId, int price) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException("요청한 멤버를 찾을 수 없습니다")); + + if (!member.isSinitto()) { + throw new NotSinittoException("출금 요청은 시니또만 가능합니다. 지금 요청은 시니또가 요청하지 않았습니다."); + } + + if (!sinittoBankInfoRepository.existsByMemberId(memberId)) { + throw new SinittoBankInfoNotFoundException("시니또의 은행 계좌 정보가 없습니다. 계좌를 등록해야 합니다."); + } + + Point point = pointRepository.findByMember(member) + .orElseThrow(() -> new PointNotFoundException("요청한 멤버의 포인트를 찾을 수 없습니다")); + + int adjustedPrice = (int) (price * WITHDRAWAL_FEE_RATE); + + if (!point.isSufficientForDeduction(price)) { + throw new NotEnoughPointException(String.format("보유한 포인트(%d) 보다 더 많은 포인트에 대한 출금요청입니다", point.getPrice())); + } + + point.deduct(price); + + pointLogRepository.save(new PointLog(PointLog.Content.WITHDRAW_REQUEST.getMessage(), member, adjustedPrice, PointLog.Status.WITHDRAW_REQUEST)); + } +} diff --git a/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java b/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java index 6fee49bb..da30208d 100644 --- a/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java +++ b/src/main/java/com/example/sinitto/sinitto/controller/SinittoControllerAdvice.java @@ -1,6 +1,6 @@ package com.example.sinitto.sinitto.controller; -import com.example.sinitto.sinitto.exception.SinittoNotFoundException; +import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.http.ResponseEntity; @@ -11,11 +11,11 @@ @RestControllerAdvice(basePackages = "com.example.sinitto.sinitto") public class SinittoControllerAdvice { - @ExceptionHandler(SinittoNotFoundException.class) - public ResponseEntity handleSinittoNotFoundException(SinittoNotFoundException e) { + @ExceptionHandler(SinittoBankInfoNotFoundException.class) + public ResponseEntity handleSinittoNotFoundException(SinittoBankInfoNotFoundException e) { ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); problemDetail.setType(URI.create("/error/sinitto-not-found")); - problemDetail.setTitle("Sinitto Not Found"); + problemDetail.setTitle("SinittoBankInfo Not Found"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetail); } diff --git a/src/main/java/com/example/sinitto/member/entity/Sinitto.java b/src/main/java/com/example/sinitto/sinitto/entity/SinittoBankInfo.java similarity index 80% rename from src/main/java/com/example/sinitto/member/entity/Sinitto.java rename to src/main/java/com/example/sinitto/sinitto/entity/SinittoBankInfo.java index 50e47950..71ceaf2a 100644 --- a/src/main/java/com/example/sinitto/member/entity/Sinitto.java +++ b/src/main/java/com/example/sinitto/sinitto/entity/SinittoBankInfo.java @@ -1,12 +1,13 @@ -package com.example.sinitto.member.entity; +package com.example.sinitto.sinitto.entity; +import com.example.sinitto.member.entity.Member; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; @Entity -public class Sinitto { +public class SinittoBankInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -21,10 +22,10 @@ public class Sinitto { @OnDelete(action = OnDeleteAction.CASCADE) private Member member; - public Sinitto() { + protected SinittoBankInfo() { } - public Sinitto(String bankName, String accountNumber, Member member) { + public SinittoBankInfo(String bankName, String accountNumber, Member member) { this.bankName = bankName; this.accountNumber = accountNumber; this.member = member; diff --git a/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java b/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java new file mode 100644 index 00000000..b7be2b58 --- /dev/null +++ b/src/main/java/com/example/sinitto/sinitto/exception/SinittoBankInfoNotFoundException.java @@ -0,0 +1,7 @@ +package com.example.sinitto.sinitto.exception; + +public class SinittoBankInfoNotFoundException extends RuntimeException { + public SinittoBankInfoNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/sinitto/sinitto/exception/SinittoNotFoundException.java b/src/main/java/com/example/sinitto/sinitto/exception/SinittoNotFoundException.java deleted file mode 100644 index 50923b49..00000000 --- a/src/main/java/com/example/sinitto/sinitto/exception/SinittoNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.sinitto.sinitto.exception; - -public class SinittoNotFoundException extends RuntimeException { - public SinittoNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/com/example/sinitto/sinitto/repository/SinittoRepository.java b/src/main/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepository.java similarity index 54% rename from src/main/java/com/example/sinitto/sinitto/repository/SinittoRepository.java rename to src/main/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepository.java index 1c211fcd..2068c443 100644 --- a/src/main/java/com/example/sinitto/sinitto/repository/SinittoRepository.java +++ b/src/main/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepository.java @@ -1,6 +1,6 @@ package com.example.sinitto.sinitto.repository; -import com.example.sinitto.member.entity.Sinitto; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -8,8 +8,8 @@ @Repository -public interface SinittoRepository extends JpaRepository { - Optional findByMemberId(Long memberId); +public interface SinittoBankInfoRepository extends JpaRepository { + Optional findByMemberId(Long memberId); boolean existsByMemberId(Long memberId); diff --git a/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java b/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java index c423177f..76d48698 100644 --- a/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java +++ b/src/main/java/com/example/sinitto/sinitto/service/SinittoService.java @@ -1,14 +1,14 @@ package com.example.sinitto.sinitto.service; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.entity.Sinitto; import com.example.sinitto.member.exception.MemberNotFoundException; import com.example.sinitto.member.repository.MemberRepository; import com.example.sinitto.sinitto.dto.SinittoBankRequest; import com.example.sinitto.sinitto.dto.SinittoRequest; import com.example.sinitto.sinitto.dto.SinittoResponse; -import com.example.sinitto.sinitto.exception.SinittoNotFoundException; -import com.example.sinitto.sinitto.repository.SinittoRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.sinitto.exception.SinittoBankInfoNotFoundException; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,11 +18,11 @@ public class SinittoService { private final MemberRepository memberRepository; - private final SinittoRepository sinittoRepository; + private final SinittoBankInfoRepository sinittoBankInfoRepository; - public SinittoService(MemberRepository memberRepository, SinittoRepository sinittoRepository) { + public SinittoService(MemberRepository memberRepository, SinittoBankInfoRepository sinittoBankInfoRepository) { this.memberRepository = memberRepository; - this.sinittoRepository = sinittoRepository; + this.sinittoBankInfoRepository = sinittoBankInfoRepository; } @@ -31,8 +31,8 @@ public void createSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankR Member member = memberRepository.findById(memberId).orElseThrow( () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); - Sinitto sinitto = new Sinitto(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber(), member); - sinittoRepository.save(sinitto); + SinittoBankInfo sinittoBankInfo = new SinittoBankInfo(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber(), member); + sinittoBankInfoRepository.save(sinittoBankInfo); } @Transactional(readOnly = true) @@ -40,10 +40,10 @@ public SinittoResponse readSinitto(Long memberId) { Member member = memberRepository.findById(memberId).orElseThrow( () -> new MemberNotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") ); - Sinitto sinitto = sinittoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( + () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); - return new SinittoResponse(member.getName(), member.getPhoneNumber(), member.getEmail(), sinitto.getAccountNumber(), sinitto.getBankName()); + return new SinittoResponse(member.getName(), member.getPhoneNumber(), member.getEmail(), sinittoBankInfo.getAccountNumber(), sinittoBankInfo.getBankName()); } @Transactional @@ -56,10 +56,10 @@ public void updateSinitto(Long memberId, SinittoRequest sinittoRequest) { @Transactional public void updateSinittoBankInfo(Long memberId, SinittoBankRequest sinittoBankRequest) { - Sinitto sinitto = sinittoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( + () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); - sinitto.updateSinitto(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber()); + sinittoBankInfo.updateSinitto(sinittoBankRequest.bankName(), sinittoBankRequest.accountNumber()); } @Transactional @@ -72,17 +72,17 @@ public void deleteSinitto(Long memberId) { @Transactional public void deleteSinittoBankInfo(Long memberId) { - Sinitto sinitto = sinittoRepository.findByMemberId(memberId).orElseThrow( - () -> new SinittoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") + SinittoBankInfo sinittoBankInfo = sinittoBankInfoRepository.findByMemberId(memberId).orElseThrow( + () -> new SinittoBankInfoNotFoundException("이메일에 해당하는 멤버의 계좌정보를 찾을 수 없습니다.") ); - sinittoRepository.delete(sinitto); + sinittoBankInfoRepository.delete(sinittoBankInfo); } @Transactional public List readAllSinitto() { - List sinittos = sinittoRepository.findAll(); + List sinittoBankInfos = sinittoBankInfoRepository.findAll(); - return sinittos.stream() + return sinittoBankInfos.stream() .map(m -> new SinittoResponse(m.getMember().getName(), m.getMember().getPhoneNumber(), m.getMember().getEmail(), m.getAccountNumber(), m.getBankName())) .toList(); } diff --git a/src/main/resources/static/css/point.css b/src/main/resources/static/css/point.css new file mode 100644 index 00000000..824d530b --- /dev/null +++ b/src/main/resources/static/css/point.css @@ -0,0 +1,61 @@ +body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + margin: 0; + padding: 20px; +} + +h1 { + text-align: center; + color: #333; +} + +table { + width: 100%; + border-collapse: collapse; + margin: 20px 0; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +th, td { + padding: 12px; + text-align: left; + border: 1px solid #ddd; + background-color: #fff; +} + +th { + background-color: #4CAF50; + color: white; +} + +tr:nth-child(even) { + background-color: #f9f9f9; +} + +tr:hover { + background-color: #f1f1f1; +} + +button { + background-color: #4CAF50; + color: white; + border: none; + padding: 10px 15px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 14px; + margin: 4px 2px; + cursor: pointer; + border-radius: 4px; + transition: background-color 0.3s; +} + +button:hover { + background-color: #45a049; +} + +form { + display: inline; +} \ No newline at end of file diff --git a/src/main/resources/templates/point/charge.html b/src/main/resources/templates/point/charge.html new file mode 100644 index 00000000..23c22b57 --- /dev/null +++ b/src/main/resources/templates/point/charge.html @@ -0,0 +1,54 @@ + + + + + + 충전 페이지 + + +
+ + + + + + + + + + + + + + + + + + + + +
요청 시간요청된 포인트입금 메세지상태상태전환
요청 시간요청된 포인트입금 메세지상태 + +
+ +
+ + +
+ +
+ + +
+ +
+
+
+ + diff --git a/src/main/resources/templates/point/withdraw.html b/src/main/resources/templates/point/withdraw.html new file mode 100644 index 00000000..2300c9e9 --- /dev/null +++ b/src/main/resources/templates/point/withdraw.html @@ -0,0 +1,56 @@ + + + + + + 출금 페이지 + + +
+ + + + + + + + + + + + + + + + + + + + + + +
출금 요청시간출금 포인트은행 이름계좌번호상태상태전환
요청 시간요청된 포인트은행 이름계좌번호상태 + +
+ +
+ + +
+ +
+ + +
+ +
+
+
+ + diff --git a/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java b/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java index d2fca9be..c9879f2e 100644 --- a/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java +++ b/src/test/java/com/example/sinitto/callback/entity/CallbackTest.java @@ -14,6 +14,12 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -27,14 +33,14 @@ class CallbackTest { @Autowired private SeniorRepository seniorRepository; private Callback testCallback; + private Member testMember; + private Senior testSenior; @BeforeEach void setUp() { - Member testMember = new Member("member", "01043214321", "tjdgns5506@gmai.com", true); - memberRepository.save(testMember); + testMember = memberRepository.save(new Member("member", "01043214321", "tjdgns5506@gmai.com", true)); - Senior testSenior = new Senior("senior", "01012341234", testMember); - seniorRepository.save(testSenior); + testSenior = seniorRepository.save(new Senior("senior", "01012341234", testMember)); testCallback = callbackRepository.save(new Callback(Callback.Status.WAITING, testSenior)); } @@ -264,4 +270,23 @@ void changeStatusToComplete_fail2() { assertThrows(AlreadyInProgressException.class, () -> testCallback.changeStatusToComplete()); } + @Test + @DisplayName("보호자에 연관된 다수의 시니어 리스트를 얻은후, 다수의 시니어들이 신청한 콜백 요청 기록 조회 테스트(CallbackService 의 getCallbackHistoryOfGuard() 테스트나 마찬가지)") + void getSeniorListAndReadCallbackHistoryOfSeniors() { + //given + Senior testSenior2 = new Senior("senior2", "01099999999", testMember); + seniorRepository.save(testSenior2); + + callbackRepository.save(new Callback(Callback.Status.WAITING, testSenior2)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, testSenior2)); + Pageable pageable = PageRequest.of(0, 1, Sort.by(Sort.Direction.DESC, "postTime")); + //when + Page result = callbackRepository.findAllBySeniorIn(List.of(testSenior, testSenior2), pageable); + + //then + assertEquals(3, result.getTotalPages()); + assertEquals(testSenior2, result.getContent().getFirst().getSenior()); + assertEquals(Callback.Status.COMPLETE.toString(), result.getContent().getFirst().getStatus()); + } + } diff --git a/src/test/java/com/example/sinitto/callback/repository/CallbackRepositoryTest.java b/src/test/java/com/example/sinitto/callback/repository/CallbackRepositoryTest.java index 8de07246..e40c2583 100644 --- a/src/test/java/com/example/sinitto/callback/repository/CallbackRepositoryTest.java +++ b/src/test/java/com/example/sinitto/callback/repository/CallbackRepositoryTest.java @@ -11,6 +11,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; @@ -26,10 +28,11 @@ class CallbackRepositoryTest { private SeniorRepository seniorRepository; private Callback testCallback; private Long memberId; + private Member testMember; @BeforeEach void setUp() { - Member testMember = new Member("member", "01043214321", "tjdgns5506@gmai.com", true); + testMember = new Member("member", "01043214321", "tjdgns5506@gmai.com", true); memberRepository.save(testMember); memberId = testMember.getId(); @@ -97,4 +100,147 @@ void findByAssignedMemberId_fail3() { //then assertTrue(result.isEmpty()); } + + @Test + @DisplayName("콜백에 할당된 멤버id와 상태를 매게변수로한 조회 - 성공") + void existsByAssignedMemberIdAndStatus() { + //given + testCallback.assignMember(memberId); + testCallback.changeStatusToInProgress(); + + //when + boolean result = callbackRepository.existsByAssignedMemberIdAndStatus(memberId, Callback.Status.IN_PROGRESS); + + //then + assertTrue(result); + } + + @Test + @DisplayName("콜백에 할당된 멤버id와 상태를 매게변수로한 조회 - 실패(멤버id 아닌 경우)") + void existsByAssignedMemberIdAndStatus_fail1() { + //given + testCallback.assignMember(memberId); + testCallback.changeStatusToInProgress(); + + //when + boolean result = callbackRepository.existsByAssignedMemberIdAndStatus(memberId + 1L, Callback.Status.IN_PROGRESS); + + //then + assertFalse(result); + } + + @Test + @DisplayName("콜백에 할당된 멤버id와 상태를 매게변수로한 조회 - 실패(멤버id만 틀리는 경우)") + void existsByAssignedMemberIdAndStatus_fail2() { + //given + testCallback.assignMember(memberId); + testCallback.changeStatusToInProgress(); + + //when + boolean result = callbackRepository.existsByAssignedMemberIdAndStatus(memberId + 1L, Callback.Status.IN_PROGRESS); + + //then + assertFalse(result); + } + + @Test + @DisplayName("콜백에 할당된 멤버id와 상태를 매게변수로한 조회 - 실패(콜백 상태만 틀리는 경우)") + void existsByAssignedMemberIdAndStatus_fail3() { + //given + testCallback.assignMember(memberId); + testCallback.changeStatusToInProgress(); + + //when + boolean result = callbackRepository.existsByAssignedMemberIdAndStatus(memberId, Callback.Status.PENDING_COMPLETE); + + //then + assertFalse(result); + } + + @Test + @DisplayName("콜백에 할당된 멤버id와 상태를 매게변수로한 조회 - 실패(멤버id, 콜백 상태 모두 틀리는 경우)") + void existsByAssignedMemberIdAndStatus_fail4() { + //given + testCallback.assignMember(memberId); + testCallback.changeStatusToInProgress(); + + //when + boolean result = callbackRepository.existsByAssignedMemberIdAndStatus(memberId + 1L, Callback.Status.WAITING); + + //then + assertFalse(result); + } + + + @Test + @DisplayName("findAllByStatusAndPendingCompleteTimeBefore 이용해서 2일이 지난 PendingComplete 콜백 조회 - 성공") + void findAllByStatusAndPendingCompleteTimeBefore_success() { + // given + LocalDateTime beforeTime = LocalDateTime.of(2024, 1, 5, 13, 00).minusDays(2); + Senior testSenior = seniorRepository.save(new Senior("senior", "01012341234", testMember)); + + Callback callback1 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback1.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 12, 58)); + Callback callback2 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback2.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 12, 59)); + Callback callback3 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback3.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 12, 59)); + Callback callback4 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback4.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 13, 01)); + Callback callback5 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback5.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 13, 02)); + + // when + List result = callbackRepository.findAllByStatusAndPendingCompleteTimeBefore(Callback.Status.PENDING_COMPLETE, beforeTime); + + // then + assertEquals(3, result.size()); + assertTrue(result.contains(callback1)); + assertTrue(result.contains(callback2)); + assertTrue(result.contains(callback3)); + } + + @Test + @DisplayName("findAllByStatusAndPendingCompleteTimeBefore 이용해서 2일이 지난 PendingComplete 콜백 조회 - 만약 아무것도 조건에 해당 안될 경우 테스트") + void findAllByStatusAndPendingCompleteTimeBefore_success_zeroList() { + // given + LocalDateTime beforeTime = LocalDateTime.of(2024, 1, 5, 13, 00).minusDays(2); + Senior testSenior = seniorRepository.save(new Senior("senior", "01012341234", testMember)); + + Callback callback1 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback1.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 13, 01)); + Callback callback2 = callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callback2.setPendingCompleteTime(LocalDateTime.of(2024, 1, 3, 13, 02)); + + // when + List result = callbackRepository.findAllByStatusAndPendingCompleteTimeBefore(Callback.Status.PENDING_COMPLETE, beforeTime); + + // then + assertNotNull(result); + assertEquals(0, result.size()); + + } + + @Test + @DisplayName("시니어와 상태들을 조건을 활용한 조회 테스트") + void existsBySeniorAndStatusIn() { + // given + Senior testSenior = seniorRepository.save(new Senior("senior", "01012341234", testMember)); + + callbackRepository.save(new Callback(Callback.Status.WAITING, testSenior)); + callbackRepository.save(new Callback(Callback.Status.PENDING_COMPLETE, testSenior)); + callbackRepository.save(new Callback(Callback.Status.COMPLETE, testSenior)); + + // when + boolean result1 = callbackRepository.existsBySeniorAndStatusIn(testSenior, List.of(Callback.Status.IN_PROGRESS, Callback.Status.WAITING)); + boolean result2 = callbackRepository.existsBySeniorAndStatusIn(testSenior, List.of(Callback.Status.WAITING)); + boolean result3 = callbackRepository.existsBySeniorAndStatusIn(testSenior, List.of(Callback.Status.IN_PROGRESS)); + boolean result4 = callbackRepository.existsBySeniorAndStatusIn(testSenior, List.of(Callback.Status.COMPLETE)); + + // then + assertTrue(result1); + assertTrue(result2); + assertFalse(result3); + assertTrue(result4); + } } diff --git a/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java b/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java index 51be815d..f4a0a436 100644 --- a/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java +++ b/src/test/java/com/example/sinitto/callback/service/CallbackServiceTest.java @@ -12,6 +12,10 @@ import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.entity.Point; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.repository.PointLogRepository; +import com.example.sinitto.point.repository.PointRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -38,12 +42,16 @@ class CallbackServiceTest { MemberRepository memberRepository; @Mock SeniorRepository seniorRepository; + @Mock + PointRepository pointRepository; + @Mock + PointLogRepository pointLogRepository; @InjectMocks CallbackService callbackService; @Test @DisplayName("getCallbacks - 성공") - void getCallbacks() { + void getWaitingCallbacks() { //given Long memberId = 1L; Pageable pageable = PageRequest.of(0, 10); @@ -59,19 +67,19 @@ void getCallbacks() { when(memberRepository.findById(memberId)).thenReturn(Optional.of(member)); when(member.isSinitto()).thenReturn(true); - when(callbackRepository.findAll(pageable)).thenReturn(callbackPage); + when(callbackRepository.findAllByStatus(Callback.Status.WAITING, pageable)).thenReturn(callbackPage); //when - Page result = callbackService.getCallbacks(memberId, pageable); + Page result = callbackService.getWaitingCallbacks(memberId, pageable); //then assertEquals(1, result.getContent().size()); - assertEquals("James", result.getContent().get(0).seniorName()); + assertEquals("James", result.getContent().getFirst().seniorName()); } @Test @DisplayName("getCallbacks 멤버가 없을때 - 실패") - void getCallbacks_Fail_WhenNotMember() { + void getWaitingCallbacks_Fail_WhenNotMember() { //given Long memberId = 1L; Pageable pageable = PageRequest.of(0, 10); @@ -79,7 +87,7 @@ void getCallbacks_Fail_WhenNotMember() { when(memberRepository.findById(memberId)).thenReturn(Optional.empty()); //when then - assertThrows(NotMemberException.class, () -> callbackService.getCallbacks(memberId, pageable)); + assertThrows(NotMemberException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); } @Test @@ -94,12 +102,12 @@ void getCallbacks_Fail_WhenNotSinitto() { when(member.isSinitto()).thenReturn(false); //when then - assertThrows(NotSinittoException.class, () -> callbackService.getCallbacks(memberId, pageable)); + assertThrows(NotSinittoException.class, () -> callbackService.getWaitingCallbacks(memberId, pageable)); } @Test @DisplayName("콜백 수락 - 성공") - void accept() { + void acceptCallbackBySinitto() { //given Long memberId = 1L; Long callbackId = 1L; @@ -112,7 +120,7 @@ void accept() { when(callbackRepository.findById(callbackId)).thenReturn(Optional.of(callback)); //when - callbackService.accept(memberId, callbackId); + callbackService.acceptCallbackBySinitto(memberId, callbackId); //then verify(callback).assignMember(memberId); @@ -121,7 +129,7 @@ void accept() { @Test @DisplayName("콜백 완료 대기 - 성공") - void complete() { + void changeCallbackStatusToCompleteByGuard() { //given Long memberId = 1L; Long callbackId = 1L; @@ -136,7 +144,7 @@ void complete() { when(callback.getAssignedMemberId()).thenReturn(assignedMemberId); //when - callbackService.pendingComplete(memberId, callbackId); + callbackService.changeCallbackStatusToPendingCompleteBySinitto(memberId, callbackId); //then verify(callback).changeStatusToPendingComplete(); @@ -144,7 +152,7 @@ void complete() { @Test @DisplayName("수락한 콜백 취소 - 성공") - void cancel() { + void cancelCallbackAssignmentBySinitto() { //given Long memberId = 1L; Long callbackId = 1L; @@ -158,7 +166,7 @@ void cancel() { when(callback.getAssignedMemberId()).thenReturn(1L); //when - callbackService.cancel(memberId, callbackId); + callbackService.cancelCallbackAssignmentBySinitto(memberId, callbackId); //then verify(callback).cancelAssignment(); @@ -167,25 +175,31 @@ void cancel() { @Test @DisplayName("새로운 콜백 등록") - void addCallback() { + void createCallbackByCall() { //given String fromPhoneNumber = "+821012341234"; String trimmedPhoneNumber = TwilioHelper.trimPhoneNumber(fromPhoneNumber); Senior senior = mock(Senior.class); + Member member = mock(Member.class); + Point point = mock(Point.class); when(seniorRepository.findByPhoneNumber(trimmedPhoneNumber)).thenReturn(Optional.of(senior)); - + when(senior.getMember()).thenReturn(member); + when(member.getId()).thenReturn(1L); + when(pointRepository.findByMemberIdWithWriteLock(1L)).thenReturn(Optional.of(point)); + when(point.isSufficientForDeduction(anyInt())).thenReturn(true); //when - String result = callbackService.add(fromPhoneNumber); + String result = callbackService.createCallbackByCall(fromPhoneNumber); //then + verify(pointLogRepository, times(1)).save(any()); verify(callbackRepository, times(1)).save(any()); assertNotNull(result); } @Test @DisplayName("새로운 콜백 등록할 때 전화온 번호가 등록된 번호가 아닐 때") - void addCallback_fail() { + void createCallbackByCallingCallback_fail() { //given String fromPhoneNumber = "+821012341234"; String trimmedPhoneNumber = TwilioHelper.trimPhoneNumber(fromPhoneNumber); @@ -193,31 +207,84 @@ void addCallback_fail() { when(seniorRepository.findByPhoneNumber(trimmedPhoneNumber)).thenReturn(Optional.empty()); //when - String result = callbackService.add(fromPhoneNumber); + String result = callbackService.createCallbackByCall(fromPhoneNumber); + + //then + verify(callbackRepository, never()).save(any()); + assertNotNull(result); + } + + @Test + @DisplayName("새로운 콜백 등록할 때 포인트가 부족할 때") + void createCallbackByCallingCallback_fail1() { + //given + String fromPhoneNumber = "+821012341234"; + String trimmedPhoneNumber = TwilioHelper.trimPhoneNumber(fromPhoneNumber); + Member member = mock(Member.class); + Senior senior = mock(Senior.class); + Point point = mock(Point.class); + + when(seniorRepository.findByPhoneNumber(trimmedPhoneNumber)).thenReturn(Optional.of(senior)); + when(senior.getMember()).thenReturn(member); + when(member.getId()).thenReturn(1L); + when(pointRepository.findByMemberIdWithWriteLock(any(Long.class))).thenReturn(Optional.of(point)); + when(point.isSufficientForDeduction(anyInt())).thenReturn(false); + + //when + String result = callbackService.createCallbackByCall(fromPhoneNumber); //then - verify(callbackRepository, times(0)).save(any()); + verify(point, never()).deduct(anyInt()); + verify(callbackRepository, never()).save(any()); + assertNotNull(result); + } + + @Test + @DisplayName("새로운 콜백 등록할 때 이미 시니어가 신청한 진행중 or 대기중인 콜백이 존재할때") + void createCallbackByCallingCallback_fail2() { + //given + String fromPhoneNumber = "+821012341234"; + String trimmedPhoneNumber = TwilioHelper.trimPhoneNumber(fromPhoneNumber); + Member member = mock(Member.class); + Senior senior = mock(Senior.class); + Point point = mock(Point.class); + + when(seniorRepository.findByPhoneNumber(trimmedPhoneNumber)).thenReturn(Optional.of(senior)); + when(senior.getMember()).thenReturn(member); + when(member.getId()).thenReturn(1L); + when(pointRepository.findByMemberIdWithWriteLock(any(Long.class))).thenReturn(Optional.of(point)); + when(point.isSufficientForDeduction(anyInt())).thenReturn(true); + when(callbackRepository.existsBySeniorAndStatusIn(any(), any())).thenReturn(true); + + //when + String result = callbackService.createCallbackByCall(fromPhoneNumber); + + //then + verify(point, never()).deduct(anyInt()); + verify(callbackRepository, never()).save(any()); assertNotNull(result); } @Test @DisplayName("보호자가 콜백 대기 상태를 완료 생태로 변경 - 성공") - void completeByGuard() { + void changeCallbackStatusToCompleteByGuardByGuard() { //given Long memberId = 1L; Long callbackId = 1L; Member member = mock(Member.class); Callback callback = mock(Callback.class); Senior senior = mock(Senior.class); + Point point = mock(Point.class); when(member.getId()).thenReturn(1L); when(callbackRepository.findById(callbackId)).thenReturn(Optional.of(callback)); when(callback.getSenior()).thenReturn(senior); when(senior.getMember()).thenReturn(member); when(senior.getMember().getId()).thenReturn(1L); + when(pointRepository.findByMemberId(any())).thenReturn(Optional.of(point)); //when - callbackService.complete(memberId, callbackId); + callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId); //then verify(callback).changeStatusToComplete(); @@ -225,7 +292,7 @@ void completeByGuard() { @Test @DisplayName("보호자가 콜백 대기 상태를 완료 생태로 변경 - 일치하는 보호자 ID가 아니어서 실패") - void completeByGuard_fail() { + void changeCallbackStatusToCompleteByGuardByGuard_fail() { //given Long memberId = 10L; Long callbackId = 1L; @@ -240,7 +307,7 @@ void completeByGuard_fail() { when(senior.getMember().getId()).thenReturn(1L); //when then - assertThrows(GuardMismatchException.class, () -> callbackService.complete(memberId, callbackId)); + assertThrows(GuardMismatchException.class, () -> callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId)); } @Test @@ -277,4 +344,65 @@ void getAcceptedCallback_fail() { //when then assertThrows(NotExistCallbackException.class, () -> callbackService.getAcceptedCallback(memberId)); } + + @Test + @DisplayName("일정 기간동안 PendingComplete 인 콜백 자동으로 Complete 로 전환 - 성공") + void changeOldPendingCompleteToCompleteByPolicy_Success() { + // Given + Callback callback1 = mock(Callback.class); + Point point = mock(Point.class); + + when(callback1.getAssignedMemberId()).thenReturn(1L); + when(pointRepository.findByMemberId(1L)).thenReturn(Optional.of(point)); + + when(callbackRepository.findAllByStatusAndPendingCompleteTimeBefore(eq(Callback.Status.PENDING_COMPLETE), any(LocalDateTime.class))) + .thenReturn(List.of(callback1)); + + // When + callbackService.changeOldPendingCompleteToCompleteByPolicy(); + + // Then + verify(callback1, times(1)).changeStatusToComplete(); + verify(point, times(1)).earn(1500); + verify(pointLogRepository, times(1)).save(any(PointLog.class)); + } + + @Test + @DisplayName("일정 기간동안 PendingComplete 인 콜백 자동으로 Complete 로 전환 - 조건에 맞는 콜백 없을 때") + void changeOldPendingCompleteToCompleteByPolicy_Success_zeroList() { + // Given + when(callbackRepository.findAllByStatusAndPendingCompleteTimeBefore(eq(Callback.Status.PENDING_COMPLETE), any(LocalDateTime.class))) + .thenReturn(List.of()); + + // When + callbackService.changeOldPendingCompleteToCompleteByPolicy(); + + // Then + verify(pointLogRepository, never()).save(any(PointLog.class)); + } + + @Test + @DisplayName("LocalDateTime 의 isBefore 메서드 공부 겸 테스트, 엣지 케이스") + void localDateTimeBeforeCalculateTest() { + //given + //메서드 실행 시간 + LocalDateTime 일월3일13시00분 = LocalDateTime.of(2024, 1, 3, 13, 0); + LocalDateTime 일월3일13시10분 = LocalDateTime.of(2024, 1, 3, 13, 10); + + //콜백이 Pending Complete 상태가 된 시간 + LocalDateTime 일월1일12시59분 = LocalDateTime.of(2024, 1, 1, 12, 59); + LocalDateTime 일월1일13시00분 = LocalDateTime.of(2024, 1, 1, 13, 0); + LocalDateTime 일월1일13시01분 = LocalDateTime.of(2024, 1, 1, 13, 1); + + //when then + // 1월 3일 13시 00분에 2일전에 COMPLETE 된 콜백의 존재를 확인한다. + assertTrue(일월1일12시59분.isBefore(일월3일13시00분.minusDays(2))); + assertFalse(일월1일13시00분.isBefore(일월3일13시00분.minusDays(2))); + assertFalse(일월1일13시01분.isBefore(일월3일13시00분.minusDays(2))); + + //10분뒤인 1월 3일 13시 10분에 2일전에 COMPLETE 된 콜백의 존재를 확인한다. 결국 모두 TRUE 로 처리가 되는것을 확인. + assertTrue(일월1일12시59분.isBefore(일월3일13시10분.minusDays(2))); + assertTrue(일월1일13시00분.isBefore(일월3일13시10분.minusDays(2))); + assertTrue(일월1일13시01분.isBefore(일월3일13시10분.minusDays(2))); + } } diff --git a/src/test/java/com/example/sinitto/guardGuideline/entity/GuardGuidelineTest.java b/src/test/java/com/example/sinitto/guardGuideline/entity/GuardGuidelineTest.java new file mode 100644 index 00000000..7f890cd4 --- /dev/null +++ b/src/test/java/com/example/sinitto/guardGuideline/entity/GuardGuidelineTest.java @@ -0,0 +1,58 @@ +package com.example.sinitto.guardGuideline.entity; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.entity.Senior; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class GuardGuidelineTest { + + private Member member; + private Senior senior; + + @BeforeEach + void setUp() { + // 테스트용 Member와 Senior 객체 생성 + member = new Member("John Doe", "123456789", "john@example.com", true); + senior = new Senior("Jane Doe", "987654321", member); + } + + @Test + @DisplayName("GuardGuideline 객체 생성 테스트") + void createGuardGuideline() { + GuardGuideline guideline = new GuardGuideline(GuardGuideline.Type.TAXI, "Taxi Guidelines", "Details about taxi guidelines", senior); + + assertEquals(GuardGuideline.Type.TAXI, guideline.getType()); + assertEquals("Taxi Guidelines", guideline.getTitle()); + assertEquals("Details about taxi guidelines", guideline.getContent()); + assertEquals(senior, guideline.getSenior()); + assertEquals(senior.getMember(), member); // Senior와 Member의 관계 확인 + } + + @Test + @DisplayName("GuardGuideline 업데이트 메서드 테스트") + void updateGuardGuideline() { + GuardGuideline guideline = new GuardGuideline(GuardGuideline.Type.TAXI, "Old Title", "Old Content", senior); + + guideline.updateGuardGuideline(GuardGuideline.Type.DELIVERY, "New Title", "New Content"); + + assertEquals(GuardGuideline.Type.DELIVERY, guideline.getType()); + assertEquals("New Title", guideline.getTitle()); + assertEquals("New Content", guideline.getContent()); + } + + @Test + @DisplayName("GuardGuideline 기본 생성자 테스트") + void guardGuidelineDefaultConstructor() { + GuardGuideline guideline = new GuardGuideline(); + assertNull(guideline.getId()); + assertNull(guideline.getType()); + assertNull(guideline.getTitle()); + assertNull(guideline.getContent()); + assertNull(guideline.getSenior()); + } +} diff --git a/src/test/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepositoryTest.java b/src/test/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepositoryTest.java new file mode 100644 index 00000000..80a3b2f5 --- /dev/null +++ b/src/test/java/com/example/sinitto/guardGuideline/repository/GuardGuidelineRepositoryTest.java @@ -0,0 +1,92 @@ +package com.example.sinitto.guardGuideline.repository; + + +import com.example.sinitto.guard.repository.SeniorRepository; +import com.example.sinitto.guardGuideline.entity.GuardGuideline; +import com.example.sinitto.guardGuideline.entity.GuardGuideline.Type; +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.entity.Senior; +import com.example.sinitto.member.repository.MemberRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@DataJpaTest +class GuardGuidelineRepositoryTest { + + @Autowired + private GuardGuidelineRepository guardGuidelineRepository; + + @Autowired + private SeniorRepository seniorRepository; + + @Autowired + private MemberRepository memberRepository; + + private Senior senior; + + @BeforeEach + void setUp() { + Member member = new Member("Test Member", "010-1234-5678", "test@member.com", true); + memberRepository.save(member); + + senior = new Senior("Test Senior", "010-9876-5432", member); + seniorRepository.save(senior); + + GuardGuideline guideline1 = new GuardGuideline(Type.TAXI, "Taxi Guideline", "Content for taxi", senior); + GuardGuideline guideline2 = new GuardGuideline(Type.DELIVERY, "Delivery Guideline", "Content for delivery", senior); + guardGuidelineRepository.save(guideline1); + guardGuidelineRepository.save(guideline2); + } + + @Test + @DisplayName("Senior ID로 GuardGuideline 목록 조회 테스트") + void testFindBySeniorId() { + List guidelines = guardGuidelineRepository.findBySeniorId(senior.getId()); + + assertEquals(2, guidelines.size()); + assertTrue(guidelines.stream().anyMatch(g -> g.getTitle().equals("Taxi Guideline"))); + assertTrue(guidelines.stream().anyMatch(g -> g.getTitle().equals("Delivery Guideline"))); + } + + @Test + @DisplayName("Senior ID와 Type으로 GuardGuideline 조회 테스트") + void testFindBySeniorIdAndType() { + List taxiGuidelines = guardGuidelineRepository.findBySeniorIdAndType(senior.getId(), Type.TAXI); + + assertEquals(1, taxiGuidelines.size()); + assertEquals("Taxi Guideline", taxiGuidelines.get(0).getTitle()); + assertEquals(Type.TAXI, taxiGuidelines.get(0).getType()); + } + + @Test + @DisplayName("존재하지 않는 Senior ID와 Type으로 GuardGuideline 조회 테스트") + void testFindBySeniorIdAndType_NoResult() { + Long nonexistentSeniorId = -1L; // 존재하지 않는 Senior ID + List guidelines = guardGuidelineRepository.findBySeniorIdAndType(nonexistentSeniorId, Type.DELIVERY); + + assertTrue(guidelines.isEmpty()); + } + + + @Test + @DisplayName("GuardGuideline 저장 및 삭제 테스트") + void testSaveAndDelete() { + GuardGuideline guideline = new GuardGuideline(Type.DELIVERY, "New Delivery Guideline", "New content", senior); + guardGuidelineRepository.save(guideline); + + List guidelines = guardGuidelineRepository.findBySeniorIdAndType(senior.getId(), Type.DELIVERY); + assertTrue(guidelines.stream().anyMatch(g -> g.getTitle().equals("New Delivery Guideline"))); + + guardGuidelineRepository.delete(guideline); + + List deletedGuidelines = guardGuidelineRepository.findBySeniorIdAndType(senior.getId(), Type.DELIVERY); + assertFalse(deletedGuidelines.stream().anyMatch(g -> g.getTitle().equals("New Delivery Guideline"))); + } +} diff --git a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java index a9c7b69a..66b993a1 100644 --- a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java +++ b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTest.java @@ -80,13 +80,13 @@ void changeStatusThrowsInvalidStatusException() { assertThatThrownBy(() -> helloCall.changeStatusToInProgress()) .isInstanceOf(InvalidStatusException.class) - .hasMessage("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 변경할 수 있습니다. 현재 상태 : " + HelloCall.Status.IN_PROGRESS); + .hasMessage("안부전화 서비스가 수행 대기중일 때만 진행중 상태로 나아갈 수 있습니다. 현재 상태 : " + HelloCall.Status.IN_PROGRESS); helloCall.changeStatusToPendingComplete(); assertThatThrownBy(() -> helloCall.changeStatusToWaiting()) .isInstanceOf(InvalidStatusException.class) - .hasMessage("안부전화 서비스가 수행중일 때만 진행중 상태로 변경할 수 있습니다. 현재 상태 : " + HelloCall.Status.PENDING_COMPLETE); + .hasMessage("안부전화 서비스가 수행중일 때만 진행중 상태로 돌아갈 수 있습니다. 현재 상태 : " + HelloCall.Status.PENDING_COMPLETE); } @Test diff --git a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTimeLogTest.java b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTimeLogTest.java index ebbfa9f4..1a2024c7 100644 --- a/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTimeLogTest.java +++ b/src/test/java/com/example/sinitto/hellocall/entity/HelloCallTimeLogTest.java @@ -3,7 +3,6 @@ import com.example.sinitto.helloCall.entity.HelloCall; import com.example.sinitto.helloCall.entity.HelloCallTimeLog; import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.entity.Sinitto; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,16 +14,15 @@ class HelloCallTimeLogTest { private HelloCall helloCall; - private Sinitto sinitto; + private Member member; private HelloCallTimeLog helloCallTimeLog; @BeforeEach void setup() { helloCall = new HelloCall(LocalDateTime.now().toLocalDate(), LocalDateTime.now().toLocalDate(), 10000, 30, "Test Requirement", null); - Member member = new Member("Sinitto Test", "01012345678", "sinitto@test.com", true); - sinitto = new Sinitto("테스트은행", "1111222233334444", member); + member = new Member("SinittoBankInfo Test", "01012345678", "sinittoBankInfo@test.com", true); - helloCallTimeLog = new HelloCallTimeLog(helloCall, sinitto); + helloCallTimeLog = new HelloCallTimeLog(helloCall, member); } @Test @@ -32,7 +30,7 @@ void setup() { void constructorTest() { assertThat(helloCallTimeLog).isNotNull(); assertThat(helloCallTimeLog.getHelloCall()).isEqualTo(helloCall); - assertThat(helloCallTimeLog.getSinitto()).isEqualTo(sinitto); + assertThat(helloCallTimeLog.getSinitto()).isEqualTo(member); } @Test @@ -49,9 +47,9 @@ void setStartAndEndDateTimeTest() { } @Test - @DisplayName("Sinitto 이름 가져오기 테스트") + @DisplayName("member 이름 가져오기 테스트") void getSinittoNameTest() { - String expectedName = sinitto.getMember().getName(); + String expectedName = member.getName(); assertThat(helloCallTimeLog.getSinittoName()).isEqualTo(expectedName); } } diff --git a/src/test/java/com/example/sinitto/hellocall/repository/HelloCallRepositoryTest.java b/src/test/java/com/example/sinitto/hellocall/repository/HelloCallRepositoryTest.java index 8fc626a2..9beac7d4 100644 --- a/src/test/java/com/example/sinitto/hellocall/repository/HelloCallRepositoryTest.java +++ b/src/test/java/com/example/sinitto/hellocall/repository/HelloCallRepositoryTest.java @@ -5,9 +5,9 @@ import com.example.sinitto.helloCall.repository.HelloCallRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.entity.Sinitto; import com.example.sinitto.member.repository.MemberRepository; -import com.example.sinitto.sinitto.repository.SinittoRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -33,13 +33,13 @@ class HelloCallRepositoryTest { private MemberRepository memberRepository; @Autowired - private SinittoRepository sinittoRepository; + private SinittoBankInfoRepository sinittoBankInfoRepository; private Member sinittoMember1; private Member sinittoMember2; private Member seniorMember; - private Sinitto sinitto1; - private Sinitto sinitto2; + private SinittoBankInfo sinittoBankInfo1; + private SinittoBankInfo sinittoBankInfo2; private Senior senior; @BeforeEach @@ -47,14 +47,14 @@ void setUp() { sinittoMember1 = new Member("test1", "01011111111", "test1@test.com", true); memberRepository.save(sinittoMember1); - sinitto1 = new Sinitto("sinittoBank1", "BankAccount1", sinittoMember1); - sinittoRepository.save(sinitto1); + sinittoBankInfo1 = new SinittoBankInfo("sinittoBank1", "BankAccount1", sinittoMember1); + sinittoBankInfoRepository.save(sinittoBankInfo1); sinittoMember2 = new Member("test2", "01022222222", "test2@test.com", true); memberRepository.save(sinittoMember2); - sinitto2 = new Sinitto("SinittoBank2", "BankAccount2", sinittoMember2); - sinittoRepository.save(sinitto2); + sinittoBankInfo2 = new SinittoBankInfo("SinittoBank2", "BankAccount2", sinittoMember2); + sinittoBankInfoRepository.save(sinittoBankInfo2); seniorMember = new Member("test3", "01033333333", "test3@test.com", false); memberRepository.save(seniorMember); @@ -78,8 +78,8 @@ void findBySeniorTest() { } @Test - @DisplayName("Sinitto 기반으로 HelloCall 리스트 찾기 테스트") - void findAllBySinittoTest() { + @DisplayName("member 기반으로 HelloCall 리스트 찾기 테스트") + void findAllByMemberTest() { Senior senior1 = new Senior("Senior1", "01012345678", sinittoMember2); seniorRepository.save(senior1); Senior senior2 = new Senior("Senior2", "01098765432", sinittoMember2); @@ -92,17 +92,17 @@ void findAllBySinittoTest() { LocalDate.of(2024, 1, 4), 15000, 90, "요구사항2", senior2); - helloCall1.setSinitto(sinitto1); - helloCall2.setSinitto(sinitto1); + helloCall1.setMember(sinittoMember1); + helloCall2.setMember(sinittoMember1); helloCallRepository.save(helloCall1); helloCallRepository.save(helloCall2); - List helloCalls = helloCallRepository.findAllBySinitto(sinitto1); + List helloCalls = helloCallRepository.findAllByMember(sinittoMember1); assertThat(helloCalls).hasSize(2); - assertThat(helloCalls.get(0).getSinitto()).isEqualTo(sinitto1); - assertThat(helloCalls.get(1).getSinitto()).isEqualTo(sinitto1); + assertThat(helloCalls.get(0).getMember()).isEqualTo(sinittoMember1); + assertThat(helloCalls.get(1).getMember()).isEqualTo(sinittoMember1); } @Test @@ -136,19 +136,19 @@ void testChangeSinittoInHelloCall() { LocalDate.of(2024, 1, 2), 10000, 60, "요구사항", senior); - helloCall.setSinitto(sinitto1); + helloCall.setMember(sinittoMember1); helloCallRepository.save(helloCall); Optional savedHelloCall = helloCallRepository.findById(helloCall.getId()); assertThat(savedHelloCall).isPresent(); - assertThat(savedHelloCall.get().getSinitto()).isEqualTo(sinitto1); + assertThat(savedHelloCall.get().getMember()).isEqualTo(sinittoMember1); - savedHelloCall.get().setSinitto(sinitto2); + savedHelloCall.get().setMember(sinittoMember2); helloCallRepository.save(savedHelloCall.get()); Optional updatedHelloCall = helloCallRepository.findById(helloCall.getId()); assertThat(updatedHelloCall).isPresent(); - assertThat(updatedHelloCall.get().getSinitto()).isEqualTo(sinitto2); + assertThat(updatedHelloCall.get().getMember()).isEqualTo(sinittoMember2); } @Test diff --git a/src/test/java/com/example/sinitto/hellocall/repository/HelloCallTimeLogRepositoryTest.java b/src/test/java/com/example/sinitto/hellocall/repository/HelloCallTimeLogRepositoryTest.java index ae2068c4..5f01be82 100644 --- a/src/test/java/com/example/sinitto/hellocall/repository/HelloCallTimeLogRepositoryTest.java +++ b/src/test/java/com/example/sinitto/hellocall/repository/HelloCallTimeLogRepositoryTest.java @@ -7,9 +7,9 @@ import com.example.sinitto.helloCall.repository.HelloCallTimeLogRepository; import com.example.sinitto.member.entity.Member; import com.example.sinitto.member.entity.Senior; -import com.example.sinitto.member.entity.Sinitto; import com.example.sinitto.member.repository.MemberRepository; -import com.example.sinitto.sinitto.repository.SinittoRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import com.example.sinitto.sinitto.repository.SinittoBankInfoRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -33,7 +33,7 @@ class HelloCallTimeLogRepositoryTest { private HelloCallRepository helloCallRepository; @Autowired - private SinittoRepository sinittoRepository; + private SinittoBankInfoRepository sinittoBankInfoRepository; @Autowired private SeniorRepository seniorRepository; @@ -43,17 +43,17 @@ class HelloCallTimeLogRepositoryTest { private Member sinittoMember; private Member seniorMember; - private Sinitto sinitto; + private SinittoBankInfo sinittoBankInfo; private Senior senior; private HelloCall helloCall; @BeforeEach void setUp() { - sinittoMember = new Member("testSinitto", "01011112222", "sinitto@test.com", true); + sinittoMember = new Member("testSinitto", "01011112222", "sinittoBankInfo@test.com", true); memberRepository.save(sinittoMember); - sinitto = new Sinitto("sinittoBank", "sinittoAccount", sinittoMember); - sinittoRepository.save(sinitto); + sinittoBankInfo = new SinittoBankInfo("sinittoBank", "sinittoAccount", sinittoMember); + sinittoBankInfoRepository.save(sinittoBankInfo); seniorMember = new Member("testSenior", "01033334444", "senior@test.com", false); memberRepository.save(seniorMember); @@ -66,16 +66,16 @@ void setUp() { } @Test - @DisplayName("로그 저장 및 Sinitto와 HelloCall ID 기반으로 특정 HelloCallTimeLog 찾기 테스트") + @DisplayName("로그 저장 및 member와 HelloCall ID 기반으로 특정 HelloCallTimeLog 찾기 테스트") void findBySinittoAndHelloCallIdTest() { - HelloCallTimeLog timeLog = new HelloCallTimeLog(helloCall, sinitto, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); + HelloCallTimeLog timeLog = new HelloCallTimeLog(helloCall, sinittoMember, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); helloCallTimeLogRepository.save(timeLog); - Optional foundTimeLog = helloCallTimeLogRepository.findBySinittoAndAndHelloCallId(sinitto, helloCall.getId()); + Optional foundTimeLog = helloCallTimeLogRepository.findByMemberAndHelloCallId(sinittoMember, helloCall.getId()); assertThat(foundTimeLog).isPresent(); assertThat(foundTimeLog.get().getHelloCall()).isEqualTo(helloCall); - assertThat(foundTimeLog.get().getSinitto()).isEqualTo(sinitto); + assertThat(foundTimeLog.get().getSinitto()).isEqualTo(sinittoMember); assertThat(foundTimeLog.get().getStartDateAndTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 10, 0)); assertThat(foundTimeLog.get().getEndDateAndTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 11, 0)); } @@ -83,8 +83,8 @@ void findBySinittoAndHelloCallIdTest() { @Test @DisplayName("HelloCall ID 기반으로 모든 HelloCallTimeLog 리스트 찾기 테스트") void findAllByHelloCallIdTest() { - HelloCallTimeLog timeLog1 = new HelloCallTimeLog(helloCall, sinitto, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); - HelloCallTimeLog timeLog2 = new HelloCallTimeLog(helloCall, sinitto, LocalDateTime.of(2024, 1, 1, 12, 0), LocalDateTime.of(2024, 1, 1, 13, 0)); + HelloCallTimeLog timeLog1 = new HelloCallTimeLog(helloCall, sinittoMember, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); + HelloCallTimeLog timeLog2 = new HelloCallTimeLog(helloCall, sinittoMember, LocalDateTime.of(2024, 1, 1, 12, 0), LocalDateTime.of(2024, 1, 1, 13, 0)); helloCallTimeLogRepository.save(timeLog1); helloCallTimeLogRepository.save(timeLog2); @@ -99,20 +99,20 @@ void findAllByHelloCallIdTest() { } @Test - @DisplayName("Sinitto와 HelloCall 기반으로 가장 최근의 HelloCallTimeLog 찾기 테스트") + @DisplayName("Member와 HelloCall 기반으로 가장 최근의 HelloCallTimeLog 찾기 테스트") void findTopBySinittoAndHelloCallOrderByStartDateAndTimeDescTest() { - HelloCallTimeLog timeLog1 = new HelloCallTimeLog(helloCall, sinitto, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); - HelloCallTimeLog timeLog2 = new HelloCallTimeLog(helloCall, sinitto, LocalDateTime.of(2024, 1, 1, 12, 0), LocalDateTime.of(2024, 1, 1, 13, 0)); + HelloCallTimeLog timeLog1 = new HelloCallTimeLog(helloCall, sinittoMember, LocalDateTime.of(2024, 1, 1, 10, 0), LocalDateTime.of(2024, 1, 1, 11, 0)); + HelloCallTimeLog timeLog2 = new HelloCallTimeLog(helloCall, sinittoMember, LocalDateTime.of(2024, 1, 1, 12, 0), LocalDateTime.of(2024, 1, 1, 13, 0)); helloCallTimeLogRepository.save(timeLog1); helloCallTimeLogRepository.save(timeLog2); Optional recentTimeLog = helloCallTimeLogRepository - .findTopBySinittoAndHelloCallOrderByStartDateAndTimeDesc(sinitto, helloCall); + .findTopByMemberAndHelloCallOrderByStartDateAndTimeDesc(sinittoMember, helloCall); assertThat(recentTimeLog).isPresent(); assertThat(recentTimeLog.get().getHelloCall()).isEqualTo(helloCall); - assertThat(recentTimeLog.get().getSinitto()).isEqualTo(sinitto); + assertThat(recentTimeLog.get().getSinitto()).isEqualTo(sinittoMember); assertThat(recentTimeLog.get().getStartDateAndTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 12, 0)); assertThat(recentTimeLog.get().getEndDateAndTime()).isEqualTo(LocalDateTime.of(2024, 1, 1, 13, 0)); } diff --git a/src/test/java/com/example/sinitto/member/entity/MemberTest.java b/src/test/java/com/example/sinitto/member/entity/MemberTest.java index b0894f60..8147fc39 100644 --- a/src/test/java/com/example/sinitto/member/entity/MemberTest.java +++ b/src/test/java/com/example/sinitto/member/entity/MemberTest.java @@ -31,7 +31,7 @@ void constructorTest() { } @Test - @DisplayName("Member Sinitto 여부 확인 테스트") + @DisplayName("Member SinittoBankInfo 여부 확인 테스트") void isSinittoTest() { assertThat(member.isSinitto()).isTrue(); diff --git a/src/test/java/com/example/sinitto/point/entity/PointLogTest.java b/src/test/java/com/example/sinitto/point/entity/PointLogTest.java new file mode 100644 index 00000000..a564e1e4 --- /dev/null +++ b/src/test/java/com/example/sinitto/point/entity/PointLogTest.java @@ -0,0 +1,167 @@ +package com.example.sinitto.point.entity; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.point.exception.InvalidPointLogStatusException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + + +class PointLogTest { + + Member member = new Member("test", "test", "test", true); + + @Test + @DisplayName("포인트 로그 ChargeWaiting 상태로 전환 성공") + void changeStatusToChargeWaiting() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.CHARGE_REQUEST); + + //when + pointLog.changeStatusToChargeWaiting(); + + //then + assertEquals(PointLog.Status.CHARGE_WAITING, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "CHARGE_WAITING", "CHARGE_COMPLETE"}) + @DisplayName("포인트 로그 ChargeWaiting 상태로 전환 실패") + void changeStatusToChargeWaiting_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeWaiting); + } + + @Test + @DisplayName("포인트 로그 ChargeComplete 상태로 전환 성공") + void changeStatusToChargeComplete() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.CHARGE_WAITING); + + //when + pointLog.changeStatusToChargeComplete(); + + //then + assertEquals(PointLog.Status.CHARGE_COMPLETE, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "CHARGE_REQUEST", "CHARGE_COMPLETE"}) + @DisplayName("포인트 로그 ChargeComplete 상태로 전환 실패") + void changeStatusToChargeComplete_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeComplete); + } + + @Test + @DisplayName("포인트 로그 ChargeFail 상태로 전환 성공") + void changeStatusToChargeFail() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.CHARGE_WAITING); + + //when + pointLog.changeStatusToChargeFail(); + + //then + assertEquals(PointLog.Status.CHARGE_FAIL, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE","WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE","CHARGE_FAIL"}) + @DisplayName("포인트 로그 ChargeFail 상태로 전환 실패") + void changeStatusToChargeFail_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToChargeFail); + } + + @Test + @DisplayName("포인트 로그 WithdrawWaiting 상태로 전환 성공") + void changeStatusToWithdrawWaiting() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.WITHDRAW_REQUEST); + + //when + pointLog.changeStatusToWithdrawWaiting(); + + //then + assertEquals(PointLog.Status.WITHDRAW_WAITING, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_WAITING", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL","CHARGE_WAITING"}) + @DisplayName("포인트 로그 WithdrawWaiting 상태로 전환 실패") + void changeStatusToWithdrawWaiting_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawWaiting); + } + + @Test + @DisplayName("포인트 로그 WithdrawComplete 상태로 전환 성공") + void changeStatusToWithdrawComplete() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.WITHDRAW_WAITING); + + //when + pointLog.changeStatusToWithdrawComplete(); + + //then + assertEquals(PointLog.Status.WITHDRAW_COMPLETE, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL"}) + @DisplayName("포인트 로그 WithdrawComplete 상태로 전환 실패") + void changeStatusToWithdrawComplete_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawComplete); + } + + @Test + @DisplayName("포인트 로그 WithdrawFail 상태로 전환 성공") + void changeStatusToWithdrawFail() { + //given + PointLog pointLog = new PointLog("content", member, 1000, PointLog.Status.WITHDRAW_WAITING); + + //when + pointLog.changeStatusToWithdrawFail(); + + //then + assertEquals(PointLog.Status.WITHDRAW_FAIL_AND_RESTORE_POINT, pointLog.getStatus()); + } + + @ParameterizedTest + @ValueSource(strings = {"EARN", "SPEND_COMPLETE", "SPEND_CANCEL", "WITHDRAW_REQUEST", "WITHDRAW_COMPLETE", "WITHDRAW_FAIL_AND_RESTORE_POINT", "CHARGE_REQUEST", "CHARGE_COMPLETE", "CHARGE_FAIL"}) + @DisplayName("포인트 로그 WithdrawFail 상태로 전환 실패") + void changeStatusToWithdrawFail_fail(String initialStatus) { + //given + PointLog.Status status = PointLog.Status.valueOf(initialStatus); + PointLog pointLog = new PointLog("content", member, 1000, status); + + //when then + assertThrows(InvalidPointLogStatusException.class, pointLog::changeStatusToWithdrawFail); + } +} diff --git a/src/test/java/com/example/sinitto/point/entity/PointTest.java b/src/test/java/com/example/sinitto/point/entity/PointTest.java new file mode 100644 index 00000000..6f775cb3 --- /dev/null +++ b/src/test/java/com/example/sinitto/point/entity/PointTest.java @@ -0,0 +1,63 @@ +package com.example.sinitto.point.entity; + +import com.example.sinitto.member.entity.Member; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.junit.jupiter.MockitoSettings; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + +@MockitoSettings +class PointTest { + + @Test + @DisplayName("포인트 적립") + void earn() { + //given + Member member = mock(Member.class); + Point point = new Point(100, member); + + //when + point.earn(3000); + + //then + assertEquals(3100, point.getPrice()); + } + + @Test + @DisplayName("포인트 차감") + void deduct() { + //given + Member member = mock(Member.class); + Point point = new Point(100, member); + + //when + point.deduct(80); + + //then + assertEquals(20, point.getPrice()); + } + + @Test + @DisplayName("차감이 되는지 확인 - FALSE") + void isSufficientForDeduction() { + //given + Member member = mock(Member.class); + Point point = new Point(100, member); + + //when then + assertFalse(point.isSufficientForDeduction(3000)); + } + + @Test + @DisplayName("차감이 되는지 확인 - TRUE") + void isSufficientForDeduction2() { + //given + Member member = mock(Member.class); + Point point = new Point(5000, member); + + //when then + assertTrue(point.isSufficientForDeduction(3000)); + } +} diff --git a/src/test/java/com/example/sinitto/point/service/PointServiceTest.java b/src/test/java/com/example/sinitto/point/service/PointServiceTest.java new file mode 100644 index 00000000..0108ed6d --- /dev/null +++ b/src/test/java/com/example/sinitto/point/service/PointServiceTest.java @@ -0,0 +1,60 @@ +package com.example.sinitto.point.service; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.point.dto.PointLogResponse; +import com.example.sinitto.point.entity.PointLog; +import com.example.sinitto.point.repository.PointLogRepository; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoSettings; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@MockitoSettings +class PointServiceTest { + + @Mock + MemberRepository memberRepository; + @Mock + PointLogRepository pointLogRepository; + @InjectMocks + PointService pointService; + + @Test + void getPointLogs() { + //given + Long memberId = 1L; + Pageable pageable = PageRequest.of(0, 10); + Member member = mock(Member.class); + PointLog pointLog = mock(PointLog.class); + + when(pointLog.getContent()).thenReturn("content"); + when(pointLog.getPrice()).thenReturn(10000); + when(pointLog.getStatus()).thenReturn(PointLog.Status.EARN); + + Page pointLogPage = new PageImpl<>(List.of(pointLog)); + + when(memberRepository.findById(memberId)).thenReturn(Optional.of(member)); + when(pointLogRepository.findAllByMember(member, pageable)).thenReturn(pointLogPage); + + //when + Page result = pointService.getPointLogs(memberId, pageable); + + //then + assertNotNull(result); + assertEquals(1, result.getTotalElements()); + assertEquals(PointLog.Status.EARN, result.getContent().getFirst().status()); + } +} diff --git a/src/test/java/com/example/sinitto/sinitto/entity/SinittoBankInfoTest.java b/src/test/java/com/example/sinitto/sinitto/entity/SinittoBankInfoTest.java new file mode 100644 index 00000000..e433e2ec --- /dev/null +++ b/src/test/java/com/example/sinitto/sinitto/entity/SinittoBankInfoTest.java @@ -0,0 +1,42 @@ +package com.example.sinitto.sinitto.entity; + +import com.example.sinitto.member.entity.Member; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class SinittoBankInfoTest { + + private SinittoBankInfo sinittoBankInfo; + private Member member; + + @BeforeEach + void setUp() { + member = new Member("John Doe", "123-4567", "johndoe@example.com", true); + sinittoBankInfo = new SinittoBankInfo("Bank A", "987654321", member); + } + + @Test + @DisplayName("SinittoBankInfo 생성자 테스트") + void testCreateSinittoBankInfo() { + SinittoBankInfo savedSinittoBankInfo = new SinittoBankInfo("new bank", "111-1111-1111", member); + + assertNotNull(savedSinittoBankInfo); + assertEquals("new bank", savedSinittoBankInfo.getBankName()); + assertEquals("111-1111-1111", savedSinittoBankInfo.getAccountNumber()); + assertEquals(member, savedSinittoBankInfo.getMember()); + } + + @Test + @DisplayName("SinittoBankInfo 업데이트 테스트") + void testUpdateSinittoBankInfo() { + sinittoBankInfo.updateSinitto("Bank B", "123456789"); + + assertNotNull(sinittoBankInfo); + assertEquals("Bank B", sinittoBankInfo.getBankName()); + assertEquals("123456789", sinittoBankInfo.getAccountNumber()); + } +} diff --git a/src/test/java/com/example/sinitto/sinitto/entity/SinittoTest.java b/src/test/java/com/example/sinitto/sinitto/entity/SinittoTest.java deleted file mode 100644 index 477dc24a..00000000 --- a/src/test/java/com/example/sinitto/sinitto/entity/SinittoTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.example.sinitto.sinitto.entity; - -import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.entity.Sinitto; -import com.example.sinitto.sinitto.repository.SinittoRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; - -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@DataJpaTest -class SinittoTest { - - @Mock - private SinittoRepository sinittoRepository; - - private Sinitto sinitto; - private Member member; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - member = new Member("John Doe", "123-4567", "johndoe@example.com", true); - sinitto = new Sinitto("Bank A", "987654321", member); - } - - @Test - void testCreateSinitto() { - when(sinittoRepository.save(sinitto)).thenReturn(sinitto); - - Sinitto savedSinitto = sinittoRepository.save(sinitto); - - assertNotNull(savedSinitto); - assertEquals("Bank A", savedSinitto.getBankName()); - assertEquals("987654321", savedSinitto.getAccountNumber()); - assertEquals(member, savedSinitto.getMember()); - - verify(sinittoRepository, times(1)).save(sinitto); - } - - @Test - void testUpdateSinitto() { - sinitto.updateSinitto("Bank B", "123456789"); - - when(sinittoRepository.save(sinitto)).thenReturn(sinitto); - - Sinitto updatedSinitto = sinittoRepository.save(sinitto); - - assertNotNull(updatedSinitto); - assertEquals("Bank B", updatedSinitto.getBankName()); - assertEquals("123456789", updatedSinitto.getAccountNumber()); - - verify(sinittoRepository, times(1)).save(sinitto); - } - - @Test - void testFindSinittoById() { - when(sinittoRepository.findById(1L)).thenReturn(Optional.of(sinitto)); - - Optional foundSinitto = sinittoRepository.findById(1L); - - assertTrue(foundSinitto.isPresent()); - assertEquals(sinitto.getId(), foundSinitto.get().getId()); - } - - @Test - void testDeleteSinitto() { - sinittoRepository.delete(sinitto); - verify(sinittoRepository, times(1)).delete(sinitto); - } -} diff --git a/src/test/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepositoryTest.java b/src/test/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepositoryTest.java new file mode 100644 index 00000000..58202c89 --- /dev/null +++ b/src/test/java/com/example/sinitto/sinitto/repository/SinittoBankInfoRepositoryTest.java @@ -0,0 +1,75 @@ +package com.example.sinitto.sinitto.repository; + +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.repository.MemberRepository; +import com.example.sinitto.sinitto.entity.SinittoBankInfo; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +@DataJpaTest +class SinittoBankInfoRepositoryTest { + + @Autowired + private SinittoBankInfoRepository sinittoBankInfoRepository; + + @Autowired + private MemberRepository memberRepository; + + private Member member; + private SinittoBankInfo sinittoBankInfo; + + @BeforeEach + void setUp() { + member = new Member("John Doe", "123-4567", "johndoe@example.com", true); + memberRepository.save(member); + + sinittoBankInfo = new SinittoBankInfo("Bank A", "987654321", member); + sinittoBankInfoRepository.save(sinittoBankInfo); + } + + @Test + @DisplayName("멤버 아이디 기반 시니또 은행 정보 불러오기 테스트") + void testFindByMemberId() { + Optional foundSinitto = sinittoBankInfoRepository.findByMemberId(member.getId()); + assertTrue(foundSinitto.isPresent()); + assertEquals(sinittoBankInfo.getBankName(), foundSinitto.get().getBankName()); + } + + @Test + @DisplayName("시니또 은행 정보 저장 테스트") + void testSaveSinittoBankInfo() { + Member newMember = new Member("new Jane Doe", "111-1111", "newjanedoe@example.com", true); + memberRepository.save(newMember); + + SinittoBankInfo newSinittoBankInfo = new SinittoBankInfo("Bank B", "123456789", newMember); + SinittoBankInfo savedSinittoBankInfo = sinittoBankInfoRepository.save(newSinittoBankInfo); + + assertNotNull(savedSinittoBankInfo); + assertEquals("Bank B", savedSinittoBankInfo.getBankName()); + } + + @Test + @DisplayName("시니또 은행 정보 삭제 테스트") + void testDeleteSinittoBankInfo() { + sinittoBankInfoRepository.delete(sinittoBankInfo); + Optional deletedSinitto = sinittoBankInfoRepository.findById(sinittoBankInfo.getId()); + assertFalse(deletedSinitto.isPresent()); + } + + @Test + @DisplayName("멤버 아이디 기반 존재여부 검증 테스트") + void testExistByMemberId() { + boolean check1 = sinittoBankInfoRepository.existsByMemberId(member.getId()); + assertTrue(check1); + + boolean check2 = sinittoBankInfoRepository.existsByMemberId(2L); + assertFalse(check2); + } +} diff --git a/src/test/java/com/example/sinitto/sinitto/repository/SinittoRepositoryTest.java b/src/test/java/com/example/sinitto/sinitto/repository/SinittoRepositoryTest.java deleted file mode 100644 index d5eae90b..00000000 --- a/src/test/java/com/example/sinitto/sinitto/repository/SinittoRepositoryTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.example.sinitto.sinitto.repository; - -import com.example.sinitto.member.entity.Member; -import com.example.sinitto.member.entity.Sinitto; -import com.example.sinitto.member.repository.MemberRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; - -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; - -@DataJpaTest -class SinittoRepositoryTest { - - @Autowired - private SinittoRepository sinittoRepository; - - @Autowired - private MemberRepository memberRepository; - - private Member member; - private Sinitto sinitto; - - @BeforeEach - void setUp() { - member = new Member("John Doe", "123-4567", "johndoe@example.com", true); - memberRepository.save(member); - - sinitto = new Sinitto("Bank A", "987654321", member); - sinittoRepository.save(sinitto); - } - - @Test - void testFindByMemberId() { - Optional foundSinitto = sinittoRepository.findByMemberId(member.getId()); - assertTrue(foundSinitto.isPresent()); - assertEquals(sinitto.getBankName(), foundSinitto.get().getBankName()); - } - - @Test - void testSaveSinitto() { - Member newMember = new Member("Jane Doe", "987-6543", "janedoe@example.com", true); - memberRepository.save(newMember); - - Sinitto newSinitto = new Sinitto("Bank B", "123456789", newMember); - Sinitto savedSinitto = sinittoRepository.save(newSinitto); - assertNotNull(savedSinitto); - assertEquals("Bank B", savedSinitto.getBankName()); - } - - - @Test - void testDeleteSinitto() { - sinittoRepository.delete(sinitto); - Optional deletedSinitto = sinittoRepository.findById(sinitto.getId()); - assertFalse(deletedSinitto.isPresent()); - } -}