修复送礼报错

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

View File

@ -26,7 +26,6 @@ public class CpApplyStatusQryExe {
return null; return null;
} }
if (isOverdueWait(cpApply)) { if (isOverdueWait(cpApply)) {
cpApplyService.expireWaitById(cpApply.getId());
return CpApplyStatus.EXPIRE.name(); return CpApplyStatus.EXPIRE.name();
} }
return cpApply.getStatus(); 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.CpRelationshipService;
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
import com.red.circle.other.infra.enums.user.user.CpApplyStatus; 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.List;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
@ -84,6 +86,22 @@ class ProcessCpApplyCmdTest {
verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class)); 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 @Test
void agreeApplyShouldAutoRefuseOtherWaitAppliesBetweenSameUsersWithoutRejectedIm() { void agreeApplyShouldAutoRefuseOtherWaitAppliesBetweenSameUsersWithoutRejectedIm() {
Fixture fixture = new Fixture("CP"); 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.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.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -34,7 +35,7 @@ class CpApplyStatusQryExeTest {
} }
@Test @Test
void shouldExpireOverdueWaitApplyWhenQueryingStatus() { void shouldReturnExpireForOverdueWaitApplyWithoutPersistingStatus() {
CpApplyService cpApplyService = mock(CpApplyService.class); CpApplyService cpApplyService = mock(CpApplyService.class);
CpApply cpApply = new CpApply() CpApply cpApply = new CpApply()
.setId(3001L) .setId(3001L)
@ -45,7 +46,7 @@ class CpApplyStatusQryExeTest {
CpApplyStatusQryExe exe = new CpApplyStatusQryExe(cpApplyService); CpApplyStatusQryExe exe = new CpApplyStatusQryExe(cpApplyService);
assertEquals("EXPIRE", exe.execute(cmd(3001L))); assertEquals("EXPIRE", exe.execute(cmd(3001L)));
verify(cpApplyService).expireWaitById(3001L); verify(cpApplyService, never()).expireWaitById(3001L);
} }
private static CpApplyStatusQueryCmd cmd(Long applyId) { private static CpApplyStatusQueryCmd cmd(Long applyId) {

View File

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