diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExe.java index b1346882..e820eb5d 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExe.java @@ -21,6 +21,7 @@ import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Stream; import lombok.RequiredArgsConstructor; @@ -41,25 +42,23 @@ public class UserCpPairUserProfileQryExe { private final UserProfileGateway userProfileGateway; private final UserProfileAppConvertor userProfileAppConvertor; private final CpValueService cpValueService; - private final TaskMqMessage taskMqMessage; - + private final TaskMqMessage taskMqMessage; + public List execute(CpRelationshipQueryCmd cmd) { String relationType = CpRelationshipType.normalize(cmd.getRelationType()); + Long queryUserId = Optional.ofNullable(cmd.getUserId()).orElse(cmd.requiredReqUserId()); + boolean queryTargetUser = Objects.nonNull(cmd.getUserId()); - UserProfile meUser = userProfileGateway.getByUserId(cmd.requiredReqUserId()); + UserProfile meUser = userProfileGateway.getByUserId(queryUserId); ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, meUser); - List cpRelationshipList = Stream.concat( - cpRelationshipService.getByUserId(cmd.requiredReqUserId(), relationType).stream(), - cpRelationshipService.getDismissingByUserId(cmd.requiredReqUserId(), relationType) - .stream() - .filter(UserCpPairUserProfileQryExe::isDismissingVisible)) - .toList(); + List cpRelationshipList = queryRelationships(queryUserId, relationType, + queryTargetUser); if (cpRelationshipList.isEmpty()) { return Collections.emptyList(); } - - return cpRelationshipList.stream() + + return cpRelationshipList.stream() .map(cpRelationship -> new CpPairUserProfileCO() .setMeUserProfile(userProfileAppConvertor.toUserProfileDTO((meUser))) .setCpUserProfile(getUserProfile(cpRelationship.getCpUserId())) @@ -71,8 +70,22 @@ public class UserCpPairUserProfileQryExe { .setDismissEndTime(dismissEndTime(cpRelationship)) .setDismissRemainSeconds(dismissRemainSeconds(cpRelationship))) .sorted(Comparator.comparing(CpPairUserProfileCO::getCpValue).reversed()) + .limit(queryTargetUser ? relationMaxCount(relationType) : Long.MAX_VALUE) .toList(); } + + private List queryRelationships(Long queryUserId, String relationType, + boolean queryTargetUser) { + if (queryTargetUser) { + return cpRelationshipService.getByUserId(queryUserId, relationType); + } + return Stream.concat( + cpRelationshipService.getByUserId(queryUserId, relationType).stream(), + cpRelationshipService.getDismissingByUserId(queryUserId, relationType) + .stream() + .filter(UserCpPairUserProfileQryExe::isDismissingVisible)) + .toList(); + } private UserProfileDTO getUserProfile(Long cpUserId) { return userProfileAppConvertor.toUserProfileDTO(userProfileGateway @@ -91,6 +104,11 @@ public class UserCpPairUserProfileQryExe { return CpRelationshipType.normalize(cpRelationship.getRelationType()); } + private static long relationMaxCount(String relationType) { + return Objects.equals(CpRelationshipType.CP.name(), CpRelationshipType.normalize(relationType)) + ? 1L : 3L; + } + private static Long dismissEndTime(CpRelationship cpRelationship) { if (Objects.isNull(cpRelationship.getDismissTime())) { return null; diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExeTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExeTest.java new file mode 100644 index 00000000..a942c644 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/UserCpPairUserProfileQryExeTest.java @@ -0,0 +1,105 @@ +package com.red.circle.other.app.command.user.query; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import com.red.circle.mq.rocket.business.producer.TaskMqMessage; +import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; +import com.red.circle.other.app.dto.clientobject.user.relation.cp.CpPairUserProfileCO; +import com.red.circle.other.app.dto.cmd.user.relation.cp.CpRelationshipQueryCmd; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.domain.model.user.UserProfile; +import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship; +import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService; +import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; +import com.red.circle.other.infra.enums.user.user.CpRelationshipStatus; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import org.junit.jupiter.api.Test; + +class UserCpPairUserProfileQryExeTest { + + @Test + void targetUserQueryShouldReturnAtMostThreeNormalCloseFriendRelations() { + Fixture fixture = new Fixture(); + CpRelationshipQueryCmd cmd = new CpRelationshipQueryCmd() + .setUserId(2001L) + .setRelationType("BROTHER"); + cmd.setReqUserId(1001L); + + List result = fixture.exe.execute(cmd); + + assertEquals(3, result.size()); + assertEquals(List.of(2001L, 2001L, 2001L), + result.stream().map(item -> item.getMeUserProfile().getId()).toList()); + assertEquals(List.of(3004L, 3003L, 3002L), + result.stream().map(item -> item.getCpUserProfile().getId()).toList()); + verify(fixture.cpRelationshipService).getByUserId(2001L, "BROTHER"); + verifyNoInteractions(fixture.taskMqMessage); + } + + private static class Fixture { + + private final CpRelationshipService cpRelationshipService = mock(CpRelationshipService.class); + private final UserProfileGateway userProfileGateway = mock(UserProfileGateway.class); + private final UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class); + private final CpValueService cpValueService = mock(CpValueService.class); + private final TaskMqMessage taskMqMessage = mock(TaskMqMessage.class); + private final UserCpPairUserProfileQryExe exe = new UserCpPairUserProfileQryExe( + cpRelationshipService, userProfileGateway, userProfileAppConvertor, cpValueService, + taskMqMessage); + + private Fixture() { + when(userProfileGateway.getByUserId(2001L)).thenReturn(profile(2001L)); + when(userProfileAppConvertor.toUserProfileDTO(profile(2001L))).thenReturn(profileDto(2001L)); + for (long userId = 3001L; userId <= 3004L; userId++) { + when(userProfileGateway.getByUserId(userId)).thenReturn(profile(userId)); + when(userProfileAppConvertor.toUserProfileDTO(profile(userId))).thenReturn( + profileDto(userId)); + } + when(cpRelationshipService.getByUserId(2001L, "BROTHER")).thenReturn(List.of( + relationship(2001L, 3001L, 4001L), + relationship(2001L, 3002L, 4002L), + relationship(2001L, 3003L, 4003L), + relationship(2001L, 3004L, 4004L) + )); + when(cpValueService.getCpVal(4001L)).thenReturn(BigDecimal.valueOf(10)); + when(cpValueService.getCpVal(4002L)).thenReturn(BigDecimal.valueOf(20)); + when(cpValueService.getCpVal(4003L)).thenReturn(BigDecimal.valueOf(30)); + when(cpValueService.getCpVal(4004L)).thenReturn(BigDecimal.valueOf(40)); + } + + private static UserProfile profile(Long userId) { + UserProfile profile = new UserProfile(); + profile.setId(userId); + profile.setAccount("account" + userId); + profile.setUserNickname("user" + userId); + profile.setUserAvatar("https://example.com/" + userId + ".png"); + return profile; + } + + private static UserProfileDTO profileDto(Long userId) { + UserProfileDTO profile = new UserProfileDTO(); + profile.setId(userId); + profile.setAccount("account" + userId); + profile.setUserNickname("user" + userId); + profile.setUserAvatar("https://example.com/" + userId + ".png"); + return profile; + } + + private static CpRelationship relationship(Long userId, Long cpUserId, Long cpValId) { + return new CpRelationship() + .setUserId(userId) + .setCpUserId(cpUserId) + .setCpValId(cpValId) + .setRelationType("BROTHER") + .setStatus(CpRelationshipStatus.NORMAL.name()) + .setCreateTime(new Date(System.currentTimeMillis() - 86_400_000L)); + } + } +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/relation/cp/CpRelationshipQueryCmd.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/relation/cp/CpRelationshipQueryCmd.java index 1f3e5355..d12ab308 100644 --- a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/relation/cp/CpRelationshipQueryCmd.java +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/relation/cp/CpRelationshipQueryCmd.java @@ -17,4 +17,9 @@ public class CpRelationshipQueryCmd extends AppExtCommand { * 关系类型:CP/BROTHER/SISTERS,默认 CP. */ private String relationType; + + /** + * 要查询关系的用户 ID;为空时查询当前登录用户. + */ + private Long userId; }