修改删除掉自己的逻辑

This commit is contained in:
hy001 2026-04-28 23:18:43 +08:00
parent 9878d6bf81
commit 5339742f69
7 changed files with 248 additions and 47 deletions

View File

@ -28,9 +28,10 @@ import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileSe
import com.red.circle.other.infra.database.rds.entity.team.TeamTerminationFeeRecord;
import com.red.circle.other.infra.database.rds.service.team.BillDiamondBalanceDetailsService;
import com.red.circle.other.infra.database.rds.service.team.BillDiamondBalanceService;
import com.red.circle.other.infra.database.rds.service.team.TeamTerminationFeeRecordService;
import com.red.circle.other.inner.enums.material.BadgeKeyEnum;
import com.red.circle.other.inner.model.cmd.team.TeamMemberIdCmd;
import com.red.circle.other.infra.database.rds.service.team.TeamTerminationFeeRecordService;
import com.red.circle.other.inner.enums.material.BadgeKeyEnum;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.model.cmd.team.TeamMemberIdCmd;
import com.red.circle.other.inner.enums.team.TeamAppProcessApprovalReason;
import com.red.circle.other.inner.enums.team.TeamApplicationType;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
@ -181,12 +182,20 @@ public class TeamMemberRemoveDecay {
teamMemberTargetService.getLatestInProgressTarget(teamMember.getMemberId()));
}
private TeamMember processRemoveTeamMember(Long memberSortId) {
String lockKey = "REMOVE_TEAM_MEMBER:" + memberSortId;
if (!redisService.lock(lockKey, 60)) {
return null;
}
TeamMember teamMember = teamMemberService.removeMember(memberSortId);
private TeamMember processRemoveTeamMember(Long memberSortId) {
String lockKey = "REMOVE_TEAM_MEMBER:" + memberSortId;
if (!redisService.lock(lockKey, 60)) {
return null;
}
TeamMember existingTeamMember = teamMemberService.getByMemberId(memberSortId);
if (Objects.nonNull(existingTeamMember) && TeamMemberRole.OWN.eq(existingTeamMember.getRole())) {
redisService.unlock(lockKey);
ResponseAssert.isFalse(TeamErrorCode.PERMISSION_DENIED, true);
return null;
}
TeamMember teamMember = teamMemberService.removeMember(memberSortId);
if (Objects.isNull(teamMember)) {
redisService.unlock(lockKey);
return null;

View File

@ -7,13 +7,15 @@ import com.mongodb.BasicDBObject;
import com.red.circle.common.business.core.enums.OpUserType;
import com.red.circle.common.business.enums.OperationUserOrigin;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.dto.team.TeamMemberCount;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.inner.model.cmd.team.TeamMemberBackQryCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamRemark;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.infra.database.mongo.dto.team.TeamMemberCount;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.inner.model.cmd.team.TeamMemberBackQryCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamRemark;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
@ -136,11 +138,28 @@ public class TeamMemberServiceImpl implements TeamMemberService {
TeamMember.class);
}
@Override
public TeamMember getByMemberId(Long memberId) {
return mongoTemplate.findOne(Query.query(Criteria.where("memberId").is(memberId)),
TeamMember.class);
}
@Override
public TeamMember getByMemberId(Long memberId) {
List<TeamMember> teamMembers = mongoTemplate.find(Query.query(Criteria.where("memberId").is(memberId))
.with(Sort.by(Sort.Order.desc("sortId"))),
TeamMember.class);
if (CollectionUtils.isEmpty(teamMembers)) {
return null;
}
Set<Long> availableTeamIds = mongoTemplate.find(Query.query(Criteria.where("id")
.in(teamMembers.stream().map(TeamMember::getTeamId).collect(Collectors.toSet()))
.and("status").is(TeamStatus.AVAILABLE)),
TeamProfile.class)
.stream()
.map(TeamProfile::getId)
.collect(Collectors.toSet());
return teamMembers.stream()
.filter(teamMember -> availableTeamIds.contains(teamMember.getTeamId()))
.findFirst()
.orElse(teamMembers.get(0));
}
@Override
public TeamMember getTeamOwn(Long teamId) {

View File

@ -4,10 +4,12 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.mongodb.BasicDBObject;
import com.red.circle.common.business.core.enums.OpUserType;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.common.business.core.enums.OpUserType;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.cmd.team.StatusTeamBatchCmd;
import com.red.circle.other.inner.model.cmd.team.TeamTableQryCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamContact;
@ -61,9 +63,7 @@ public class TeamProfileServiceImpl implements TeamProfileService {
@Override
public boolean existsAvailableOwnUserId(Long ownUserId) {
return mongoTemplate.exists(Query.query(Criteria.where("ownUserId").is(ownUserId)
.and("status").is(TeamStatus.AVAILABLE)),
TeamProfile.class);
return Objects.nonNull(getAvailableByOwnUserId(ownUserId));
}
@Override
@ -236,12 +236,14 @@ public class TeamProfileServiceImpl implements TeamProfileService {
criteria.andOperator(andOperator);
}
return mongoTemplate.find(Query.query(criteria)
.with(Sort.by(Sort.Order.desc("id")))
.limit(
Objects.nonNull(query.getLimit()) ? query.getLimit() : PageConstant.DEFAULT_LIMIT_SIZE),
TeamProfile.class);
}
List<TeamProfile> teamProfiles = mongoTemplate.find(Query.query(criteria)
.with(Sort.by(Sort.Order.desc("id")))
.limit(
Objects.nonNull(query.getLimit()) ? query.getLimit() : PageConstant.DEFAULT_LIMIT_SIZE),
TeamProfile.class);
return filterCurrentAvailableOwnProfiles(teamProfiles);
}
@Override
public List<TeamProfile> listRegion(String region, Integer limit) {
@ -285,9 +287,59 @@ public class TeamProfileServiceImpl implements TeamProfileService {
@Override
public TeamProfile getAvailableByOwnUserId(Long ownUserId) {
return mongoTemplate.findOne(Query.query(Criteria.where("ownUserId").is(ownUserId)
.and("status").is(TeamStatus.AVAILABLE)),
List<TeamProfile> teamProfiles = mongoTemplate.find(
Query.query(Criteria.where("ownUserId").is(ownUserId)
.and("status").is(TeamStatus.AVAILABLE))
.with(Sort.by(Sort.Order.desc("id"))),
TeamProfile.class);
return filterCurrentAvailableOwnProfiles(teamProfiles).stream().findFirst().orElse(null);
}
private List<TeamProfile> filterCurrentAvailableOwnProfiles(List<TeamProfile> teamProfiles) {
if (CollectionUtils.isEmpty(teamProfiles)) {
return teamProfiles;
}
List<TeamProfile> availableProfiles = teamProfiles.stream()
.filter(teamProfile -> TeamStatus.AVAILABLE.equals(teamProfile.getStatus()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(availableProfiles)) {
return teamProfiles;
}
Set<Long> teamIds = availableProfiles.stream()
.map(TeamProfile::getId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Set<Long> ownUserIds = availableProfiles.stream()
.map(TeamProfile::getOwnUserId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(teamIds) || CollectionUtils.isEmpty(ownUserIds)) {
return teamProfiles.stream()
.filter(teamProfile -> !TeamStatus.AVAILABLE.equals(teamProfile.getStatus()))
.collect(Collectors.toList());
}
Set<String> currentOwnerKeys = mongoTemplate.find(Query.query(Criteria.where("teamId").in(teamIds)
.and("memberId").in(ownUserIds)
.and("role").is(TeamMemberRole.OWN)),
TeamMember.class)
.stream()
.map(teamMember -> ownerKey(teamMember.getTeamId(), teamMember.getMemberId()))
.collect(Collectors.toSet());
return teamProfiles.stream()
.filter(teamProfile -> !TeamStatus.AVAILABLE.equals(teamProfile.getStatus())
|| currentOwnerKeys.contains(ownerKey(teamProfile.getId(), teamProfile.getOwnUserId())))
.collect(Collectors.toList());
}
private String ownerKey(Long teamId, Long ownUserId) {
return teamId + "_" + ownUserId;
}
@Override

View File

@ -0,0 +1,41 @@
package com.red.circle.other.infra.database.mongo.service.team.team.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
class TeamMemberServiceImplTest {
@Test
void getByMemberIdShouldPreferAvailableTeamMemberWhenHistoricalRowsExist() {
MongoTemplate mongoTemplate = mock(MongoTemplate.class);
TeamMemberServiceImpl service = new TeamMemberServiceImpl(mongoTemplate);
TeamMember closedMember = member(1L, 100L, 10L);
TeamMember availableMember = member(2L, 100L, 20L);
when(mongoTemplate.find(any(Query.class), eq(TeamMember.class)))
.thenReturn(List.of(closedMember, availableMember));
when(mongoTemplate.find(any(Query.class), eq(TeamProfile.class)))
.thenReturn(List.of(new TeamProfile().setId(20L).setStatus(TeamStatus.AVAILABLE)));
assertEquals(availableMember, service.getByMemberId(100L));
}
private TeamMember member(Long sortId, Long memberId, Long teamId) {
return new TeamMember()
.setSortId(sortId)
.setMemberId(memberId)
.setTeamId(teamId);
}
}

View File

@ -0,0 +1,66 @@
package com.red.circle.other.infra.database.mongo.service.team.team.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.cmd.team.TeamTableQryCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
class TeamProfileServiceImplTest {
@Test
void listShouldHideAvailableProfileWithoutCurrentOwnerMember() {
MongoTemplate mongoTemplate = mock(MongoTemplate.class);
TeamProfileServiceImpl service = new TeamProfileServiceImpl(mongoTemplate);
TeamProfile orphanAvailable = profile(1L, 10L, TeamStatus.AVAILABLE);
TeamProfile currentAvailable = profile(2L, 20L, TeamStatus.AVAILABLE);
TeamProfile closed = profile(3L, 30L, TeamStatus.CLOSE);
when(mongoTemplate.find(any(Query.class), eq(TeamProfile.class)))
.thenReturn(List.of(orphanAvailable, currentAvailable, closed));
when(mongoTemplate.find(any(Query.class), eq(TeamMember.class)))
.thenReturn(List.of(member(2L, 20L, TeamMemberRole.OWN)));
List<TeamProfile> result = service.list(new TeamTableQryCmd());
assertEquals(List.of(currentAvailable, closed), result);
}
@Test
void getAvailableByOwnUserIdShouldIgnoreProfileWithoutCurrentOwnerMember() {
MongoTemplate mongoTemplate = mock(MongoTemplate.class);
TeamProfileServiceImpl service = new TeamProfileServiceImpl(mongoTemplate);
when(mongoTemplate.find(any(Query.class), eq(TeamProfile.class)))
.thenReturn(List.of(profile(1L, 10L, TeamStatus.AVAILABLE)));
when(mongoTemplate.find(any(Query.class), eq(TeamMember.class))).thenReturn(List.of());
assertNull(service.getAvailableByOwnUserId(10L));
}
private TeamProfile profile(Long teamId, Long ownUserId, TeamStatus status) {
return new TeamProfile()
.setId(teamId)
.setOwnUserId(ownUserId)
.setStatus(status);
}
private TeamMember member(Long teamId, Long memberId, TeamMemberRole role) {
return new TeamMember()
.setTeamId(teamId)
.setMemberId(memberId)
.setRole(role);
}
}

View File

@ -76,9 +76,11 @@ class UserRegionGatewayImplTest {
region("SA", "IN,BD", "en,hi"),
region("OTHER", "", "")
));
when(userProfileGateway.listByUserIds(Set.of(USER_ID))).thenReturn(List.of(
new UserProfile().setId(USER_ID).setOriginSys(SYS_ORIGIN).setCountryCode("JP")
));
UserProfile userProfile = new UserProfile();
userProfile.setId(USER_ID);
userProfile.setOriginSys(SYS_ORIGIN);
userProfile.setCountryCode("JP");
when(userProfileGateway.listByUserIds(Set.of(USER_ID))).thenReturn(List.of(userProfile));
when(countryCodeAliasSupport.containsCode("IN,BD", "JP")).thenReturn(false);
}

View File

@ -211,10 +211,10 @@ public class TeamProfileClientServiceImpl implements TeamProfileClientService {
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
ResponseAssert.isTrue(UserErrorCode.USER_INFO_NOT_FOUND,
Objects.equals(userProfile.getOriginSys(), cmd.getSysOrigin()));
ResponseAssert.isFalse(TeamErrorCode.USER_ALREADY_TEAM_OWN,
teamProfileService.existsOwnUserId(userProfile.getId()));
ResponseAssert.isFalse(TeamErrorCode.USER_ALREADY_TEAM_MEMBER,
teamMemberService.existsMember(userProfile.getId()));
ResponseAssert.isFalse(TeamErrorCode.USER_ALREADY_TEAM_OWN,
teamProfileService.existsAvailableOwnUserId(userProfile.getId()));
ResponseAssert.isFalse(TeamErrorCode.USER_ALREADY_TEAM_MEMBER,
existsAvailableTeamMember(userProfile.getId()));
// 验证BD关系
if (Objects.nonNull(cmd.getBdUserId())) {
@ -338,10 +338,22 @@ public class TeamProfileClientServiceImpl implements TeamProfileClientService {
userMqMessageService.sendBadgeOperateEvent(userProfile.getId(), BadgeKeyEnum.AGENCY.name(), BadgeOperateEvent.OperationType.WEAR.name());
userMqMessageService.sendBadgeOperateEvent(userProfile.getId(), BadgeKeyEnum.HOST.name(), BadgeOperateEvent.OperationType.WEAR.name());
redisService.unlock(key);
}
private TeamProfileDTO TeamProfileDTOConvertor(TeamCreateCmd cmd) {
redisService.unlock(key);
}
private boolean existsAvailableTeamMember(Long userId) {
TeamMember teamMember = teamMemberService.getByMemberId(userId);
if (Objects.isNull(teamMember)) {
return false;
}
TeamProfile teamProfile = teamProfileService.getById(teamMember.getTeamId());
return Objects.nonNull(teamProfile)
&& TeamStatus.AVAILABLE.equals(teamProfile.getStatus())
&& teamProfileService.existsAvailableOwnUserId(teamProfile.getOwnUserId());
}
private TeamProfileDTO TeamProfileDTOConvertor(TeamCreateCmd cmd) {
return new TeamProfileDTO()
.setRegion(cmd.getRegion())
.setSysOrigin(cmd.getSysOrigin())