|
|
@@ -1,26 +1,31 @@
|
|
|
package shop.alien.second.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.alibaba.nacos.common.utils.CollectionUtils;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import io.swagger.models.auth.In;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import shop.alien.config.properties.RiskControlProperties;
|
|
|
+import shop.alien.config.redis.BaseRedisService;
|
|
|
import shop.alien.entity.result.BusinessException;
|
|
|
import shop.alien.entity.second.*;
|
|
|
+import shop.alien.entity.second.vo.SecondEntrustUserDTO;
|
|
|
+import shop.alien.entity.store.*;
|
|
|
import shop.alien.mapper.second.SecondRiskControlRecordMapper;
|
|
|
import shop.alien.entity.second.vo.SecondTradeRecordVo;
|
|
|
-import shop.alien.entity.store.LifeMessage;
|
|
|
-import shop.alien.entity.store.LifeNotice;
|
|
|
-import shop.alien.entity.store.LifeUser;
|
|
|
-import shop.alien.entity.store.StoreDictionary;
|
|
|
+import shop.alien.entity.second.vo.SellerEvaluationVo;
|
|
|
import shop.alien.entity.store.vo.WebSocketVo;
|
|
|
import shop.alien.mapper.LifeMessageMapper;
|
|
|
import shop.alien.mapper.LifeNoticeMapper;
|
|
|
@@ -32,10 +37,7 @@ import shop.alien.second.service.SecondTradeRecordService;
|
|
|
import shop.alien.util.common.JwtUtil;
|
|
|
|
|
|
import java.time.*;
|
|
|
-import java.util.Comparator;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Objects;
|
|
|
+import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -63,14 +65,18 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
private final LifeUserMapper lifeUserMapper;
|
|
|
private final AlienStoreFeign alienStoreFeign;
|
|
|
private final StoreDictionaryMapper storeDictionaryMapper;
|
|
|
+ private final BaseRedisService baseRedisService;
|
|
|
@Autowired
|
|
|
private RiskControlProperties riskControlProperties;
|
|
|
|
|
|
+ // 委托人信息
|
|
|
+ private final SecondEntrustUserMapper secondEntrustUserMapper;
|
|
|
+
|
|
|
private final Object lock = new Object();
|
|
|
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public boolean createTrade(SecondTradeRecord trade) throws Exception {
|
|
|
+ public boolean createTrade(SecondEntrustUserDTO trade) throws Exception {
|
|
|
try {
|
|
|
synchronized (lock) {
|
|
|
LocalDate now = LocalDate.now();
|
|
|
@@ -107,6 +113,17 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
// 查询商品
|
|
|
goods = secondGoodsMapper.selectById(trade.getGoodsId());
|
|
|
|
|
|
+ if (StringUtils.isNotBlank(trade.getEntrustUserPhone()) && StringUtils.isNotBlank(trade.getEntrustUserName()) && StringUtils.isNotBlank(trade.getEntrustIdCard())) {
|
|
|
+ // 添加商家委托信息
|
|
|
+ SecondEntrustUser secondEntrustUser = new SecondEntrustUser();
|
|
|
+ secondEntrustUser.setEntrustTradeId(trade.getId());
|
|
|
+ secondEntrustUser.setEntrustUserPhone(trade.getEntrustUserPhone());
|
|
|
+ secondEntrustUser.setEntrustUserName(trade.getEntrustUserName());
|
|
|
+ secondEntrustUser.setEntrustIdCard(trade.getEntrustIdCard());
|
|
|
+ secondEntrustUser.setEntrustTradeNo(trade.getTradeNo());
|
|
|
+ secondEntrustUserMapper.insert(secondEntrustUser);
|
|
|
+ }
|
|
|
+
|
|
|
// 发送消息
|
|
|
sendMsg(goods, trade, 1, "4");
|
|
|
|
|
|
@@ -138,6 +155,18 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
message.put("transactionLocation", trade.getTransactionLocation());
|
|
|
message.put("transactionTime", trade.getTransactionTime());
|
|
|
message.put("tradeStatus", tradeStatus);
|
|
|
+
|
|
|
+ // 查询商家委托信息
|
|
|
+ LambdaQueryWrapper<SecondEntrustUser> entrustWrapper = new LambdaQueryWrapper<>();
|
|
|
+ entrustWrapper.eq(SecondEntrustUser::getEntrustTradeId, trade.getId());
|
|
|
+ SecondEntrustUser entrustUser = secondEntrustUserMapper.selectOne(entrustWrapper);
|
|
|
+ if ( entrustUser != null ) {
|
|
|
+ message.put("entrustId", entrustUser.getId());
|
|
|
+ message.put("entrustUserPhone", entrustUser.getEntrustUserPhone());
|
|
|
+ message.put("entrustUserName", entrustUser.getEntrustUserName());
|
|
|
+ message.put("entrustIdCard", entrustUser.getEntrustIdCard());
|
|
|
+ }
|
|
|
+
|
|
|
if (6 == tradeStatus) {
|
|
|
message.put("cancelUserId", trade.getCancelUserId());
|
|
|
message.put("cancelReason", trade.getCancelReason());
|
|
|
@@ -461,10 +490,13 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
if (userId == tradeRecord.getBuyerId()) {
|
|
|
recordVo.setUserTransactionStatus(tradeRecord.getBuyerTransactionStatus());
|
|
|
recordVo.setUserEvaluate(tradeRecord.getBuyerEvaluate());
|
|
|
+ recordVo.setUserRating(tradeRecord.getBuyerRating());
|
|
|
} else if (userId == tradeRecord.getSellerId()) {
|
|
|
recordVo.setUserTransactionStatus(tradeRecord.getSellerTransactionStatus());
|
|
|
recordVo.setUserEvaluate(tradeRecord.getSellerEvaluate());
|
|
|
+ recordVo.setUserRating(tradeRecord.getSellerRating());
|
|
|
}
|
|
|
+ recordVo.setSellerId(tradeRecord.getSellerId());
|
|
|
return recordVo;
|
|
|
} catch (Exception e) {
|
|
|
log.error("SecondTradeRecordServiceImpl.getUserTradeStatus(): Error Msg={}", e.getMessage());
|
|
|
@@ -474,7 +506,7 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public boolean tradeCompleteConfirm(int tradeId, int type, String evaluate) throws Exception {
|
|
|
+ public boolean tradeCompleteConfirm(int tradeId, int type, String evaluate, Integer rating) throws Exception {
|
|
|
try {
|
|
|
int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
|
|
|
SecondTradeRecord tradeRecord = secondTradeRecordMapper.selectById(tradeId);
|
|
|
@@ -484,12 +516,16 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
if (userId == tradeRecord.getBuyerId()) {
|
|
|
if (0 != tradeRecord.getBuyerTransactionStatus()) return false;
|
|
|
record.setBuyerTransactionStatus(type);
|
|
|
+ record.setBuyerCompleteTime(new Date());
|
|
|
record.setBuyerEvaluate(evaluate);
|
|
|
+ record.setBuyerRating(rating);
|
|
|
// 卖家
|
|
|
} else if (userId == tradeRecord.getSellerId()) {
|
|
|
if (0 != tradeRecord.getSellerTransactionStatus()) return false;
|
|
|
record.setSellerTransactionStatus(type);
|
|
|
+ record.setSellerCompleteTime(new Date());
|
|
|
record.setSellerEvaluate(evaluate);
|
|
|
+ record.setSellerRating(rating);
|
|
|
record.setTradeStatus(1 == type ? 4 : 5);
|
|
|
// 卖家如果选择交易成功 同步修改商品表
|
|
|
if (1 == type) {
|
|
|
@@ -552,7 +588,22 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
wrapper.eq("trade.delete_flag", 0);
|
|
|
wrapper.apply("((trade.buyer_id = '" + sideId + "' and trade.seller_id = '" + userId + "') || (trade.buyer_id = '" + userId + "' and trade.seller_id = '" + sideId + "'))");
|
|
|
wrapper.orderByDesc("trade.created_time");
|
|
|
- return secondTradeRecordMapper.getTradeRecord(wrapper);
|
|
|
+ List<SecondTradeRecordVo> vo = secondTradeRecordMapper.getTradeRecord(wrapper);
|
|
|
+ if (vo.size() > 0) {
|
|
|
+ for (SecondTradeRecordVo item : vo) {
|
|
|
+ // 查询商家委托信息
|
|
|
+ LambdaQueryWrapper<SecondEntrustUser> entrustWrapper = new LambdaQueryWrapper<>();
|
|
|
+ entrustWrapper.eq(SecondEntrustUser::getEntrustTradeId, item.getId());
|
|
|
+ SecondEntrustUser entrustUser = secondEntrustUserMapper.selectOne(entrustWrapper);
|
|
|
+ if ( entrustUser != null ) {
|
|
|
+ item.setEntrustId(entrustUser.getId());
|
|
|
+ item.setEntrustUserPhone(entrustUser.getEntrustUserPhone());
|
|
|
+ item.setEntrustUserName(entrustUser.getEntrustUserName());
|
|
|
+ item.setEntrustIdCard(entrustUser.getEntrustIdCard());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
} catch (Exception e) {
|
|
|
log.error("SecondTradeRecordServiceImpl.getTradeRecord(): Error Msg={}", e.getMessage());
|
|
|
throw new Exception(e);
|
|
|
@@ -583,7 +634,7 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
.orElse(null);
|
|
|
|
|
|
list = list.stream().filter(item -> item.getTransactionTime().equals(minDate)).collect(Collectors.toList());
|
|
|
- return list.isEmpty() ? null : list.get(0);
|
|
|
+ return list.isEmpty() ? null : (1 == list.get(0).getBuyerSignIn() && 1 == list.get(0).getSellerSignIn() ? null : list.get(0));
|
|
|
} catch (Exception e) {
|
|
|
log.error("SecondTradeRecordServiceImpl.hasInTradeRecord(): Error Msg={}", e.getMessage());
|
|
|
throw new Exception(e);
|
|
|
@@ -592,7 +643,8 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public boolean modifyTradeRecord(int type, Integer tradeId, String transactionTime, String transactionLatitudeLongitude, String transactionLatitudeLongitudeAddress, String transactionLocation, String messageId) throws Exception {
|
|
|
+ public boolean modifyTradeRecord(int type, Integer tradeId, String transactionTime, String transactionLatitudeLongitude, String transactionLatitudeLongitudeAddress, String transactionLocation, String messageId,
|
|
|
+ String userPhone, String userName, String idCard, Integer entrustId) throws Exception {
|
|
|
try {
|
|
|
if (type == 1) {
|
|
|
LambdaUpdateWrapper<SecondTradeRecord> wrapper = new LambdaUpdateWrapper<>();
|
|
|
@@ -600,6 +652,15 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
wrapper.set(SecondTradeRecord::getTransactionLatitudeLongitude, transactionLatitudeLongitude);
|
|
|
wrapper.set(SecondTradeRecord::getTransactionLatitudeLongitudeAddress, transactionLatitudeLongitudeAddress);
|
|
|
wrapper.set(SecondTradeRecord::getTransactionLocation, transactionLocation);
|
|
|
+ // 清空签到信息
|
|
|
+ wrapper.set(SecondTradeRecord::getBuyerSignIn, 0);
|
|
|
+ wrapper.set(SecondTradeRecord::getBuyerSignInTime, null);
|
|
|
+ wrapper.set(SecondTradeRecord::getBuyerSignInLatitudeLongitude, null);
|
|
|
+ wrapper.set(SecondTradeRecord::getBuyerSignInLatitudeLongitudeAddress, null);
|
|
|
+ wrapper.set(SecondTradeRecord::getSellerSignIn, 0);
|
|
|
+ wrapper.set(SecondTradeRecord::getSellerSignInTime, null);
|
|
|
+ wrapper.set(SecondTradeRecord::getSellerSignInLatitudeLongitude, null);
|
|
|
+ wrapper.set(SecondTradeRecord::getSellerSignInLatitudeLongitudeAddress, null);
|
|
|
wrapper.eq(SecondTradeRecord::getId, tradeId);
|
|
|
secondTradeRecordMapper.update(null, wrapper);
|
|
|
}
|
|
|
@@ -624,6 +685,35 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
|
|
|
String receiverId = "user_" + lifeUser.getUserPhone();
|
|
|
|
|
|
+ if (entrustId != null) {
|
|
|
+ LambdaUpdateWrapper<SecondEntrustUser> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ updateWrapper.eq(SecondEntrustUser::getId, entrustId);
|
|
|
+ if (StringUtils.isBlank(userPhone) && StringUtils.isBlank(userName) && StringUtils.isBlank(idCard)) {
|
|
|
+ updateWrapper.set(SecondEntrustUser::getDeleteFlag, 1);
|
|
|
+ } else {
|
|
|
+ updateWrapper.set(SecondEntrustUser::getEntrustTradeId, tradeId);
|
|
|
+ updateWrapper.set(SecondEntrustUser::getEntrustUserPhone, userPhone);
|
|
|
+ updateWrapper.set(SecondEntrustUser::getEntrustUserName, userName);
|
|
|
+ updateWrapper.set(SecondEntrustUser::getEntrustIdCard, idCard);
|
|
|
+ }
|
|
|
+ secondEntrustUserMapper.update(null, updateWrapper);
|
|
|
+ } else {
|
|
|
+ LambdaUpdateWrapper<SecondEntrustUser> wrapper = new LambdaUpdateWrapper<>();
|
|
|
+ wrapper.eq(SecondEntrustUser::getEntrustTradeId, tradeId);
|
|
|
+ Integer entrust = secondEntrustUserMapper.selectCount(wrapper);
|
|
|
+ if (entrust <= 0) {
|
|
|
+ if (StringUtils.isNotBlank(userPhone) && StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(idCard)) {
|
|
|
+ secondEntrustUserMapper.insert(new SecondEntrustUser()
|
|
|
+ .setEntrustTradeId(tradeId)
|
|
|
+ .setEntrustUserPhone(userPhone)
|
|
|
+ .setEntrustUserName(userName)
|
|
|
+ .setEntrustIdCard(idCard)
|
|
|
+ .setDeleteFlag(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
// 给买家与卖家发送交易消息
|
|
|
WebSocketVo webSocketVo = new WebSocketVo();
|
|
|
webSocketVo.setSenderId(phoneId);
|
|
|
@@ -636,6 +726,11 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
|
|
|
alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
|
|
|
alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());
|
|
|
+
|
|
|
+ // 交易时间小于十分钟,直接发送交易提醒
|
|
|
+ if (1 == type && Math.abs(Duration.between(Instant.now(), trade.getTransactionTime().toInstant()).getSeconds()) < 600) {
|
|
|
+ sendSignInMessage(trade);
|
|
|
+ }
|
|
|
return true;
|
|
|
} catch (Exception e) {
|
|
|
log.error("SecondTradeRecordServiceImpl.modifyTradeRecord(): Error Msg={}", e.getMessage());
|
|
|
@@ -760,4 +855,341 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
|
|
|
throw new Exception(e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户作为卖家的交易评价列表(分页)
|
|
|
+ *
|
|
|
+ * @param sellerId 卖家ID(用户ID,必传)
|
|
|
+ * @param pageNum 页码
|
|
|
+ * @param pageSize 每页条数
|
|
|
+ * @return 卖家评价分页列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public IPage<SellerEvaluationVo> getSellerEvaluationList(Integer sellerId, Integer pageNum, Integer pageSize) throws Exception {
|
|
|
+ try {
|
|
|
+ log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): sellerId={}, pageNum={}, pageSize={}",
|
|
|
+ sellerId, pageNum, pageSize);
|
|
|
+
|
|
|
+ // sellerId必传校验
|
|
|
+ if (sellerId == null) {
|
|
|
+ throw new Exception("卖家ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 参数默认值处理
|
|
|
+ if (pageNum == null || pageNum < 1) {
|
|
|
+ pageNum = 1;
|
|
|
+ }
|
|
|
+ if (pageSize == null || pageSize < 1) {
|
|
|
+ pageSize = 10;
|
|
|
+ }
|
|
|
+ // 限制最大每页条数
|
|
|
+ if (pageSize > 100) {
|
|
|
+ pageSize = 100;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用MyBatis Plus分页查询交易记录
|
|
|
+ Page<SecondTradeRecord> page = new Page<>(pageNum, pageSize);
|
|
|
+ LambdaQueryWrapper<SecondTradeRecord> tradeWrapper = new LambdaQueryWrapper<>();
|
|
|
+ tradeWrapper.eq(SecondTradeRecord::getSellerId, sellerId)
|
|
|
+ .eq(SecondTradeRecord::getDeleteFlag, 0)
|
|
|
+ .isNotNull(SecondTradeRecord::getBuyerEvaluate)
|
|
|
+ .ne(SecondTradeRecord::getBuyerEvaluate, "")
|
|
|
+ .orderByDesc(SecondTradeRecord::getCreatedTime);
|
|
|
+
|
|
|
+ IPage<SecondTradeRecord> tradePage = secondTradeRecordMapper.selectPage(page, tradeWrapper);
|
|
|
+ List<SecondTradeRecord> tradeRecords = tradePage.getRecords();
|
|
|
+
|
|
|
+ // 如果没有数据,直接返回空分页对象
|
|
|
+ if (tradeRecords.isEmpty()) {
|
|
|
+ log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): 未查询到评价记录");
|
|
|
+ Page<SellerEvaluationVo> emptyPage = new Page<>(pageNum, pageSize);
|
|
|
+ emptyPage.setTotal(0);
|
|
|
+ return emptyPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取所有商品记录ID、买家ID和卖家ID
|
|
|
+ List<Integer> goodsRecordIds = tradeRecords.stream()
|
|
|
+ .map(SecondTradeRecord::getGoodsRecordId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<Integer> buyerIds = tradeRecords.stream()
|
|
|
+ .map(SecondTradeRecord::getBuyerId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 批量查询商品记录信息
|
|
|
+ java.util.Map<Integer, SecondGoodsRecord> goodsRecordMap = new java.util.HashMap<>();
|
|
|
+ if (!goodsRecordIds.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<SecondGoodsRecord> goodsWrapper = new LambdaQueryWrapper<>();
|
|
|
+ goodsWrapper.in(SecondGoodsRecord::getId, goodsRecordIds);
|
|
|
+ List<SecondGoodsRecord> goodsRecords = secondGoodsRecordMapper.selectList(goodsWrapper);
|
|
|
+ goodsRecordMap = goodsRecords.stream()
|
|
|
+ .collect(Collectors.toMap(SecondGoodsRecord::getId, g -> g));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量查询买家用户信息
|
|
|
+ java.util.Map<Integer, LifeUser> buyerMap = new java.util.HashMap<>();
|
|
|
+ if (!buyerIds.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<LifeUser> userWrapper = new LambdaQueryWrapper<>();
|
|
|
+ userWrapper.in(LifeUser::getId, buyerIds)
|
|
|
+ .eq(LifeUser::getDeleteFlag, 0);
|
|
|
+ List<LifeUser> buyers = lifeUserMapper.selectList(userWrapper);
|
|
|
+ buyerMap = buyers.stream()
|
|
|
+ .collect(Collectors.toMap(LifeUser::getId, u -> u));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询卖家信息
|
|
|
+ LifeUser seller = lifeUserMapper.selectById(sellerId);
|
|
|
+
|
|
|
+ // 批量查询买家和卖家的信用积分
|
|
|
+ List<Integer> allUserIds = new java.util.ArrayList<>(buyerIds);
|
|
|
+ allUserIds.add(sellerId);
|
|
|
+ java.util.Map<Integer, SecondUserCredit> creditMap = new java.util.HashMap<>();
|
|
|
+ if (!allUserIds.isEmpty()) {
|
|
|
+ LambdaQueryWrapper<SecondUserCredit> creditWrapper = new LambdaQueryWrapper<>();
|
|
|
+ creditWrapper.in(SecondUserCredit::getUserId, allUserIds)
|
|
|
+ .eq(SecondUserCredit::getDeleteFlag, 0);
|
|
|
+ List<SecondUserCredit> credits = secondUserCreditMapper.selectList(creditWrapper);
|
|
|
+ creditMap = credits.stream()
|
|
|
+ .collect(Collectors.toMap(SecondUserCredit::getUserId, c -> c));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装返回结果
|
|
|
+ List<SellerEvaluationVo> evaluationList = new java.util.ArrayList<>();
|
|
|
+ for (SecondTradeRecord trade : tradeRecords) {
|
|
|
+ SellerEvaluationVo vo = new SellerEvaluationVo();
|
|
|
+
|
|
|
+ // 交易基本信息
|
|
|
+ vo.setId(trade.getId());
|
|
|
+ vo.setTradeNo(trade.getTradeNo());
|
|
|
+ vo.setGoodsId(trade.getGoodsId());
|
|
|
+ vo.setTransactionAmount(trade.getTransactionAmount());
|
|
|
+ vo.setBuyerId(trade.getBuyerId());
|
|
|
+ vo.setBuyerEvaluate(trade.getBuyerEvaluate());
|
|
|
+ // 卖家交易完成时间(评价时间,评分时间)
|
|
|
+ vo.setSellerCompleteTime(trade.getSellerCompleteTime());
|
|
|
+ // 买家交易完成时间(评价时间,评分时间)
|
|
|
+ vo.setBuyerCompleteTime(trade.getBuyerCompleteTime());
|
|
|
+ vo.setBuyerRating(trade.getBuyerRating());
|
|
|
+ vo.setTransactionTime(trade.getTransactionTime());
|
|
|
+ vo.setTradeStatus(trade.getTradeStatus());
|
|
|
+ vo.setCreatedTime(trade.getCreatedTime());
|
|
|
+
|
|
|
+ // 商品信息
|
|
|
+ SecondGoodsRecord goodsRecord = goodsRecordMap.get(trade.getGoodsRecordId());
|
|
|
+ if (goodsRecord != null) {
|
|
|
+ vo.setGoodsTitle(goodsRecord.getTitle());
|
|
|
+ vo.setGoodsHomeImage(goodsRecord.getHomeImage());
|
|
|
+ vo.setGoodsPrice(goodsRecord.getPrice());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 买家用户信息
|
|
|
+ LifeUser buyer = buyerMap.get(trade.getBuyerId());
|
|
|
+ if (buyer != null) {
|
|
|
+ vo.setBuyerName(buyer.getUserName());
|
|
|
+ vo.setBuyerImage(buyer.getUserImage());
|
|
|
+ vo.setBuyerPhone(buyer.getUserPhone());
|
|
|
+ vo.setBuyerRealName(buyer.getRealName());
|
|
|
+ vo.setBuyerSex(buyer.getUserSex());
|
|
|
+ vo.setBuyerJianjie(buyer.getJianjie());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 买家信用积分和风控评分等级
|
|
|
+ SecondUserCredit buyerCredit = creditMap.get(trade.getBuyerId());
|
|
|
+ if (buyerCredit != null) {
|
|
|
+ vo.setBuyerCreditScore(buyerCredit.getUserPoints());
|
|
|
+ } else {
|
|
|
+ vo.setBuyerCreditScore(0);
|
|
|
+ }
|
|
|
+ vo.setBuyerCreditLevel(calculateCreditLevel(trade.getBuyerId()));
|
|
|
+
|
|
|
+ // 卖家信息
|
|
|
+ vo.setSellerId(sellerId);
|
|
|
+ if (seller != null) {
|
|
|
+ vo.setSellerName(seller.getUserName());
|
|
|
+ vo.setSellerImage(seller.getUserImage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 卖家信用积分和风控评分等级
|
|
|
+ SecondUserCredit sellerCredit = creditMap.get(sellerId);
|
|
|
+ if (sellerCredit != null) {
|
|
|
+ vo.setSellerCreditScore(sellerCredit.getUserPoints());
|
|
|
+ } else {
|
|
|
+ vo.setSellerCreditScore(0);
|
|
|
+ }
|
|
|
+ vo.setSellerCreditLevel(calculateCreditLevel(sellerId));
|
|
|
+
|
|
|
+ evaluationList.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建分页返回对象
|
|
|
+ Page<SellerEvaluationVo> resultPage = new Page<>(pageNum, pageSize);
|
|
|
+ resultPage.setRecords(evaluationList);
|
|
|
+ resultPage.setTotal(tradePage.getTotal());
|
|
|
+ resultPage.setPages(tradePage.getPages());
|
|
|
+
|
|
|
+ log.info("SecondTradeRecordServiceImpl.getSellerEvaluationList(): 查询到{}条评价记录,共{}页",
|
|
|
+ evaluationList.size(), resultPage.getPages());
|
|
|
+ return resultPage;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("SecondTradeRecordServiceImpl.getSellerEvaluationList(): Error Msg={}", e.getMessage(), e);
|
|
|
+ throw new Exception("获取卖家评价列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void locationShareAdd(Integer otherUserId) throws Exception {
|
|
|
+ try {
|
|
|
+ Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
|
|
|
+ String key = getKey(userId, otherUserId);
|
|
|
+
|
|
|
+ if (baseRedisService.hasKey(key)) {
|
|
|
+ JSONArray array = JSONArray.parseArray(baseRedisService.getString(key));
|
|
|
+ if (!array.contains(userId)) array.add(userId);
|
|
|
+ baseRedisService.setString(key, array.toJSONString());
|
|
|
+ } else {
|
|
|
+ JSONArray array = new JSONArray();
|
|
|
+ array.add(userId);
|
|
|
+ baseRedisService.setString(key, array.toJSONString());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("SecondTradeRecordServiceImpl.locationShareAdd(): Error Msg={}", e.getMessage(), e);
|
|
|
+ throw new Exception("添加位置共享失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void locationShareDel(Integer otherUserId) throws Exception {
|
|
|
+ try {
|
|
|
+ Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
|
|
|
+ String key = getKey(userId, otherUserId);
|
|
|
+
|
|
|
+ // 存在key,则删除
|
|
|
+ if (baseRedisService.hasKey(key)) {
|
|
|
+ JSONArray array = JSONArray.parseArray(baseRedisService.getString(key));
|
|
|
+ array.remove(userId);
|
|
|
+ if (array.isEmpty()) {
|
|
|
+ baseRedisService.delete(key);
|
|
|
+ LifeUser user = lifeUserMapper.selectById(userId);
|
|
|
+ LifeUser otherUser = lifeUserMapper.selectById(otherUserId);
|
|
|
+ LambdaQueryWrapper<LifeMessage> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(LifeMessage::getType, 10);
|
|
|
+ wrapper.isNull(LifeMessage::getContent);
|
|
|
+ wrapper.apply("((receiver_id = 'user_" + otherUser.getUserPhone() + "' and sender_id = 'user_" + user.getUserPhone() + "') or (receiver_id = 'user_" + user.getUserPhone() + "' and sender_id = 'user_" + otherUser.getUserPhone() + "'))");
|
|
|
+ List<Integer> messageIds = lifeMessageMapper.selectList(wrapper).stream().map(LifeMessage::getId).collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(messageIds)) {
|
|
|
+ // 修改消息状态
|
|
|
+ JSONObject messageJson = new JSONObject();
|
|
|
+ messageJson.put("cardType", 2);
|
|
|
+ LambdaUpdateWrapper<LifeMessage> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ updateWrapper.in(LifeMessage::getId, messageIds);
|
|
|
+ updateWrapper.set(LifeMessage::getContent, messageJson.toJSONString());
|
|
|
+ lifeMessageMapper.update(null, updateWrapper);
|
|
|
+
|
|
|
+ // 发起交易人信息
|
|
|
+ String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
|
|
|
+
|
|
|
+ // 获取交易对方信息
|
|
|
+ LifeUser lifeUser = lifeUserMapper.selectById(otherUserId);
|
|
|
+ String receiverId = "user_" + lifeUser.getUserPhone();
|
|
|
+
|
|
|
+ // 给买家与卖家发送交易消息
|
|
|
+ WebSocketVo webSocketVo = new WebSocketVo();
|
|
|
+ webSocketVo.setSenderId(phoneId);
|
|
|
+ webSocketVo.setReceiverId(receiverId);
|
|
|
+ webSocketVo.setCategory("message");
|
|
|
+ webSocketVo.setType("10");
|
|
|
+ webSocketVo.setIsRead(0);
|
|
|
+ webSocketVo.setText(messageJson.toJSONString());
|
|
|
+ webSocketVo.setMessageIdList(messageIds);
|
|
|
+
|
|
|
+ alienStoreFeign.sendMsgToClientByPhoneId(phoneId, JSONObject.from(webSocketVo).toJSONString());
|
|
|
+ alienStoreFeign.sendMsgToClientByPhoneId(receiverId, JSONObject.from(webSocketVo).toJSONString());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ baseRedisService.setString(key, array.toJSONString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("SecondTradeRecordServiceImpl.locationShareDel(): Error Msg={}", e.getMessage(), e);
|
|
|
+ throw new Exception("删除位置共享失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean locationShareHas(Integer otherUserId) throws Exception {
|
|
|
+ try {
|
|
|
+ Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
|
|
|
+ String key = getKey(userId, otherUserId);
|
|
|
+
|
|
|
+ // 是否存在定位信息
|
|
|
+ if (baseRedisService.hasKey(key) && !JSONArray.parseArray(baseRedisService.getString(key)).isEmpty()) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ baseRedisService.delete(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("SecondTradeRecordServiceImpl.locationShareHas(): Error Msg={}", e.getMessage(), e);
|
|
|
+ throw new Exception("获取位置共享状态失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getKey(Integer userId, Integer otherUserId) {
|
|
|
+ // 组合userId和otherUserId作为Redis的key
|
|
|
+ // 使用排序方式确保key的一致性(较小的ID在前)
|
|
|
+ String key;
|
|
|
+ if (userId.compareTo(otherUserId) < 0) {
|
|
|
+ key = "second_location_share:" + userId + ":" + otherUserId;
|
|
|
+ } else {
|
|
|
+ key = "second_location_share:" + otherUserId + ":" + userId;
|
|
|
+ }
|
|
|
+ return key;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算用户风控评分等级
|
|
|
+ * 根据用户违规次数计算等级:O(无记录) < A(1-2次) < B(3-5次) < C(6-9次) < D(10-14次) < E(≥15次)
|
|
|
+ *
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @return 风控评分等级
|
|
|
+ */
|
|
|
+ private String calculateCreditLevel(Integer userId) {
|
|
|
+ try {
|
|
|
+ if (userId == null) {
|
|
|
+ return "O";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询用户违规记录数量
|
|
|
+ LambdaQueryWrapper<SecondRiskControlRecord> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(SecondRiskControlRecord::getUserId, userId)
|
|
|
+ .eq(SecondRiskControlRecord::getDeleteFlag, 0);
|
|
|
+
|
|
|
+ Integer count = secondRiskControlRecordMapper.selectCount(wrapper);
|
|
|
+ int violationCount = count != null ? count : 0;
|
|
|
+
|
|
|
+ // 根据违规次数确定等级
|
|
|
+ if (violationCount == 0) {
|
|
|
+ return "O"; // 无记录
|
|
|
+ } else if (violationCount >= 15) {
|
|
|
+ return "E"; // 最差
|
|
|
+ } else if (violationCount >= 10) {
|
|
|
+ return "D";
|
|
|
+ } else if (violationCount >= 6) {
|
|
|
+ return "C";
|
|
|
+ } else if (violationCount >= 3) {
|
|
|
+ return "B";
|
|
|
+ } else {
|
|
|
+ return "A"; // 1-2次违规
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("SecondTradeRecordServiceImpl.calculateCreditLevel(): Error Msg={}", e.getMessage(), e);
|
|
|
+ return "O"; // 异常时返回默认等级
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|