| | |
| | | import com.ruoyi.order.mapper.OrderMapper; |
| | | import com.ruoyi.order.model.Order; |
| | | import com.ruoyi.order.model.OrderGood; |
| | | import com.ruoyi.order.service.OrderGoodService; |
| | | import com.ruoyi.order.service.OrderService; |
| | | import com.ruoyi.order.util.ExpressDeliveryUtil; |
| | | import com.ruoyi.order.util.payment.PaymentUtil; |
| | |
| | | import com.ruoyi.order.vo.*; |
| | | import com.ruoyi.other.api.domain.*; |
| | | import com.ruoyi.other.api.feignClient.*; |
| | | import com.ruoyi.other.api.vo.GetSeckillActivityInfo; |
| | | import com.ruoyi.system.api.domain.SysConfig; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysConfigClient; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import com.ruoyi.system.api.model.LoginUser; |
| | | import lombok.SneakyThrows; |
| | |
| | | |
| | | @Resource |
| | | private GoodsClient goodsClient; |
| | | @Resource |
| | | private SeckillActivityInfoClient seckillActivityInfoClient; |
| | | @Resource |
| | | private SysConfigClient sysConfigClient; |
| | | @Resource |
| | | private GoodsShopClient goodsShopClient; |
| | | @Resource |
| | | private OrderGoodService orderGoodService; |
| | | |
| | | @Resource |
| | | private RedisTemplate redisTemplate; |
| | |
| | | //用户信息 |
| | | Long userid = tokenService.getLoginUserApplet().getUserid(); |
| | | AppUser appUser = appUserClient.getAppUserById(userid); |
| | | //商品信息 |
| | | //获取商品信息 |
| | | Goods good = goodsClient.getGoodsById(goodId).getData(); |
| | | if (null == good) { |
| | | if (null == good||good.getDelFlag()==1||good.getStatus()==0) { |
| | | //商品不存在 |
| | | throw new ServiceException("商品不存在"); |
| | | } |
| | | //店铺信息 |
| | | //查询店铺信息 |
| | | |
| | | //计算价格信息 |
| | | GoodsShop shop = goodsShopClient.getGoodsShop(goodId).getData(); |
| | | System.out.println(shop); |
| | | if (null == shop){ |
| | | //门店不存在 |
| | | throw new ServiceException("该商品门店不存在"); |
| | | } |
| | | //插入基础信息 |
| | | confirmOrderVo.setGoodId(goodId); |
| | | confirmOrderVo.setGoodName(good.getName()); |
| | | confirmOrderVo.setHomePicture(good.getHomePagePicture()); |
| | | confirmOrderVo.setNumber(1); |
| | | confirmOrderVo.setShopId(shop.getShopId()); |
| | | confirmOrderVo.setShopName(shop.getShopName()); |
| | | confirmOrderVo.setPurchaseLimitNum(good.getPurchaseLimit()); |
| | | confirmOrderVo.setOriginalPrice(good.getOriginalPrice()); |
| | | //todo 实时计算用户可用积分 |
| | | |
| | | |
| | | confirmOrderVo.setResidualPoint(appUser.getAvailablePoint()); |
| | | //插入价格 |
| | | confirmOrderVo.setCash(good.getSellingPrice()); |
| | | confirmOrderVo.setPoint(good.getIntegral()); |
| | | |
| | | //计算活动价格信息 |
| | | Price price = getPrice(goodId, 1); |
| | | if (null != price) { |
| | | confirmOrderVo.setCash(price.getCash()); |
| | | confirmOrderVo.setOrderPoint(price.getPoint()); |
| | | confirmOrderVo.setEndTimeStamp(price.getEndTimeStamp()); |
| | | } |
| | | //判断是否是积分支付 |
| | | if (type == 1) {//现金 |
| | | confirmOrderVo.setOrderMoney(confirmOrderVo.getCash()); |
| | | //计算积分抵扣的金额 将积分转为金额,去掉小数 |
| | | BigDecimal deduction=getCashByPoint(confirmOrderVo.getResidualPoint()); |
| | | confirmOrderVo.setDeduction(deduction); |
| | | }else {//积分 |
| | | confirmOrderVo.setOrderPoint(good.getIntegral()); |
| | | } |
| | | //限购检查 |
| | | //判断当前数量是否已经超出限购数量(需要计算已经购买的数量) |
| | | if(null == good.getPurchaseLimit() || -1 == good.getPurchaseLimit()){ |
| | | confirmOrderVo.setIsPurchaseLimit(false); |
| | | confirmOrderVo.setPurchaseLimitNum(-1); |
| | | }else{ |
| | | //todo 查当前用户的订单 |
| | | List<Order> orders = this.list(new LambdaQueryWrapper<Order>().eq(Order::getAppUserId, appUser.getId()).eq(Order::getDelFlag, 0).in(Order::getOrderStatus, Arrays.asList(4, 8))); |
| | | List<Long> orderIds = orders.stream().map(Order::getId).collect(Collectors.toList()); |
| | | int sum = 0; |
| | | if(!orderIds.isEmpty()){ |
| | | //关于该商品的订单 |
| | | List<OrderGood> orderGoodList = orderGoodService.list(new LambdaQueryWrapper<OrderGood>().in(OrderGood::getOrderId, orderIds) |
| | | .eq(OrderGood::getGoodsId, good.getId()).eq(OrderGood::getDelFlag, 0)); |
| | | sum = orderGoodList.stream().mapToInt(OrderGood::getNum).sum(); |
| | | } |
| | | confirmOrderVo.setIsPurchaseLimit((1 + sum) > good.getPurchaseLimit()); |
| | | confirmOrderVo.setPurchaseLimitNum(good.getPurchaseLimit() - sum); |
| | | } |
| | | |
| | | return confirmOrderVo; |
| | | } |
| | | /** |
| | | * 根据商品的价格配置体系获取商品当前的价格 |
| | | * @param goodsId |
| | | * @param type 1普通商品,2秒杀商品 |
| | | * @return |
| | | */ |
| | | public Price getPrice( Integer goodsId, Integer type){ |
| | | //判断是否有在秒杀活动时间中 |
| | | Price price = new Price(); |
| | | GetSeckillActivityInfo getSeckillActivityInfo = new GetSeckillActivityInfo(); |
| | | getSeckillActivityInfo.setGoodsId(goodsId); |
| | | GoodsSeckill goodsSeckill = seckillActivityInfoClient.getSeckillActivityInfo(getSeckillActivityInfo).getData(); |
| | | //没有秒杀活动或者添加的普通商品则使用秒杀活动价格 |
| | | if(null == goodsSeckill || type == 1){ |
| | | return null; |
| | | } |
| | | //秒杀活动价格 |
| | | price.setCash(goodsSeckill.getSellingPrice()); |
| | | //计算对应积分 |
| | | price.setPoint(getPoint(price.getCash())); |
| | | price.setEndTimeStamp(goodsSeckill.getEndTime()); |
| | | return price; |
| | | } |
| | | /** |
| | | * 获取现金对应积分 |
| | | */ |
| | | public Integer getPoint(BigDecimal cash){ |
| | | if (cash == null || cash.compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new IllegalArgumentException("金额不能为null或负数"); |
| | | } |
| | | // 获取积分兑换比例配置 |
| | | R<SysConfig> info = sysConfigClient.getInfo(6L); |
| | | if (info == null || info.getData() == null) { |
| | | throw new RuntimeException("获取积分兑换比例配置失败"); |
| | | } |
| | | String configValue = info.getData().getConfigValue(); |
| | | if (StringUtils.isBlank(configValue)) { |
| | | throw new RuntimeException("积分兑换比例配置值为空"); |
| | | } |
| | | try { |
| | | // 使用BigDecimal处理比例,避免精度问题 |
| | | BigDecimal ratio = new BigDecimal(configValue.trim()); |
| | | if (ratio.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new RuntimeException("积分兑换比例必须大于0"); |
| | | } |
| | | |
| | | // 计算积分并四舍五入取整 |
| | | return cash.multiply(ratio).intValue(); |
| | | |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException("积分兑换比例配置值格式错误", e); |
| | | } catch (ArithmeticException e) { |
| | | throw new RuntimeException("积分计算结果溢出", e); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 获取积分对应金额 |
| | | */ |
| | | public BigDecimal getCashByPoint(Integer point){ |
| | | // 参数校验 |
| | | if (point == null || point < 0) { |
| | | throw new IllegalArgumentException("积分值不能为null或负数"); |
| | | } |
| | | |
| | | // 特殊情况:0积分直接返回0金额 |
| | | if (point == 0) { |
| | | return BigDecimal.ZERO.setScale(2); |
| | | } |
| | | |
| | | // 获取积分兑换比例配置 |
| | | R<SysConfig> info = sysConfigClient.getInfo(6L); |
| | | if (info == null || info.getData() == null) { |
| | | throw new RuntimeException("获取积分兑换比例配置失败"); |
| | | } |
| | | |
| | | String configValue = info.getData().getConfigValue(); // 示例:"100" 表示 100积分=1元 |
| | | if (StringUtils.isBlank(configValue)) { |
| | | throw new RuntimeException("积分兑换比例配置值为空"); |
| | | } |
| | | |
| | | try { |
| | | // 解析兑换比例(转换为BigDecimal保证精度) |
| | | BigDecimal exchangeRate = new BigDecimal(configValue.trim()); |
| | | if (exchangeRate.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new RuntimeException("积分兑换比例必须为正数"); |
| | | } |
| | | |
| | | // 高精度计算(积分/比例) |
| | | return new BigDecimal(point) |
| | | .divide(exchangeRate, 2, RoundingMode.HALF_UP); |
| | | |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException("积分兑换比例配置值格式错误,应为数字", e); |
| | | } catch (ArithmeticException e) { |
| | | throw new RuntimeException("积分计算错误", e); |
| | | } |
| | | } |
| | | } |