|
@@ -395,49 +395,165 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
|
|
|
}*/
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 默认佣金率(百分比)
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int DEFAULT_COMMISSION_RATE = 3;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 订单号生成最大重试次数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int MAX_ORDER_NUMBER_RETRY = 5;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 订单支付超时时间(秒),30分钟
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final long ORDER_PAYMENT_TIMEOUT_SECONDS = 30 * 60;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 立即咨询 - 创建咨询订单
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 创建订单前会进行以下校验:
|
|
|
|
|
+ * 1. 参数校验:客户端用户ID、律师用户ID、订单金额不能为空
|
|
|
|
|
+ * 2. 律师信息校验:律师必须存在且未被删除
|
|
|
|
|
+ * 3. 订单号唯一性校验:确保生成的订单号唯一
|
|
|
|
|
+ * </p>
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 创建订单后会:
|
|
|
|
|
+ * 1. 计算咨询费用(根据律师佣金率)
|
|
|
|
|
+ * 2. 设置订单支付超时监听(30分钟)
|
|
|
|
|
+ * </p>
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param lawyerConsultationOrder 咨询订单信息
|
|
|
|
|
+ * @return 创建结果
|
|
|
|
|
+ */
|
|
|
@Override
|
|
@Override
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
public R<LawyerConsultationOrderDto> consultNow(LawyerConsultationOrder lawyerConsultationOrder) {
|
|
public R<LawyerConsultationOrderDto> consultNow(LawyerConsultationOrder lawyerConsultationOrder) {
|
|
|
- log.info("LawyerConsultationOrderController.consultNow?lawyerConsultationOrder={}", lawyerConsultationOrder);
|
|
|
|
|
- LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
|
|
|
|
|
- order.setClientUserId(lawyerConsultationOrder.getClientUserId());
|
|
|
|
|
- order.setLawyerUserId(lawyerConsultationOrder.getLawyerUserId());
|
|
|
|
|
- order.setProblemScenarioId(lawyerConsultationOrder.getProblemScenarioId());
|
|
|
|
|
- order.setProblemDescription(lawyerConsultationOrder.getProblemDescription());
|
|
|
|
|
- order.setOrderAmount(lawyerConsultationOrder.getOrderAmount());
|
|
|
|
|
- order.setOrderStatus(0);
|
|
|
|
|
- order.setPaymentStatus(0);
|
|
|
|
|
- order.setOrderTime(new Date());
|
|
|
|
|
-// order.setValidityPeriod(DateUtils.addDays(new Date(), 7));
|
|
|
|
|
- order.setCreatedTime(new Date());
|
|
|
|
|
- order.setUpdatedTime(new Date());
|
|
|
|
|
- order.setDeleteFlag(0);
|
|
|
|
|
- order.setAlipayNo(lawyerConsultationOrder.getAlipayNo());
|
|
|
|
|
- order.setOrderStr(lawyerConsultationOrder.getOrderStr());
|
|
|
|
|
- //订单编号想要LAW+年月日(8位数字)+随机5位数字这种格式的
|
|
|
|
|
- String orderNumber = "LAW" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + String.format("%05d", RandomUtils.nextInt(100000));
|
|
|
|
|
- order.setOrderNumber(orderNumber);
|
|
|
|
|
- //计算本单收益
|
|
|
|
|
- LawyerUser lawyerUser = lawyerUserMapper.selectById(lawyerConsultationOrder.getLawyerUserId());
|
|
|
|
|
- if(lawyerUser != null){
|
|
|
|
|
|
|
+ log.info("开始创建咨询订单,clientUserId={}, lawyerUserId={}, orderAmount={}",
|
|
|
|
|
+ lawyerConsultationOrder.getClientUserId(),
|
|
|
|
|
+ lawyerConsultationOrder.getLawyerUserId(),
|
|
|
|
|
+ lawyerConsultationOrder.getOrderAmount());
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1. 参数校验
|
|
|
|
|
+ if (lawyerConsultationOrder.getClientUserId() == null) {
|
|
|
|
|
+ log.warn("创建咨询订单失败:客户端用户ID为空");
|
|
|
|
|
+ return R.fail("客户端用户ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (lawyerConsultationOrder.getLawyerUserId() == null) {
|
|
|
|
|
+ log.warn("创建咨询订单失败:律师用户ID为空");
|
|
|
|
|
+ return R.fail("律师用户ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (lawyerConsultationOrder.getOrderAmount() == null ||
|
|
|
|
|
+ lawyerConsultationOrder.getOrderAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
+ log.warn("创建咨询订单失败:订单金额无效,orderAmount={}", lawyerConsultationOrder.getOrderAmount());
|
|
|
|
|
+ return R.fail("订单金额必须大于0");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 校验律师信息
|
|
|
|
|
+ LawyerUser lawyerUser = lawyerUserMapper.selectById(lawyerConsultationOrder.getLawyerUserId());
|
|
|
|
|
+ if (lawyerUser == null) {
|
|
|
|
|
+ log.warn("创建咨询订单失败:律师不存在,lawyerUserId={}", lawyerConsultationOrder.getLawyerUserId());
|
|
|
|
|
+ return R.fail("律师不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (lawyerUser.getDeleteFlag() != null && lawyerUser.getDeleteFlag() == 1) {
|
|
|
|
|
+ log.warn("创建咨询订单失败:律师已被删除,lawyerUserId={}", lawyerConsultationOrder.getLawyerUserId());
|
|
|
|
|
+ return R.fail("律师已被删除");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 创建订单对象
|
|
|
|
|
+ LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
|
|
|
|
|
+ BeanUtils.copyProperties(lawyerConsultationOrder, order);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 设置订单基本信息
|
|
|
|
|
+ Date now = new Date();
|
|
|
|
|
+ order.setOrderStatus(LawyerStatusEnum.WAIT_PAY.getStatus()); // 待支付
|
|
|
|
|
+ order.setPaymentStatus(0); // 未支付
|
|
|
|
|
+ order.setOrderTime(now);
|
|
|
|
|
+ order.setCreatedTime(now);
|
|
|
|
|
+ order.setUpdatedTime(now);
|
|
|
|
|
+ order.setDeleteFlag(0);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 生成唯一订单号
|
|
|
|
|
+ String orderNumber = generateUniqueOrderNumber();
|
|
|
|
|
+ order.setOrderNumber(orderNumber);
|
|
|
|
|
+ log.info("生成订单号:{}", orderNumber);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 计算咨询费用(根据律师佣金率)
|
|
|
Integer commissionRate = lawyerUser.getCommissionRate();
|
|
Integer commissionRate = lawyerUser.getCommissionRate();
|
|
|
- int rate = commissionRate!=null&&commissionRate>0?commissionRate:3;
|
|
|
|
|
- BigDecimal orderAmount = lawyerConsultationOrder.getOrderAmount();
|
|
|
|
|
- BigDecimal result2 = orderAmount.multiply(new BigDecimal(rate/100))
|
|
|
|
|
|
|
+ int rate = (commissionRate != null && commissionRate > 0) ? commissionRate : DEFAULT_COMMISSION_RATE;
|
|
|
|
|
+ BigDecimal orderAmount = lawyerConsultationOrder.getOrderAmount();
|
|
|
|
|
+ // 修复计算逻辑:使用 BigDecimal 进行精确计算
|
|
|
|
|
+ BigDecimal rateDecimal = new BigDecimal(rate).divide(new BigDecimal(100), 4, RoundingMode.HALF_UP);
|
|
|
|
|
+ BigDecimal platformFee = orderAmount.multiply(rateDecimal)
|
|
|
.setScale(0, RoundingMode.HALF_UP);
|
|
.setScale(0, RoundingMode.HALF_UP);
|
|
|
- order.setConsultationFee(result2.intValue());
|
|
|
|
|
- }
|
|
|
|
|
- int num = consultationOrderMapper.insertOrder(order);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ BigDecimal consultationFee = orderAmount.subtract(platformFee);
|
|
|
|
|
|
|
|
-// boolean result = this.save(order);
|
|
|
|
|
-// if (result) {
|
|
|
|
|
-// return R.data(order);
|
|
|
|
|
-// }
|
|
|
|
|
-// return R.fail("新增失败");
|
|
|
|
|
- if (num >0){
|
|
|
|
|
|
|
+ order.setConsultationFee(consultationFee.intValue());
|
|
|
|
|
+ log.info("计算咨询费用:订单金额={}, 佣金率={}%, 咨询费用={}",
|
|
|
|
|
+ orderAmount, rate, consultationFee);
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 插入订单
|
|
|
|
|
+ int insertResult = consultationOrderMapper.insertOrder(order);
|
|
|
|
|
+ if (insertResult <= 0) {
|
|
|
|
|
+ log.error("创建咨询订单失败:数据库插入失败,订单号={}", orderNumber);
|
|
|
|
|
+ return R.fail("创建订单失败");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 8. 设置订单支付超时监听(30分钟)
|
|
|
|
|
+ try {
|
|
|
|
|
+ orderExpirationService.setOrderPaymentTimeout(orderNumber, ORDER_PAYMENT_TIMEOUT_SECONDS);
|
|
|
|
|
+ log.info("已设置订单支付超时监听,订单号={}, 超时时间={}秒", orderNumber, ORDER_PAYMENT_TIMEOUT_SECONDS);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("设置订单支付超时监听失败,订单号={}", orderNumber, e);
|
|
|
|
|
+ // 不影响订单创建,仅记录日志
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("创建咨询订单成功,订单号={}, 订单ID={}", orderNumber, order.getId());
|
|
|
return R.data(order);
|
|
return R.data(order);
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("创建咨询订单异常", e);
|
|
|
|
|
+ return R.fail("创建订单失败:" + e.getMessage());
|
|
|
}
|
|
}
|
|
|
- return R.fail("新增失败");
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成唯一的订单号
|
|
|
|
|
+ * 格式:LAW + 年月日(8位数字)+ 随机5位数字
|
|
|
|
|
+ * 如果订单号已存在,会重试生成(最多重试5次)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 唯一的订单号
|
|
|
|
|
+ */
|
|
|
|
|
+ private String generateUniqueOrderNumber() {
|
|
|
|
|
+ String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
|
|
|
|
+ String prefix = "LAW" + dateStr;
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < MAX_ORDER_NUMBER_RETRY; i++) {
|
|
|
|
|
+ // 生成5位随机数字
|
|
|
|
|
+ int randomNum = RandomUtils.nextInt(100000);
|
|
|
|
|
+ String orderNumber = prefix + String.format("%05d", randomNum);
|
|
|
|
|
+
|
|
|
|
|
+ // 检查订单号是否已存在
|
|
|
|
|
+ LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
+ queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNumber)
|
|
|
|
|
+ .last("LIMIT 1");
|
|
|
|
|
+ LawyerConsultationOrder existingOrder = consultationOrderMapper.selectOne(queryWrapper);
|
|
|
|
|
+
|
|
|
|
|
+ if (existingOrder == null) {
|
|
|
|
|
+ // 订单号唯一,返回
|
|
|
|
|
+ return orderNumber;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.warn("订单号已存在,重新生成,orderNumber={}, retry={}", orderNumber, i + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果重试5次后仍然重复,使用时间戳确保唯一性
|
|
|
|
|
+ String timestamp = String.valueOf(System.currentTimeMillis());
|
|
|
|
|
+ String fallbackOrderNumber = prefix + timestamp.substring(timestamp.length() - 5);
|
|
|
|
|
+ log.warn("订单号生成重试{}次后仍重复,使用时间戳生成:{}", MAX_ORDER_NUMBER_RETRY, fallbackOrderNumber);
|
|
|
|
|
+ return fallbackOrderNumber;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|