修复送礼报错

This commit is contained in:
hy001 2026-05-25 17:07:13 +08:00
parent c2e28b5cb3
commit 6573219751
5 changed files with 42 additions and 20 deletions

View File

@ -19,6 +19,7 @@ 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.inner.asserts.user.UserRelationErrorCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
@ -40,6 +41,7 @@ public class ProcessCpApplyCmd {
private static final int CP_MAX_COUNT = 1;
private static final int FRIEND_MAX_COUNT = 3;
private static final long APPLY_WAIT_EXPIRE_HOURS = 24L;
private final CpApplyService cpApplyService;
private final CpValueService cpValueService;
@ -60,8 +62,9 @@ public class ProcessCpApplyCmd {
String relationType = CpRelationshipType.normalize(cpApply.getRelationType());
// 状态错误
ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR,
Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name()));
ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR,
Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name()));
ResponseAssert.isFalse(CommonErrorCode.STATE_ERROR, isOverdueWait(cpApply));
boolean agree = isAgree(cmd);
boolean isReconcile = false;
@ -114,6 +117,13 @@ public class ProcessCpApplyCmd {
sendProcessNotice(cpApply, true);
}
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));
}
private void sendProcessNotice(CpApply cpApply, boolean agree) {
try {
UserProfile senderProfile = userProfileGateway.getByUserId(cpApply.getSendApplyUserId());

View File

@ -26,7 +26,6 @@ public class CpApplyStatusQryExe {
return null;
}
if (isOverdueWait(cpApply)) {
cpApplyService.expireWaitById(cpApply.getId());
return CpApplyStatus.EXPIRE.name();
}
return cpApply.getStatus();

View File

@ -22,6 +22,8 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService;
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.CpApplyStatus;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
@ -84,6 +86,22 @@ class ProcessCpApplyCmdTest {
verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
}
@Test
void processOverdueWaitApplyShouldFailStateError() {
Fixture fixture = new Fixture("CP");
CpApply overdueApply = apply("CP");
overdueApply.setCreateTime(Timestamp.valueOf(LocalDateTime.now().minusHours(25)));
when(fixture.cpApplyService.getById(3001L)).thenReturn(overdueApply);
Assertions.assertThrows(RuntimeException.class, () -> fixture.exe.execute(processCmd(true)));
verify(fixture.cpApplyService, never()).changeStatusById(eq(3001L),
any(CpApplyStatus.class));
verify(fixture.cpRelationshipService, never()).addCp(any(Long.class), any(Long.class),
nullable(Long.class), any(String.class), any(String.class));
verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class));
}
@Test
void agreeApplyShouldAutoRefuseOtherWaitAppliesBetweenSameUsersWithoutRejectedIm() {
Fixture fixture = new Fixture("CP");

View File

@ -3,6 +3,7 @@ package com.red.circle.other.app.command.user.query;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -34,7 +35,7 @@ class CpApplyStatusQryExeTest {
}
@Test
void shouldExpireOverdueWaitApplyWhenQueryingStatus() {
void shouldReturnExpireForOverdueWaitApplyWithoutPersistingStatus() {
CpApplyService cpApplyService = mock(CpApplyService.class);
CpApply cpApply = new CpApply()
.setId(3001L)
@ -45,7 +46,7 @@ class CpApplyStatusQryExeTest {
CpApplyStatusQryExe exe = new CpApplyStatusQryExe(cpApplyService);
assertEquals("EXPIRE", exe.execute(cmd(3001L)));
verify(cpApplyService).expireWaitById(3001L);
verify(cpApplyService, never()).expireWaitById(3001L);
}
private static CpApplyStatusQueryCmd cmd(Long applyId) {

View File

@ -111,27 +111,21 @@ public class CpApplyServiceImpl extends BaseServiceImpl<CpApplyDAO, CpApply> imp
@Override
public boolean expireWaitById(Long id) {
return update()
.set(CpApply::getStatus, CpApplyStatus.EXPIRE.name())
.set(CpApply::getUpdateTime, LocalDateTime.now())
return Optional.ofNullable(query()
.select(CpApply::getId)
.eq(CpApply::getId, id)
.eq(CpApply::getStatus, CpApplyStatus.WAIT.name())
.execute();
.lt(CpApply::getCreateTime, waitExpireBefore())
.last(PageConstant.LIMIT_ONE)
.getOne())
.map(cpApply -> Objects.nonNull(cpApply.getId()))
.orElse(Boolean.FALSE);
}
@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();
// The production status column does not accept a persisted EXPIRE value.
// Expiration is derived from create_time so old WAIT rows do not block new applies.
}
private Timestamp waitExpireBefore() {