CP关系申请 问题修复
This commit is contained in:
parent
e5eeebf84a
commit
0260498bd3
@ -108,6 +108,9 @@ public class SendCpApplyCmdExe {
|
|||||||
ResponseAssert.isFalse(UserRelationErrorCode.UNAVAILABLE_OPS_YOURSELF,
|
ResponseAssert.isFalse(UserRelationErrorCode.UNAVAILABLE_OPS_YOURSELF,
|
||||||
Objects.equals(sendUserId, acceptUserId));
|
Objects.equals(sendUserId, acceptUserId));
|
||||||
|
|
||||||
|
cpApplyService.expireOverdueWaitApplies(sendUserId);
|
||||||
|
cpApplyService.expireOverdueWaitApplies(acceptUserId);
|
||||||
|
|
||||||
boolean eqRegion = userRegionGateway.checkEqRegion(sendUserId, acceptUserId);
|
boolean eqRegion = userRegionGateway.checkEqRegion(sendUserId, acceptUserId);
|
||||||
ResponseAssert.isTrue(UserRelationErrorCode.UNAVAILABLE_NOT_REGION, eqRegion);
|
ResponseAssert.isTrue(UserRelationErrorCode.UNAVAILABLE_NOT_REGION, eqRegion);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,8 @@ package com.red.circle.other.app.command.user.query;
|
|||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyIdQueryCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyIdQueryCmd;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
import java.util.Optional;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -16,13 +17,27 @@ import org.springframework.stereotype.Component;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CpApplyIdQryExe {
|
public class CpApplyIdQryExe {
|
||||||
|
|
||||||
private final CpApplyService cpApplyService;
|
private final CpApplyService cpApplyService;
|
||||||
|
|
||||||
public String execute(CpApplyIdQueryCmd cmd) {
|
public String execute(CpApplyIdQueryCmd cmd) {
|
||||||
return Optional.ofNullable(cpApplyService.getId(cmd.requiredReqUserId(), cmd.getUserId(),
|
Long currentUserId = cmd.requiredReqUserId();
|
||||||
CpRelationshipType.normalize(cmd.getRelationType())))
|
Long targetUserId = cmd.getUserId();
|
||||||
|
String relationType = CpRelationshipType.normalize(cmd.getRelationType());
|
||||||
|
cpApplyService.expireOverdueWaitApplies(currentUserId);
|
||||||
|
cpApplyService.expireOverdueWaitApplies(targetUserId);
|
||||||
|
|
||||||
|
Long applyId = cpApplyService.getId(targetUserId, currentUserId, relationType);
|
||||||
|
if (isEmptyApplyId(applyId)) {
|
||||||
|
applyId = cpApplyService.getId(currentUserId, targetUserId, relationType);
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(applyId)
|
||||||
|
.filter(id -> id > 0)
|
||||||
.map(String::valueOf)
|
.map(String::valueOf)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private boolean isEmptyApplyId(Long applyId) {
|
||||||
|
return Objects.isNull(applyId) || applyId <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package com.red.circle.other.app.command.user.query;
|
|||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyStatusQueryCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyStatusQueryCmd;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
|
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -14,10 +16,26 @@ import org.springframework.stereotype.Component;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CpApplyStatusQryExe {
|
public class CpApplyStatusQryExe {
|
||||||
|
|
||||||
|
private static final long APPLY_WAIT_EXPIRE_HOURS = 24L;
|
||||||
|
|
||||||
private final CpApplyService cpApplyService;
|
private final CpApplyService cpApplyService;
|
||||||
|
|
||||||
public String execute(CpApplyStatusQueryCmd cmd) {
|
public String execute(CpApplyStatusQueryCmd cmd) {
|
||||||
CpApply cpApply = cpApplyService.getById(cmd.getApplyId());
|
CpApply cpApply = cpApplyService.getById(cmd.getApplyId());
|
||||||
return Objects.nonNull(cpApply) ? cpApply.getStatus() : null;
|
if (Objects.isNull(cpApply)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isOverdueWait(cpApply)) {
|
||||||
|
cpApplyService.expireWaitById(cpApply.getId());
|
||||||
|
return CpApplyStatus.EXPIRE.name();
|
||||||
|
}
|
||||||
|
return cpApply.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOverdueWait(CpApply cpApply) {
|
||||||
|
return Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())
|
||||||
|
&& Objects.nonNull(cpApply.getCreateTime())
|
||||||
|
&& cpApply.getCreateTime().toLocalDateTime()
|
||||||
|
.isBefore(LocalDateTime.now().minusHours(APPLY_WAIT_EXPIRE_HOURS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import com.red.circle.tool.core.json.JacksonUtils;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public final class CpRelationC2cNoticeUtils {
|
public final class CpRelationC2cNoticeUtils {
|
||||||
@ -36,9 +37,17 @@ public final class CpRelationC2cNoticeUtils {
|
|||||||
content.put("applyType", isReconcile ? "RECONCILE" : "APPLY");
|
content.put("applyType", isReconcile ? "RECONCILE" : "APPLY");
|
||||||
content.put("relationType", relationType.name());
|
content.put("relationType", relationType.name());
|
||||||
putAcceptProfile(content, acceptProfile);
|
putAcceptProfile(content, acceptProfile);
|
||||||
|
long createTimeSeconds = System.currentTimeMillis() / 1000;
|
||||||
|
long expireTimeSeconds = createTimeSeconds + TimeUnit.DAYS.toSeconds(1);
|
||||||
|
content.put("createTime", createTimeSeconds);
|
||||||
|
content.put("sendTime", createTimeSeconds);
|
||||||
|
content.put("dismissEndTime", expireTimeSeconds);
|
||||||
|
|
||||||
Map<String, Object> payload = basePayload(applyId, relationType.name(), title,
|
Map<String, Object> payload = basePayload(applyId, relationType.name(), title,
|
||||||
ACTION_INVITE_PENDING, "PENDING", content);
|
ACTION_INVITE_PENDING, "PENDING", content);
|
||||||
|
payload.put("createTime", createTimeSeconds);
|
||||||
|
payload.put("sendTime", createTimeSeconds);
|
||||||
|
payload.put("dismissEndTime", expireTimeSeconds);
|
||||||
putSenderProfile(payload, senderProfile);
|
putSenderProfile(payload, senderProfile);
|
||||||
putAcceptProfile(payload, acceptProfile);
|
putAcceptProfile(payload, acceptProfile);
|
||||||
return buildMessage(fromUserId, toUserId, payload);
|
return buildMessage(fromUserId, toUserId, payload);
|
||||||
|
|||||||
@ -56,12 +56,15 @@ public class CpApplyListener implements MessageListener {
|
|||||||
// 等待超时
|
// 等待超时
|
||||||
if (Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())) {
|
if (Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())) {
|
||||||
expire(cpApply);
|
expire(cpApply);
|
||||||
|
} else {
|
||||||
|
log.info("[CP] skip expire cp apply, applyId={}, status={}", cpApply.getId(),
|
||||||
|
cpApply.getStatus());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expire(CpApply cpApply) {
|
private void expire(CpApply cpApply) {
|
||||||
boolean changed = cpApplyService.changeStatusById(cpApply.getId(), CpApplyStatus.EXPIRE);
|
boolean changed = cpApplyService.expireWaitById(cpApply.getId());
|
||||||
if (changed) {
|
if (changed) {
|
||||||
sendExpiredNotice(cpApply);
|
sendExpiredNotice(cpApply);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
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.when;
|
||||||
|
|
||||||
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyIdQueryCmd;
|
||||||
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class CpApplyIdQryExeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReturnApplyIdSentByCurrentUser() {
|
||||||
|
CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
when(cpApplyService.getId(2001L, 1001L, "BROTHER")).thenReturn(3001L);
|
||||||
|
|
||||||
|
CpApplyIdQryExe exe = new CpApplyIdQryExe(cpApplyService);
|
||||||
|
|
||||||
|
assertEquals("3001", exe.execute(cmd(1001L, 2001L, "BROTHER")));
|
||||||
|
verify(cpApplyService).expireOverdueWaitApplies(1001L);
|
||||||
|
verify(cpApplyService).expireOverdueWaitApplies(2001L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFallbackToApplyIdReceivedByCurrentUser() {
|
||||||
|
CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
when(cpApplyService.getId(1001L, 2001L, "CP")).thenReturn(3002L);
|
||||||
|
|
||||||
|
CpApplyIdQryExe exe = new CpApplyIdQryExe(cpApplyService);
|
||||||
|
|
||||||
|
assertEquals("3002", exe.execute(cmd(1001L, 2001L, "CP")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CpApplyIdQueryCmd cmd(Long reqUserId, Long targetUserId, String relationType) {
|
||||||
|
CpApplyIdQueryCmd cmd = new CpApplyIdQueryCmd();
|
||||||
|
cmd.setReqUserId(reqUserId);
|
||||||
|
cmd.setUserId(targetUserId);
|
||||||
|
cmd.setRelationType(relationType);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,11 +3,14 @@ package com.red.circle.other.app.command.user.query;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyStatusQueryCmd;
|
import com.red.circle.other.app.dto.cmd.user.relation.cp.CpApplyStatusQueryCmd;
|
||||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class CpApplyStatusQryExeTest {
|
class CpApplyStatusQryExeTest {
|
||||||
@ -30,6 +33,21 @@ class CpApplyStatusQryExeTest {
|
|||||||
assertNull(exe.execute(cmd(3001L)));
|
assertNull(exe.execute(cmd(3001L)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldExpireOverdueWaitApplyWhenQueryingStatus() {
|
||||||
|
CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
CpApply cpApply = new CpApply()
|
||||||
|
.setId(3001L)
|
||||||
|
.setStatus("WAIT");
|
||||||
|
cpApply.setCreateTime(Timestamp.valueOf(LocalDateTime.now().minusHours(25)));
|
||||||
|
when(cpApplyService.getById(3001L)).thenReturn(cpApply);
|
||||||
|
|
||||||
|
CpApplyStatusQryExe exe = new CpApplyStatusQryExe(cpApplyService);
|
||||||
|
|
||||||
|
assertEquals("EXPIRE", exe.execute(cmd(3001L)));
|
||||||
|
verify(cpApplyService).expireWaitById(3001L);
|
||||||
|
}
|
||||||
|
|
||||||
private static CpApplyStatusQueryCmd cmd(Long applyId) {
|
private static CpApplyStatusQueryCmd cmd(Long applyId) {
|
||||||
CpApplyStatusQueryCmd cmd = new CpApplyStatusQueryCmd();
|
CpApplyStatusQueryCmd cmd = new CpApplyStatusQueryCmd();
|
||||||
cmd.setApplyId(applyId);
|
cmd.setApplyId(applyId);
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
@ -45,7 +47,7 @@ class CpApplyListenerTest {
|
|||||||
.setStatus(CpApplyStatus.WAIT.name());
|
.setStatus(CpApplyStatus.WAIT.name());
|
||||||
|
|
||||||
when(cpApplyService.getById(3001L)).thenReturn(apply);
|
when(cpApplyService.getById(3001L)).thenReturn(apply);
|
||||||
when(cpApplyService.changeStatusById(3001L, CpApplyStatus.EXPIRE)).thenReturn(true);
|
when(cpApplyService.expireWaitById(3001L)).thenReturn(true);
|
||||||
when(userProfileGateway.getByUserId(1001L)).thenReturn(profile(1001L));
|
when(userProfileGateway.getByUserId(1001L)).thenReturn(profile(1001L));
|
||||||
when(userProfileGateway.getByUserId(2001L)).thenReturn(profile(2001L));
|
when(userProfileGateway.getByUserId(2001L)).thenReturn(profile(2001L));
|
||||||
when(imMessageClient.sendCustomMessage(any(CustomC2cMsgBodyCmd.class)))
|
when(imMessageClient.sendCustomMessage(any(CustomC2cMsgBodyCmd.class)))
|
||||||
@ -68,12 +70,41 @@ class CpApplyListenerTest {
|
|||||||
ArgumentCaptor<CustomC2cMsgBodyCmd> captor = ArgumentCaptor.forClass(
|
ArgumentCaptor<CustomC2cMsgBodyCmd> captor = ArgumentCaptor.forClass(
|
||||||
CustomC2cMsgBodyCmd.class);
|
CustomC2cMsgBodyCmd.class);
|
||||||
InOrder inOrder = inOrder(cpApplyService, imMessageClient);
|
InOrder inOrder = inOrder(cpApplyService, imMessageClient);
|
||||||
inOrder.verify(cpApplyService).changeStatusById(3001L, CpApplyStatus.EXPIRE);
|
inOrder.verify(cpApplyService).expireWaitById(3001L);
|
||||||
inOrder.verify(imMessageClient).sendCustomMessage(captor.capture());
|
inOrder.verify(imMessageClient).sendCustomMessage(captor.capture());
|
||||||
List<CustomC2cMsgBodyCmd> messages = captor.getAllValues();
|
List<CustomC2cMsgBodyCmd> messages = captor.getAllValues();
|
||||||
assertExpiredMessage(messages.get(0), "1001", "2001");
|
assertExpiredMessage(messages.get(0), "1001", "2001");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nonWaitApplyShouldNotExpireAgain() {
|
||||||
|
CpApplyService cpApplyService = mock(CpApplyService.class);
|
||||||
|
ImMessageClient imMessageClient = mock(ImMessageClient.class);
|
||||||
|
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||||
|
MessageEventProcess messageEventProcess = mock(MessageEventProcess.class);
|
||||||
|
CpApply apply = new CpApply()
|
||||||
|
.setId(3001L)
|
||||||
|
.setStatus(CpApplyStatus.EXPIRE.name());
|
||||||
|
|
||||||
|
when(cpApplyService.getById(3001L)).thenReturn(apply);
|
||||||
|
when(messageEventProcess.consume(any(MessageEventProcessDescribe.class),
|
||||||
|
eq(CpApplyEvent.class), any())).thenAnswer(invocation -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Consumer<CpApplyEvent> consumer = invocation.getArgument(2, Consumer.class);
|
||||||
|
consumer.accept(new CpApplyEvent()
|
||||||
|
.setId(3001L)
|
||||||
|
.setSysOrigin(SysOriginPlatformEnum.LIKEI));
|
||||||
|
return Action.SUCCESS;
|
||||||
|
});
|
||||||
|
|
||||||
|
CpApplyListener listener = new CpApplyListener(cpApplyService, imMessageClient,
|
||||||
|
userProfileGateway, messageEventProcess);
|
||||||
|
|
||||||
|
assertEquals(Action.SUCCESS, listener.consume(new ConsumerMessage()));
|
||||||
|
verify(cpApplyService, never()).expireWaitById(3001L);
|
||||||
|
verify(imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static void assertExpiredMessage(CustomC2cMsgBodyCmd message, String fromAccount,
|
private static void assertExpiredMessage(CustomC2cMsgBodyCmd message, String fromAccount,
|
||||||
String toAccount) {
|
String toAccount) {
|
||||||
|
|||||||
@ -76,7 +76,17 @@ public interface CpApplyService extends BaseService<CpApply> {
|
|||||||
* @param status 状态
|
* @param status 状态
|
||||||
* @return true 成功,false 失败
|
* @return true 成功,false 失败
|
||||||
*/
|
*/
|
||||||
boolean changeStatusById(Long id, CpApplyStatus status);
|
boolean changeStatusById(Long id, CpApplyStatus status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只把等待中的申请置为超时.
|
||||||
|
*/
|
||||||
|
boolean expireWaitById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理用户相关超过 24 小时仍处于等待状态的申请.
|
||||||
|
*/
|
||||||
|
void expireOverdueWaitApplies(Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拒绝所有等待状态在用户.
|
* 拒绝所有等待状态在用户.
|
||||||
|
|||||||
@ -10,9 +10,10 @@ import com.red.circle.other.infra.database.rds.entity.user.user.CpApply;
|
|||||||
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
import com.red.circle.other.infra.enums.user.user.CpApplyStatus;
|
||||||
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
|
||||||
import com.red.circle.other.inner.model.cmd.user.CpApplyQryCmd;
|
import com.red.circle.other.inner.model.cmd.user.CpApplyQryCmd;
|
||||||
import java.time.LocalDateTime;
|
import java.sql.Timestamp;
|
||||||
import java.util.List;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -26,9 +27,11 @@ import org.springframework.stereotype.Service;
|
|||||||
* @since 2021-07-13
|
* @since 2021-07-13
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> implements
|
public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> implements
|
||||||
CpApplyService {
|
CpApplyService {
|
||||||
|
|
||||||
|
private static final long APPLY_WAIT_EXPIRE_HOURS = 24L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dismiss(Long requestUserId) {
|
public void dismiss(Long requestUserId) {
|
||||||
dismiss(requestUserId, CpRelationshipType.CP.name());
|
dismiss(requestUserId, CpRelationshipType.CP.name());
|
||||||
@ -62,10 +65,12 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
|
|||||||
.eq(CpApply::getRelationType, CpRelationshipType.normalize(relationType))
|
.eq(CpApply::getRelationType, CpRelationshipType.normalize(relationType))
|
||||||
.eq(CpApply::getAcceptApplyUserId, acceptApplyUserId)
|
.eq(CpApply::getAcceptApplyUserId, acceptApplyUserId)
|
||||||
.eq(CpApply::getSendApplyUserId, sendApplyUserId)
|
.eq(CpApply::getSendApplyUserId, sendApplyUserId)
|
||||||
.last(PageConstant.LIMIT_ONE)
|
.gt(CpApply::getCreateTime, waitExpireBefore())
|
||||||
.getOne()
|
.orderByDesc(CpApply::getCreateTime)
|
||||||
).map(CpApply::getId).orElse(null);
|
.last(PageConstant.LIMIT_ONE)
|
||||||
}
|
.getOne()
|
||||||
|
).map(CpApply::getId).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exists(Long acceptApplyUserId, Long sendApplyUserId) {
|
public boolean exists(Long acceptApplyUserId, Long sendApplyUserId) {
|
||||||
@ -89,6 +94,7 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
|
|||||||
.eq(CpApply::getSendApplyUserId, sendApplyUserId)
|
.eq(CpApply::getSendApplyUserId, sendApplyUserId)
|
||||||
.eq(CpApply::getRelationType, CpRelationshipType.normalize(relationType))
|
.eq(CpApply::getRelationType, CpRelationshipType.normalize(relationType))
|
||||||
.eq(CpApply::getStatus, CpApplyStatus.WAIT.name())
|
.eq(CpApply::getStatus, CpApplyStatus.WAIT.name())
|
||||||
|
.gt(CpApply::getCreateTime, waitExpireBefore())
|
||||||
.getOne())
|
.getOne())
|
||||||
.map(cpApply -> Objects.nonNull(cpApply.getId()))
|
.map(cpApply -> Objects.nonNull(cpApply.getId()))
|
||||||
.orElse(Boolean.FALSE);
|
.orElse(Boolean.FALSE);
|
||||||
@ -98,9 +104,39 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
|
|||||||
public boolean changeStatusById(Long id, CpApplyStatus status) {
|
public boolean changeStatusById(Long id, CpApplyStatus status) {
|
||||||
return update()
|
return update()
|
||||||
.set(CpApply::getStatus, status.name())
|
.set(CpApply::getStatus, status.name())
|
||||||
|
.set(CpApply::getUpdateTime, LocalDateTime.now())
|
||||||
.eq(CpApply::getId, id)
|
.eq(CpApply::getId, id)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean expireWaitById(Long id) {
|
||||||
|
return update()
|
||||||
|
.set(CpApply::getStatus, CpApplyStatus.EXPIRE.name())
|
||||||
|
.set(CpApply::getUpdateTime, LocalDateTime.now())
|
||||||
|
.eq(CpApply::getId, id)
|
||||||
|
.eq(CpApply::getStatus, CpApplyStatus.WAIT.name())
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expireOverdueWaitApplies(Long userId) {
|
||||||
|
if (Objects.isNull(userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update()
|
||||||
|
.set(CpApply::getStatus, CpApplyStatus.EXPIRE.name())
|
||||||
|
.set(CpApply::getUpdateTime, LocalDateTime.now())
|
||||||
|
.eq(CpApply::getStatus, CpApplyStatus.WAIT.name())
|
||||||
|
.lt(CpApply::getCreateTime, waitExpireBefore())
|
||||||
|
.and(where -> where.eq(CpApply::getSendApplyUserId, userId)
|
||||||
|
.or().eq(CpApply::getAcceptApplyUserId, userId))
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamp waitExpireBefore() {
|
||||||
|
return Timestamp.valueOf(LocalDateTime.now().minusHours(APPLY_WAIT_EXPIRE_HOURS));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refuseStatusWait(Long acceptApplyUserId) {
|
public void refuseStatusWait(Long acceptApplyUserId) {
|
||||||
|
|||||||
@ -134,7 +134,8 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
billBelong, row.getSysOrigin());
|
billBelong, row.getSysOrigin());
|
||||||
|
|
||||||
for (PolicyPayment policyPayment : row.getPayments()) {
|
for (PolicyPayment policyPayment : row.getPayments()) {
|
||||||
if (Boolean.TRUE.equals(teamSalaryPaymentService.checkRepeatPayment(payment.getId(),
|
if (policyPayment.getSalary().compareTo(BigDecimal.ZERO) <= 0
|
||||||
|
&& Boolean.TRUE.equals(teamSalaryPaymentService.checkRepeatPayment(payment.getId(),
|
||||||
row.getUserId(), row.getRegion(), policyPayment.getLevel(),
|
row.getUserId(), row.getRegion(), policyPayment.getLevel(),
|
||||||
policyPayment.getAnchor()))) {
|
policyPayment.getAnchor()))) {
|
||||||
continue;
|
continue;
|
||||||
@ -501,32 +502,32 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.setScale(2, RoundingMode.DOWN);
|
.setScale(2, RoundingMode.DOWN);
|
||||||
BigDecimal agentMissing = agentExpected.subtract(paymentSummary.getAgentIssuedSalary())
|
BigDecimal agentMissing = agentExpected.subtract(paymentSummary.getAgentIssuedSalary())
|
||||||
.setScale(2, RoundingMode.DOWN);
|
.setScale(2, RoundingMode.DOWN);
|
||||||
boolean memberSettled = isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(),
|
boolean memberHasSettlementRecord = hasPaidPolicy(cyclePayments, userId, region,
|
||||||
Boolean.TRUE, memberExpected);
|
billTarget.getLevel(), Boolean.TRUE);
|
||||||
boolean agentSettled = isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(),
|
boolean agentHasSettlementRecord = hasPaidPolicy(cyclePayments, userId, region,
|
||||||
Boolean.FALSE, agentExpected);
|
billTarget.getLevel(), Boolean.FALSE);
|
||||||
|
|
||||||
List<PolicyPayment> payments = new ArrayList<>();
|
List<PolicyPayment> payments = new ArrayList<>();
|
||||||
if (remainingPayable.compareTo(BigDecimal.ZERO) <= 0) {
|
if (remainingPayable.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
if (!memberSettled && memberExpected.compareTo(BigDecimal.ZERO) > 0) {
|
if (!memberHasSettlementRecord && memberExpected.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
|
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
|
||||||
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.TRUE));
|
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.TRUE));
|
||||||
}
|
}
|
||||||
if (!agentSettled && agentExpected.compareTo(BigDecimal.ZERO) > 0) {
|
if (!agentHasSettlementRecord && agentExpected.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
|
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
|
||||||
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.FALSE));
|
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.FALSE));
|
||||||
}
|
}
|
||||||
return payments;
|
return payments;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memberSettled && memberMissing.compareTo(BigDecimal.ZERO) > 0) {
|
if (memberMissing.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
BigDecimal issueSalary = memberMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
|
BigDecimal issueSalary = memberMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
|
||||||
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
|
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
payments.add(new PolicyPayment(policy, billTarget.getLevel(), issueSalary, Boolean.TRUE));
|
payments.add(new PolicyPayment(policy, billTarget.getLevel(), issueSalary, Boolean.TRUE));
|
||||||
remainingPayable = remainingPayable.subtract(issueSalary).setScale(2, RoundingMode.DOWN);
|
remainingPayable = remainingPayable.subtract(issueSalary).setScale(2, RoundingMode.DOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!agentSettled && agentMissing.compareTo(BigDecimal.ZERO) > 0
|
if (agentMissing.compareTo(BigDecimal.ZERO) > 0
|
||||||
&& remainingPayable.compareTo(BigDecimal.ZERO) > 0) {
|
&& remainingPayable.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
BigDecimal issueSalary = agentMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
|
BigDecimal issueSalary = agentMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
|
||||||
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
|
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
package com.red.circle.other.app.inner.service.team.impl;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillMemberTarget;
|
||||||
|
import com.red.circle.other.infra.database.mongo.dto.team.TeamSalaryPaymentDetails;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamSalaryPayment;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
|
class TeamManualSalaryPaymentClientServiceImplTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void buildSettlementPaymentsShouldTopUpWhenCurrentLevelRecordExistsButSalaryIsInsufficient()
|
||||||
|
throws Exception {
|
||||||
|
TeamManualSalaryPaymentClientServiceImpl service =
|
||||||
|
new TeamManualSalaryPaymentClientServiceImpl(
|
||||||
|
null, null, null, null, null, null, null, null);
|
||||||
|
Long userId = 2054591808909930498L;
|
||||||
|
String region = "2046067717605224449";
|
||||||
|
|
||||||
|
TeamBillMemberTarget billTarget = new TeamBillMemberTarget()
|
||||||
|
.setLevel(6)
|
||||||
|
.setMemberSalary(new BigDecimal("35.00"))
|
||||||
|
.setOwnSalary(new BigDecimal("8.75"));
|
||||||
|
TeamSalaryPayment currentPayment = new TeamSalaryPayment()
|
||||||
|
.setSalarySendDetails(List.of(new TeamSalaryPaymentDetails()
|
||||||
|
.setTeamMemberId(userId)
|
||||||
|
.setTeamRegionId(region)
|
||||||
|
.setPolicyLevel(6)
|
||||||
|
.setAnchor(Boolean.TRUE)
|
||||||
|
.setSalary(new BigDecimal("3.00"))
|
||||||
|
.setRecycled(Boolean.FALSE)));
|
||||||
|
|
||||||
|
Object paymentSummary = paymentSummary(
|
||||||
|
new BigDecimal("31.50"),
|
||||||
|
new BigDecimal("22.00"),
|
||||||
|
new BigDecimal("9.50"));
|
||||||
|
|
||||||
|
List<?> payments = ReflectionTestUtils.invokeMethod(service, "buildSettlementPayments",
|
||||||
|
null, billTarget, List.of(currentPayment), userId, region, paymentSummary,
|
||||||
|
new BigDecimal("12.25"), false);
|
||||||
|
|
||||||
|
assertEquals(1, payments.size());
|
||||||
|
Object payment = payments.get(0);
|
||||||
|
assertEquals(6, ReflectionTestUtils.getField(payment, "level"));
|
||||||
|
assertEquals(Boolean.TRUE, ReflectionTestUtils.getField(payment, "anchor"));
|
||||||
|
assertEquals(new BigDecimal("12.25"), ReflectionTestUtils.getField(payment, "salary"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void buildSettlementPaymentsShouldSettleZeroWhenPayableSalaryIsNegative() throws Exception {
|
||||||
|
TeamManualSalaryPaymentClientServiceImpl service =
|
||||||
|
new TeamManualSalaryPaymentClientServiceImpl(
|
||||||
|
null, null, null, null, null, null, null, null);
|
||||||
|
Long userId = 1008071L;
|
||||||
|
String region = "2046067717605224449";
|
||||||
|
|
||||||
|
TeamBillMemberTarget billTarget = new TeamBillMemberTarget()
|
||||||
|
.setLevel(6)
|
||||||
|
.setMemberSalary(new BigDecimal("35.00"))
|
||||||
|
.setOwnSalary(new BigDecimal("8.75"));
|
||||||
|
Object paymentSummary = paymentSummary(
|
||||||
|
new BigDecimal("45.00"),
|
||||||
|
new BigDecimal("36.00"),
|
||||||
|
new BigDecimal("9.00"));
|
||||||
|
|
||||||
|
List<?> payments = ReflectionTestUtils.invokeMethod(service, "buildSettlementPayments",
|
||||||
|
null, billTarget, List.of(), userId, region, paymentSummary,
|
||||||
|
new BigDecimal("-1.25"), false);
|
||||||
|
|
||||||
|
assertEquals(2, payments.size());
|
||||||
|
assertEquals(BigDecimal.ZERO.setScale(2), ReflectionTestUtils.getField(payments.get(0),
|
||||||
|
"salary"));
|
||||||
|
assertEquals(BigDecimal.ZERO.setScale(2), ReflectionTestUtils.getField(payments.get(1),
|
||||||
|
"salary"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object paymentSummary(BigDecimal totalIssuedSalary, BigDecimal memberIssuedSalary,
|
||||||
|
BigDecimal agentIssuedSalary) throws Exception {
|
||||||
|
Class<?> summaryClass = Class.forName(
|
||||||
|
"com.red.circle.other.app.inner.service.team.impl."
|
||||||
|
+ "TeamManualSalaryPaymentClientServiceImpl$PaymentSummary");
|
||||||
|
Constructor<?> constructor = summaryClass.getDeclaredConstructor(
|
||||||
|
BigDecimal.class,
|
||||||
|
BigDecimal.class,
|
||||||
|
BigDecimal.class,
|
||||||
|
BigDecimal.class,
|
||||||
|
BigDecimal.class,
|
||||||
|
BigDecimal.class);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return constructor.newInstance(
|
||||||
|
totalIssuedSalary,
|
||||||
|
memberIssuedSalary,
|
||||||
|
agentIssuedSalary,
|
||||||
|
BigDecimal.ZERO.setScale(2),
|
||||||
|
BigDecimal.ZERO.setScale(2),
|
||||||
|
BigDecimal.ZERO.setScale(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user