From 2c48077d415c02ae115c6502c158104ca6d7b2ac Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Mon, 10 Jun 2024 11:51:16 +0900 Subject: [PATCH 1/7] =?UTF-8?q?#192=20fix:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sharemind/counselor/presentation/CounselorController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/sharemind/counselor/presentation/CounselorController.java b/src/main/java/com/example/sharemind/counselor/presentation/CounselorController.java index 8c7d405e..37a8d926 100644 --- a/src/main/java/com/example/sharemind/counselor/presentation/CounselorController.java +++ b/src/main/java/com/example/sharemind/counselor/presentation/CounselorController.java @@ -50,7 +50,7 @@ public class CounselorController { }) @PostMapping("/quiz") public ResponseEntity updateIsEducated(@RequestParam Boolean isEducated, - @AuthenticationPrincipal CustomUserDetails customUserDetails) { + @AuthenticationPrincipal CustomUserDetails customUserDetails) { counselorService.updateIsEducated(isEducated, customUserDetails.getCustomer().getCustomerId()); return ResponseEntity.ok().build(); @@ -201,7 +201,7 @@ public ResponseEntity getCounselorForConsultCrea - 들을 준비가 된 마인더들(상담사 전체 리스트)조회의 경우, RequestBody에서 consultCategory를 빼고 넘겨주시면 됩니다.""") @ApiResponses({ @ApiResponse(responseCode = "200", description = "조회 성공"), - @ApiResponse(responseCode = "404", description = "1. sortType이 잘못된 경우 2. RequestBody의 카테고리가 잘못도니 경우", + @ApiResponse(responseCode = "404", description = "1. sortType이 잘못된 경우 2. RequestBody의 카테고리가 잘못된 경우", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CustomExceptionResponse.class)) ) From c429ef42f8e44b4538750bcc3f1c36aa7ff02682 Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Mon, 10 Jun 2024 11:51:44 +0900 Subject: [PATCH 2/7] =?UTF-8?q?#192=20feat:=20=EC=A0=95=EA=B0=81=EB=A7=88?= =?UTF-8?q?=EB=8B=A4=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EC=83=81=EB=8B=B4?= =?UTF-8?q?=EC=82=AC=20=EA=B2=80=EC=82=AC=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/CounselorServiceImpl.java | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java index f14e0028..d65f01c2 100644 --- a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java +++ b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java @@ -23,11 +23,15 @@ import com.example.sharemind.wishList.application.WishListCounselorService; import com.example.sharemind.wishList.domain.WishList; import com.example.sharemind.wishList.dto.request.WishListGetRequest; +import java.time.LocalDate; +import java.time.LocalTime; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Page; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,10 +44,12 @@ public class CounselorServiceImpl implements CounselorService { private static final int COUNSELOR_PAGE = 4; + private static final String SPLIT_HOURS = "~"; private final CounselorRepository counselorRepository; private final CustomerService customerService; private final WishListCounselorService wishListCounselorService; + private final RedisTemplate> redisTemplate; @Override public Counselor getCounselorByCounselorId(Long counselorId) { @@ -107,7 +113,7 @@ public Boolean getRetryPermission(Long customerId) { @Transactional @Override public void updateCounselorProfile(CounselorUpdateProfileRequest counselorUpdateProfileRequest, - Long customerId) { + Long customerId) { Counselor counselor = getCounselorByCustomerId(customerId); if ((counselor.getIsEducated() == null) || (!counselor.getIsEducated())) { throw new CounselorException(CounselorErrorCode.COUNSELOR_NOT_EDUCATED); @@ -223,7 +229,8 @@ public List getCounselorByWordWithPagination( @Override public List getCounselorsByCategoryAndCustomer(Long customerId, - String sortType, CounselorGetRequest counselorGetRequest) { + String sortType, + CounselorGetRequest counselorGetRequest) { List counselors = getCounselorByCategoryWithPagination(counselorGetRequest, sortType); @@ -239,7 +246,7 @@ public List getCounselorsByCategoryAndCustomer(Long cu @Override public List getAllCounselorsByCategory(String sortType, - CounselorGetRequest counselorGetRequest) { + CounselorGetRequest counselorGetRequest) { List counselors = getCounselorByCategoryWithPagination(counselorGetRequest, sortType); @@ -250,7 +257,7 @@ public List getAllCounselorsByCategory(String sortType @Override public CounselorGetMinderProfileResponse getCounselorMinderProfileByCustomer(Long counselorId, - Long customerId) { + Long customerId) { Customer customer = customerService.getCustomerByCustomerId(customerId); Counselor counselor = getCounselorByCounselorId(counselorId); @@ -268,7 +275,7 @@ public CounselorGetMinderProfileResponse getAllCounselorMinderProfile(Long couns @Transactional @Override public void updateAccount(CounselorUpdateAccountRequest counselorUpdateAccountRequest, - Long customerId) { + Long customerId) { Counselor counselor = getCounselorByCustomerId(customerId); Bank.existsByDisplayName(counselorUpdateAccountRequest.getBank()); counselor.updateAccountInfo(counselorUpdateAccountRequest.getAccount(), @@ -302,7 +309,7 @@ public CounselorGetInfoResponse getCounselorMyInfo(Long customerId) { @Override public CounselorGetForConsultResponse getCounselorForConsultCreation(Long counselorId, - String type) { + String type) { Counselor counselor = getCounselorByCounselorId(counselorId); ConsultType consultType = ConsultType.getConsultTypeByName(type); if (!counselor.getConsultTypes().contains(consultType)) { @@ -342,4 +349,38 @@ public void checkCounselorAndCustomerSame(Customer customer, Counselor counselor customer.getCustomerId().toString()); } } + + @Scheduled(cron = "0 0 * * * *", zone = "Asia/Seoul") + public void updateRealtimeCounselors() { + List counselors = counselorRepository.findAllByIsEducatedIsTrueAndIsActivatedIsTrue(); + String currentDay = LocalDate.now().getDayOfWeek().toString().substring(0, 3).toUpperCase(); + int currentHour = LocalTime.now().getHour(); + + List realtimeCounselors = counselors.stream() + .filter(counselor -> isAvailableAtRealTime(counselor.getConsultTimes(), currentDay, currentHour)) + .sorted((c1, c2) -> Long.compare(c2.getTotalConsult(), c1.getTotalConsult())) + .toList(); + + List counselorIds = realtimeCounselors.stream() + .map(Counselor::getCounselorId) + .toList(); + + redisTemplate.opsForValue().set("availableCounselors", counselorIds); + } + + private boolean isAvailableAtRealTime(Set consultTimes, String day, int hour) { + for (ConsultTime consultTime : consultTimes) { + if (Objects.equals(consultTime.getDay().toString(), day)) { + for (String timeRange : consultTime.getTimes()) { + String[] parts = timeRange.split(SPLIT_HOURS); + int startHour = Integer.parseInt(parts[0]); + int endHour = Integer.parseInt(parts[1]); + if (hour >= startHour && hour < endHour) { + return true; + } + } + } + } + return false; + } } From 152cf4769888b92f9c9df63938b92b1a84e8b9ff Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Mon, 10 Jun 2024 13:25:06 +0900 Subject: [PATCH 3/7] =?UTF-8?q?#192=20feat:=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=A0=91=EC=86=8D=20=EC=97=AC=EB=B6=80=20Response=20dto?= =?UTF-8?q?=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/CounselorGetListResponse.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java b/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java index 06cbd33e..60527dfb 100644 --- a/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java +++ b/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java @@ -23,16 +23,20 @@ public class CounselorGetListResponse extends CounselorGetBaseResponse { @Schema(description = "찜여부", example = "true") private final Boolean isWishList; - private CounselorGetListResponse(Counselor counselor, Boolean isWishList) { + @Schema(description = "현재 접속 여부", example = "true") + private final Boolean isRealtime; + + private CounselorGetListResponse(Counselor counselor, Boolean isWishList, Boolean isRealtime) { super(counselor); this.counselorId = counselor.getCounselorId(); this.level = counselor.getLevel(); this.totalReview = counselor.getTotalReview(); this.ratingAverage = counselor.getRatingAverage(); this.isWishList = isWishList; + this.isRealtime = isRealtime; } - public static CounselorGetListResponse of(Counselor counselor, Boolean isWishList) { - return new CounselorGetListResponse(counselor, isWishList); + public static CounselorGetListResponse of(Counselor counselor, Boolean isWishList, Boolean isRealtime) { + return new CounselorGetListResponse(counselor, isWishList, isRealtime); } } From a17b4115d0444ecaa046c9eb2a99c4487d8368ad Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Mon, 10 Jun 2024 13:25:38 +0900 Subject: [PATCH 4/7] =?UTF-8?q?#192=20fix:=20=EC=8B=A4=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=20=EC=A0=91=EC=86=8D=20=EC=97=AC=EB=B6=80=20=ED=8F=AC=ED=95=A8?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EB=A6=AC=ED=84=B4=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/CounselorServiceImpl.java | 38 +++++++++++++++---- .../application/SearchWordServiceImpl.java | 24 +++++++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java index d65f01c2..3665e5b1 100644 --- a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java +++ b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java @@ -1,5 +1,7 @@ package com.example.sharemind.counselor.application; +import static com.example.sharemind.global.constants.Constants.REALTIME_COUNSELOR; + import com.example.sharemind.chat.domain.Chat; import com.example.sharemind.counselor.content.Bank; import com.example.sharemind.counselor.content.ConsultStyle; @@ -204,7 +206,7 @@ private List getCounselorByCategoryWithPagination( Pageable pageable = PageRequest.of(counselorGetRequest.getIndex(), COUNSELOR_PAGE, Sort.by(sortColumn).descending()); if (counselorGetRequest.getConsultCategory() == null) { - return counselorRepository.findByLevelAndStatus(pageable).getContent(); + return getRealtimeCounselors(counselorGetRequest.getIndex()); } ConsultCategory consultCategory = ConsultCategory.getConsultCategoryByName( @@ -213,6 +215,16 @@ private List getCounselorByCategoryWithPagination( .getContent(); } + private List getRealtimeCounselors(int index) { + int start = index * COUNSELOR_PAGE; + List counselorIds = redisTemplate.opsForValue().get(REALTIME_COUNSELOR); + + List counselorsSubList = + counselorIds != null && counselorIds.size() >= 3 ? counselorIds.subList(start, start + COUNSELOR_PAGE) + : counselorIds; + return counselorRepository.findAllById(counselorsSubList); + } + @Override public List getCounselorByWordWithPagination( SearchWordCounselorFindRequest searchWordCounselorFindRequest, @@ -233,14 +245,20 @@ public List getCounselorsByCategoryAndCustomer(Long cu CounselorGetRequest counselorGetRequest) { List counselors = getCounselorByCategoryWithPagination(counselorGetRequest, sortType); - + List counselorIds = redisTemplate.opsForValue().get(REALTIME_COUNSELOR); Customer customer = customerService.getCustomerByCustomerId(customerId); Set wishListCounselorIds = wishListCounselorService.getWishListCounselorIdsByCustomer( customer); - + if (counselorIds == null) { + return counselors.stream() + .map(counselor -> CounselorGetListResponse.of(counselor, + wishListCounselorIds.contains(counselor.getCounselorId()), false)) + .toList(); + } return counselors.stream() .map(counselor -> CounselorGetListResponse.of(counselor, - wishListCounselorIds.contains(counselor.getCounselorId()))) + wishListCounselorIds.contains(counselor.getCounselorId()), + counselorIds.contains(counselor.getCounselorId()))) .toList(); } @@ -249,9 +267,15 @@ public List getAllCounselorsByCategory(String sortType CounselorGetRequest counselorGetRequest) { List counselors = getCounselorByCategoryWithPagination(counselorGetRequest, sortType); - + List counselorIds = redisTemplate.opsForValue().get(REALTIME_COUNSELOR); + if (counselorIds == null) { + return counselors.stream() + .map(counselor -> CounselorGetListResponse.of(counselor, false, false)) + .toList(); + } return counselors.stream() - .map(counselor -> CounselorGetListResponse.of(counselor, false)) + .map(counselor -> CounselorGetListResponse.of(counselor, false, + counselorIds.contains(counselor.getCounselorId()))) .toList(); } @@ -365,7 +389,7 @@ public void updateRealtimeCounselors() { .map(Counselor::getCounselorId) .toList(); - redisTemplate.opsForValue().set("availableCounselors", counselorIds); + redisTemplate.opsForValue().set(REALTIME_COUNSELOR, counselorIds); } private boolean isAvailableAtRealTime(Set consultTimes, String day, int hour) { diff --git a/src/main/java/com/example/sharemind/searchWord/application/SearchWordServiceImpl.java b/src/main/java/com/example/sharemind/searchWord/application/SearchWordServiceImpl.java index 3d427dfa..7e523cc0 100644 --- a/src/main/java/com/example/sharemind/searchWord/application/SearchWordServiceImpl.java +++ b/src/main/java/com/example/sharemind/searchWord/application/SearchWordServiceImpl.java @@ -1,5 +1,7 @@ package com.example.sharemind.searchWord.application; +import static com.example.sharemind.global.constants.Constants.REALTIME_COUNSELOR; + import com.example.sharemind.counselor.application.CounselorService; import com.example.sharemind.counselor.domain.Counselor; import com.example.sharemind.counselor.dto.response.CounselorGetListResponse; @@ -40,6 +42,7 @@ public class SearchWordServiceImpl implements SearchWordService { private final PostScrapRepository postScrapRepository; private final RedisTemplate redisTemplate; + private final RedisTemplate> counselorRedisTemplate; @Transactional @Override @@ -50,13 +53,18 @@ public List storeSearchWordAndGetCounselorsByCustomer( List counselors = counselorService.getCounselorByWordWithPagination(searchWordCounselorFindRequest, sortType); - + List counselorIds = counselorRedisTemplate.opsForValue().get(REALTIME_COUNSELOR); Customer customer = customerService.getCustomerByCustomerId(customerId); Set wishListCounselorIds = wishListCounselorService.getWishListCounselorIdsByCustomer(customer); - + if (counselorIds == null) { + return counselors.stream() + .map(counselor -> CounselorGetListResponse.of(counselor, + wishListCounselorIds.contains(counselor.getCounselorId()), false)) + .toList(); + } return counselors.stream() .map(counselor -> CounselorGetListResponse.of(counselor, - wishListCounselorIds.contains(counselor.getCounselorId()))) + wishListCounselorIds.contains(counselor.getCounselorId()), counselorIds.contains(counselor.getCounselorId()))) .toList(); } @@ -68,9 +76,14 @@ public List storeAllSearchWordAndGetCounselors(String List counselors = counselorService.getCounselorByWordWithPagination(searchWordCounselorFindRequest, sortType); - + List counselorIds = counselorRedisTemplate.opsForValue().get(REALTIME_COUNSELOR); + if (counselorIds == null) { + return counselors.stream() + .map(counselor -> CounselorGetListResponse.of(counselor, false, false)) + .toList(); + } return counselors.stream() - .map(counselor -> CounselorGetListResponse.of(counselor, false)) + .map(counselor -> CounselorGetListResponse.of(counselor, false, counselorIds.contains(counselor.getCounselorId()))) .toList(); } @@ -79,7 +92,6 @@ public List storeAllSearchWordAndGetCounselors(String public List storeAllSearchWordAndGetPosts(String sortType, SearchWordPostFindRequest searchWordPostFindRequest) { storeSearchWordInDB(searchWordPostFindRequest.getWord()); - List posts = postService.getPostByWordWithPagination(searchWordPostFindRequest, sortType); return posts.stream() From b600898935a4a7f08f1fcb37d3c6adf4c6d7be6e Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Mon, 10 Jun 2024 13:25:51 +0900 Subject: [PATCH 5/7] =?UTF-8?q?#192=20feat:=20REALTIME=5FCOUNSELOR=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/sharemind/global/constants/Constants.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/example/sharemind/global/constants/Constants.java b/src/main/java/com/example/sharemind/global/constants/Constants.java index 14743c3e..4e901d7b 100644 --- a/src/main/java/com/example/sharemind/global/constants/Constants.java +++ b/src/main/java/com/example/sharemind/global/constants/Constants.java @@ -8,6 +8,8 @@ public class Constants { public static final String CUSTOMER_CHATTING_PREFIX = "customer chatting: "; // 현재 접속중인 방 public static final String COUNSELOR_CHATTING_PREFIX = "counselor chatting: "; + public static final String REALTIME_COUNSELOR = "realtimeCounselors"; + public static final Integer CUSTOMER_ONGOING_CONSULT = 1; public static final Integer COUNSELOR_ONGOING_CONSULT = 3; From 9b403c658ad47ca71e6b9bc15e5a974efb909880 Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Thu, 20 Jun 2024 03:16:57 +0900 Subject: [PATCH 6/7] =?UTF-8?q?#192=20fix:=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sharemind/counselor/application/CounselorServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java index 3665e5b1..159fdb3a 100644 --- a/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java +++ b/src/main/java/com/example/sharemind/counselor/application/CounselorServiceImpl.java @@ -220,7 +220,7 @@ private List getRealtimeCounselors(int index) { List counselorIds = redisTemplate.opsForValue().get(REALTIME_COUNSELOR); List counselorsSubList = - counselorIds != null && counselorIds.size() >= 3 ? counselorIds.subList(start, start + COUNSELOR_PAGE) + counselorIds != null && counselorIds.size() >= COUNSELOR_PAGE ? counselorIds.subList(start, start + COUNSELOR_PAGE) : counselorIds; return counselorRepository.findAllById(counselorsSubList); } From 5b6da17d54f5b17d607233b2b8c3fdd84e22e216 Mon Sep 17 00:00:00 2001 From: aeyongdodam Date: Thu, 20 Jun 2024 03:20:32 +0900 Subject: [PATCH 7/7] =?UTF-8?q?#192=20fix:=20=EC=83=81=EB=8B=B4=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=ED=9A=9F=EC=88=98=20response=20dto?= =?UTF-8?q?=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../counselor/dto/response/CounselorGetListResponse.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java b/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java index 60527dfb..f9a18778 100644 --- a/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java +++ b/src/main/java/com/example/sharemind/counselor/dto/response/CounselorGetListResponse.java @@ -26,6 +26,9 @@ public class CounselorGetListResponse extends CounselorGetBaseResponse { @Schema(description = "현재 접속 여부", example = "true") private final Boolean isRealtime; + @Schema(description = "상담 완료 횟수") + private final Long totalConsult; + private CounselorGetListResponse(Counselor counselor, Boolean isWishList, Boolean isRealtime) { super(counselor); this.counselorId = counselor.getCounselorId(); @@ -34,6 +37,7 @@ private CounselorGetListResponse(Counselor counselor, Boolean isWishList, Boolea this.ratingAverage = counselor.getRatingAverage(); this.isWishList = isWishList; this.isRealtime = isRealtime; + this.totalConsult = counselor.getTotalConsult(); } public static CounselorGetListResponse of(Counselor counselor, Boolean isWishList, Boolean isRealtime) {