|
@@ -23,7 +23,9 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import shop.alien.config.properties.RiskControlProperties;
|
|
import shop.alien.config.properties.RiskControlProperties;
|
|
|
import shop.alien.entity.second.LifeUserLog;
|
|
import shop.alien.entity.second.LifeUserLog;
|
|
|
|
|
+import shop.alien.entity.second.SecondGoods;
|
|
|
import shop.alien.entity.second.SecondRiskControlRecord;
|
|
import shop.alien.entity.second.SecondRiskControlRecord;
|
|
|
|
|
+import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
|
|
|
import shop.alien.entity.store.*;
|
|
import shop.alien.entity.store.*;
|
|
|
import shop.alien.entity.store.dto.LifeFansFollowOutcome;
|
|
import shop.alien.entity.store.dto.LifeFansFollowOutcome;
|
|
|
import shop.alien.entity.store.vo.LifeMessageVo;
|
|
import shop.alien.entity.store.vo.LifeMessageVo;
|
|
@@ -31,8 +33,10 @@ import shop.alien.entity.store.vo.LifeUserVo;
|
|
|
import shop.alien.entity.store.vo.WebSocketVo;
|
|
import shop.alien.entity.store.vo.WebSocketVo;
|
|
|
import shop.alien.mapper.*;
|
|
import shop.alien.mapper.*;
|
|
|
import shop.alien.mapper.second.LifeUserLogMapper;
|
|
import shop.alien.mapper.second.LifeUserLogMapper;
|
|
|
|
|
+import shop.alien.mapper.second.SecondGoodsMapper;
|
|
|
import shop.alien.mapper.second.SecondRiskControlRecordMapper;
|
|
import shop.alien.mapper.second.SecondRiskControlRecordMapper;
|
|
|
import shop.alien.mapper.second.SecondUserCreditMapper;
|
|
import shop.alien.mapper.second.SecondUserCreditMapper;
|
|
|
|
|
+import shop.alien.util.common.constant.LawyerStatusEnum;
|
|
|
import shop.alien.store.config.BaseRedisService;
|
|
import shop.alien.store.config.BaseRedisService;
|
|
|
import shop.alien.store.config.WebSocketProcess;
|
|
import shop.alien.store.config.WebSocketProcess;
|
|
|
import shop.alien.store.feign.SecondServiceFeign;
|
|
import shop.alien.store.feign.SecondServiceFeign;
|
|
@@ -71,6 +75,28 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
|
|
|
private static final Pattern LIFE_FANS_PAIR_ID_PATTERN = Pattern.compile("^(store|user)_[^\\s]{1,120}$");
|
|
private static final Pattern LIFE_FANS_PAIR_ID_PATTERN = Pattern.compile("^(store|user)_[^\\s]{1,120}$");
|
|
|
private static final int FAN_IDS_MAX_CHARS = 160;
|
|
private static final int FAN_IDS_MAX_CHARS = 160;
|
|
|
|
|
|
|
|
|
|
+ /** 商家预订:待支付 / 待使用 / 商家预订 */
|
|
|
|
|
+ private static final List<Integer> PENDING_RESERVATION_ORDER_STATUSES =
|
|
|
|
|
+ Arrays.asList(0, 1, 8);
|
|
|
|
|
+
|
|
|
|
|
+ private static final String CANCEL_MSG_PENDING_RESERVATION =
|
|
|
|
|
+ "您有待消费的商家预订,请完成消费或取消预订后再申请注销。";
|
|
|
|
|
+ private static final String CANCEL_MSG_LISTED_SECOND_GOODS =
|
|
|
|
|
+ "您有上架的二手商品,请确认下架后再申请注销。";
|
|
|
|
|
+ private static final String CANCEL_MSG_CONSULT_IN_PROGRESS =
|
|
|
|
|
+ "您有进行中的法律咨询,请与律师确认服务完结后再申请注销。";
|
|
|
|
|
+ private static final String CANCEL_MSG_UNPAID_CONSULT_FEE =
|
|
|
|
|
+ "您有未结清的咨询费用,请完成支付后再申请注销。";
|
|
|
|
|
+ private static final String CANCEL_MSG_MULTIPLE_BLOCKERS =
|
|
|
|
|
+ "您有多项待办事项未处理,处理完成后即可申请注销。";
|
|
|
|
|
+ private static final String CANCEL_REVOKE_NOT_IN_COOLING_MSG =
|
|
|
|
|
+ "当前账号不在注销冷静期内,无法撤销";
|
|
|
|
|
+
|
|
|
|
|
+ /** C 端用户注销冷静期:logout_flag=2 */
|
|
|
|
|
+ private static final int LIFE_USER_LOGOUT_FLAG_COOLING = 2;
|
|
|
|
|
+
|
|
|
|
|
+ private static final int LOGOUT_COOLING_DAYS = 7;
|
|
|
|
|
+
|
|
|
private final LifeUserMapper lifeUserMapper;
|
|
private final LifeUserMapper lifeUserMapper;
|
|
|
|
|
|
|
|
private final LifeFansMapper lifeFansMapper;
|
|
private final LifeFansMapper lifeFansMapper;
|
|
@@ -115,6 +141,12 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
|
|
|
|
|
|
|
|
private final TypeUtil typeUtil;
|
|
private final TypeUtil typeUtil;
|
|
|
|
|
|
|
|
|
|
+ private final UserReservationOrderMapper userReservationOrderMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final SecondGoodsMapper secondGoodsMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private final LawyerConsultationOrderMapper lawyerConsultationOrderMapper;
|
|
|
|
|
+
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private RiskControlProperties riskControlProperties;
|
|
private RiskControlProperties riskControlProperties;
|
|
|
|
|
|
|
@@ -519,28 +551,102 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
|
|
|
if (lifeUser == null) {
|
|
if (lifeUser == null) {
|
|
|
throw new IllegalArgumentException("用户不存在");
|
|
throw new IllegalArgumentException("用户不存在");
|
|
|
}
|
|
}
|
|
|
- if (lifeUser.getLogoutFlag() != null && lifeUser.getLogoutFlag() == 1) {
|
|
|
|
|
|
|
+ if (lifeUser.getLogoutFlag() != null && lifeUser.getLogoutFlag() == 2) {
|
|
|
throw new IllegalArgumentException("账号已在注销中");
|
|
throw new IllegalArgumentException("账号已在注销中");
|
|
|
}
|
|
}
|
|
|
- lifeUser.setLogoutFlag(1);
|
|
|
|
|
|
|
+ validateCancelAccountBlockers(user.getId());
|
|
|
|
|
+ // 设置成2,注销冷静期
|
|
|
|
|
+ lifeUser.setLogoutFlag(2);
|
|
|
lifeUser.setLogoutReason(user.getLogoutReason());
|
|
lifeUser.setLogoutReason(user.getLogoutReason());
|
|
|
lifeUser.setLogoutTime(new Date());
|
|
lifeUser.setLogoutTime(new Date());
|
|
|
lifeUserMapper.updateById(lifeUser);
|
|
lifeUserMapper.updateById(lifeUser);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 注销前业务校验:商家预订、二手上架、咨询进行中、咨询费用未结清。
|
|
|
|
|
+ * 单项不满足返回对应提示;多项不满足返回汇总提示。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void validateCancelAccountBlockers(Integer userId) {
|
|
|
|
|
+ List<String> blockers = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ long pendingReservationCount = userReservationOrderMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<UserReservationOrder>()
|
|
|
|
|
+ .eq(UserReservationOrder::getUserId, userId)
|
|
|
|
|
+ .in(UserReservationOrder::getOrderStatus, PENDING_RESERVATION_ORDER_STATUSES));
|
|
|
|
|
+ if (pendingReservationCount > 0) {
|
|
|
|
|
+ blockers.add(CANCEL_MSG_PENDING_RESERVATION);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ long listedGoodsCount = secondGoodsMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<SecondGoods>()
|
|
|
|
|
+ .eq(SecondGoods::getUserId, userId)
|
|
|
|
|
+ .eq(SecondGoods::getGoodsStatus, SecondGoodsStatusEnum.LISTED.getCode()));
|
|
|
|
|
+ if (listedGoodsCount > 0) {
|
|
|
|
|
+ blockers.add(CANCEL_MSG_LISTED_SECOND_GOODS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ long inProgressConsultCount = lawyerConsultationOrderMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<LawyerConsultationOrder>()
|
|
|
|
|
+ .eq(LawyerConsultationOrder::getClientUserId, userId)
|
|
|
|
|
+ .in(LawyerConsultationOrder::getOrderStatus,
|
|
|
|
|
+ LawyerStatusEnum.WAIT_ACCEPT.getStatus(),
|
|
|
|
|
+ LawyerStatusEnum.INPROGRESS.getStatus()));
|
|
|
|
|
+ if (inProgressConsultCount > 0) {
|
|
|
|
|
+ blockers.add(CANCEL_MSG_CONSULT_IN_PROGRESS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ long unpaidConsultCount = lawyerConsultationOrderMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<LawyerConsultationOrder>()
|
|
|
|
|
+ .eq(LawyerConsultationOrder::getClientUserId, userId)
|
|
|
|
|
+ .eq(LawyerConsultationOrder::getPaymentStatus, 0)
|
|
|
|
|
+ .notIn(LawyerConsultationOrder::getOrderStatus,
|
|
|
|
|
+ LawyerStatusEnum.CANCEL.getStatus(),
|
|
|
|
|
+ LawyerStatusEnum.REFUNDED.getStatus(),LawyerStatusEnum.COMPLETE.getStatus()));
|
|
|
|
|
+ if (unpaidConsultCount > 0) {
|
|
|
|
|
+ blockers.add(CANCEL_MSG_UNPAID_CONSULT_FEE);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (blockers.isEmpty()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (blockers.size() == 1) {
|
|
|
|
|
+ throw new IllegalArgumentException(blockers.get(0));
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new IllegalArgumentException(CANCEL_MSG_MULTIPLE_BLOCKERS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public void liftCancelAccountUn(Integer id) {
|
|
public void liftCancelAccountUn(Integer id) {
|
|
|
- LambdaQueryWrapper<LifeUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
- lambdaQueryWrapper.eq(LifeUser::getId, id);
|
|
|
|
|
- LifeUser lifeUser = lifeUserMapper.selectOne(lambdaQueryWrapper);
|
|
|
|
|
- // 修改注销标记为0
|
|
|
|
|
|
|
+ if (id == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("用户id不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ LifeUser lifeUser = lifeUserMapper.selectById(id);
|
|
|
|
|
+ if (lifeUser == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("用户不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ boolean logoutFlagCooling = lifeUser.getLogoutFlag() != null
|
|
|
|
|
+ && lifeUser.getLogoutFlag() == LIFE_USER_LOGOUT_FLAG_COOLING;
|
|
|
|
|
+ if (!logoutFlagCooling && !isLifeUserInLogoutCoolingPeriod(lifeUser)) {
|
|
|
|
|
+ throw new IllegalArgumentException(CANCEL_REVOKE_NOT_IN_COOLING_MSG);
|
|
|
|
|
+ }
|
|
|
lifeUser.setLogoutFlag(0);
|
|
lifeUser.setLogoutFlag(0);
|
|
|
- // 清空注销原因
|
|
|
|
|
lifeUser.setLogoutReason(null);
|
|
lifeUser.setLogoutReason(null);
|
|
|
- // 清空注销申请时间
|
|
|
|
|
lifeUser.setLogoutTime(null);
|
|
lifeUser.setLogoutTime(null);
|
|
|
lifeUserMapper.updateById(lifeUser);
|
|
lifeUserMapper.updateById(lifeUser);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否在注销冷静期内(logoutTime 起 7 天内,含第 7 天当日)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private static boolean isLifeUserInLogoutCoolingPeriod(LifeUser lifeUser) {
|
|
|
|
|
+ if (lifeUser == null || lifeUser.getLogoutTime() == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
|
|
+ calendar.setTime(lifeUser.getLogoutTime());
|
|
|
|
|
+ calendar.add(Calendar.DAY_OF_YEAR, LOGOUT_COOLING_DAYS);
|
|
|
|
|
+ return !new Date().after(calendar.getTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public List<String> getIds(String name, String phone) {
|
|
public List<String> getIds(String name, String phone) {
|
|
|
if (Objects.isNull(name) && Objects.isNull(phone)) return Arrays.asList("");
|
|
if (Objects.isNull(name) && Objects.isNull(phone)) return Arrays.asList("");
|
|
|
LambdaQueryWrapper<LifeUser> wrapper = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<LifeUser> wrapper = new LambdaQueryWrapper<>();
|