huliguo
3 天以前 3348eda2c33469e9935ae6afcf83ea5c52cea906
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java
@@ -9,26 +9,30 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.GeodesyUtil;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.other.api.domain.Phone;
import com.ruoyi.other.api.domain.Shop;
import com.ruoyi.other.api.domain.ShopScore;
import com.ruoyi.other.mapper.PhoneMapper;
import com.ruoyi.other.mapper.ShopMapper;
import com.ruoyi.other.mapper.ShopScoreMapper;
import com.ruoyi.other.service.ShopScoreService;
import com.ruoyi.other.service.ShopService;
import com.ruoyi.other.vo.NearbyShopVO;
import com.ruoyi.other.vo.SaveWithdrawalAccount;
import com.ruoyi.other.vo.ShopDetailVO;
import com.ruoyi.order.feignClient.OrderClient;
import com.ruoyi.order.vo.Price;
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.dto.AddGoodsDTO;
import com.ruoyi.other.enums.GoodsStatus;
import com.ruoyi.other.mapper.*;
import com.ruoyi.other.service.*;
import com.ruoyi.other.vo.*;
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 org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -44,6 +48,8 @@
    @Resource
    private ShopMapper shopMapper;
    @Resource
    private GoodsService goodsService;
    @Resource
    private PhoneMapper phoneMapper;
    @Resource
    private ShopScoreService shopScoreService;
@@ -55,6 +61,22 @@
    private SysUserClient sysUserClient;
    @Resource
    private ShopScoreMapper scoreMapper;
    @Resource
    private ShopBalanceStatementMapper shopBalanceStatementMapper;
    @Resource
    private OrderClient orderClient;
    @Resource
    private SeckillActivityInfoService seckillActivityInfoService;
    @Resource
    private GoodsSeckillService goodsSeckillService;
    @Resource
    private SysConfigClient sysConfigClient;
    @Resource
    private GoodsShopMapper goodsShopMapper;
    @Resource
    private GoodsShopService goodsShopService;
    @Resource
    private GoodsEvaluateMapper goodsEvaluateMapper;
    /**
@@ -139,7 +161,8 @@
        }
        // 计算距离
        if (shopDetailVO.getLongitude() != null && shopDetailVO.getLatitude() != null){
        if (shopDetailVO.getLongitude() != null && shopDetailVO.getLatitude() != null
            && longitude != null && latitude != null) {
            String shopLocation = String.format("%s,%s", shopDetailVO.getLongitude(), shopDetailVO.getLatitude());
            String userLocation = String.format("%s,%s", longitude.toString(), latitude.toString());
            Map<String, Double> distanceMap = GeodesyUtil.getDistance(userLocation, shopLocation);
@@ -179,5 +202,342 @@
        }
    }
    /**
     * 门店余额统计
     * @param shopId
     * @return
     */
    @Override
    public ShopBalanceVO getShopBalance(Integer shopId) {
        Shop shop = shopMapper.selectById(shopId);
        ShopBalanceVO shopBalanceVO = new ShopBalanceVO();
        shopBalanceVO.setBalance(shop.getBalance());
        shopBalanceVO.setCanWithdrawMoney(shop.getCanWithdrawMoney());
        shopBalanceVO.setWithdrawMoney(shop.getWithdrawMoney());
        shopBalanceVO.setWithdrawAuditMoney(shop.getWithdrawAuditMoney());
        //冻结金额 = 余额 - 可提现金额
        shopBalanceVO.setFreezeMoney(shop.getBalance().subtract(shop.getCanWithdrawMoney()));
        return shopBalanceVO;
    }
    /**
     * 门店余额变更明细
     */
    @Override
    public PageInfo<ShopBalanceStatementVO> getShopBalanceStatementList(Integer shopId, LocalDateTime startTime, LocalDateTime endTime, Integer type, Integer pageCurr, Integer pageSize) {
        PageInfo<ShopBalanceStatementVO> pageInfo = new PageInfo<>(pageCurr, pageSize);
        List<ShopBalanceStatementVO> ShopBalanceStatementList = shopBalanceStatementMapper.getShopBalanceStatementList(pageInfo, shopId, startTime, endTime, type);
        for (ShopBalanceStatementVO shopBalanceStatementVO : ShopBalanceStatementList) {
            log.error(shopBalanceStatementVO.toString());
            BigDecimal historicalBalance = shopBalanceStatementVO.getHistoricalBalance();
            BigDecimal balance = shopBalanceStatementVO.getBalance();
            if (historicalBalance != null && balance != null) {
                shopBalanceStatementVO.setFlag(
                        historicalBalance.compareTo(balance) > 0 ? 2 : 1
                );
            }
        }
        pageInfo.setRecords(ShopBalanceStatementList);
        return pageInfo;
    }
    /**
     * 店铺内商品列表 门店后台
     */
    @Override
    public List<GoodsVO> getGoodsListByShopId(PageInfo<GoodsVO> pageInfo, Integer shopId) {
        //查询该门店商品
        List<GoodsVO> goods = shopMapper.selectListByShopId(pageInfo, shopId);
        if(null == goods){
            return null;
        }
        // 根据id去重
        List<GoodsVO> distinctGoods = goods.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toMap(GoodsVO::getGoodsId, Function.identity(), (existing, replacement) -> existing),
                        map -> new ArrayList<>(map.values())
                ));
        for (GoodsVO good : distinctGoods) {
            //价格
            Price price = getPrice( good.getGoodsId());
            if(null != price){
                //秒杀活动
                good.setSellingPrice(price.getCash());
                good.setIntegral(price.getPoint());
                good.setStartTime(price.getStartTime());
                good.setEndTime(price.getEndTime());
                good.setPurchaseLimit(price.getPurchaseLimit());
            }
            Integer data = orderClient.getGoodsSaleNum(good.getGoodsId(), 1).getData();
            good.setSaleNum(data);
        }
        return distinctGoods;
    }
    @Override
    public GoodsVO goodsDetail(Long goodsId) {
        if (goodsId == null || goodsId <= 0) {
            throw new NullPointerException("商品ID不能为空");
        }
        Goods goods = goodsService.getById(goodsId);
        if(null == goods || goods.getDelFlag() == 1){
            throw new RuntimeException("商品不存在");
        }
        GoodsVO goodsVO = new GoodsVO();
        BeanUtils.copyBeanProp(goodsVO, goods);
        goodsVO.setGoodsId(goods.getId());
        goodsVO.setGoodsName(goods.getName());
        //商品活动前售价(编辑商品回显)
        goodsVO.setEditPrice(goods.getSellingPrice());
        //限购数量(编辑商品回显)
        goodsVO.setEditNum(goods.getPurchaseLimit());
        //计算所需价格和积分
        Price price = getPrice( goods.getId());
        if(null != price){
            //在秒杀活动时间段内
            goodsVO.setSellingPrice(price.getCash());
            goodsVO.setIntegral(price.getPoint());
            goodsVO.setStartTime(price.getStartTime());
            goodsVO.setEndTime(price.getEndTime());
        }
        //已售数量
        Integer data = orderClient.getGoodsSaleNum(goods.getId(), 1).getData();
        goodsVO.setSaleNum(data);
        //一个商品对应一个门店
        //查找门店
        GoodsShop goodsShop = goodsShopMapper.selectOne(new LambdaQueryWrapper<GoodsShop>()
                .eq(GoodsShop::getGoodsId, goodsId));
        Shop shop1 = shopMapper.selectById(goodsShop.getShopId());
        goodsVO.setShop(shop1);
        //已售数量
        Integer integer = orderClient.getGoodsSaleNum(goods.getId(), 1).getData();
        goodsVO.setSaleNum(integer);
        //分类id
        goodsVO.setGoodsCategoryId(goods.getGoodsCategoryId());
        //一个商品只有一个秒杀活动
        SeckillActivityInfo seckillActivityInfo = seckillActivityInfoService.getOne(new LambdaQueryWrapper<SeckillActivityInfo>()
                .eq(SeckillActivityInfo::getGoodId, goodsId)
                        .eq(SeckillActivityInfo::getIsShelves,1)
                .eq(SeckillActivityInfo::getDelFlag, 0));
        //商品是否开启秒杀活动
        goodsVO.setIsSkillActivity(0);
        if (seckillActivityInfo != null) {
            goodsVO.setIsSkillActivity(1);
            //活动限购数量
            goodsVO.setEditActivityNum(seckillActivityInfo.getMaxNum());
            GoodsSeckill one = goodsSeckillService.getOne(new LambdaQueryWrapper<GoodsSeckill>().eq(GoodsSeckill::getSeckillActivityInfoId, seckillActivityInfo.getId()));
            //有秒杀活动,查看秒杀价格
            goodsVO.setEditActivityPrice(one.getSellingPrice());
        }
        //商品评价
        GoodsEvaluate goodsEvaluateOne = goodsEvaluateMapper.getGoodsEvaluateOne(goods.getId());
        AppUser appUserById = appUserClient.getAppUserById(goodsEvaluateOne.getAppUserId());
        goodsEvaluateOne.setUserName(appUserById.getName());
        goodsEvaluateOne.setAvatar(appUserById.getAvatar());
        goodsVO.setGoodsEvaluate(goodsEvaluateOne);
        return goodsVO;
    }
    /**
     * 发布商品 门店后台-商品管理
     */
    @Override
    public Integer addGoodsByShop(AddGoodsDTO addGoodsDTO) {
        if(addGoodsDTO.getPurchaseLimit()==null){
            addGoodsDTO.setPurchaseLimit(-1);
        }
        Goods goods = new Goods();
        BeanUtils.copyProperties(addGoodsDTO, goods);
        goods.setSaleNum(0);//销量
        goods.setStatus(GoodsStatus.DOWN.getCode());//下架状态
        goods.setIntegral(getPoint(addGoodsDTO.getSellingPrice()));//积分
        goods.setDelFlag(0);
        goods.setCreateTime(LocalDateTime.now());
        goodsService.save(goods);//添加商品
        //保存商品门店关系
        GoodsShop goodsShop = new GoodsShop();
        goodsShop.setGoodsId(goods.getId());
        goodsShop.setShopId(addGoodsDTO.getShopId());
        Shop shop = shopMapper.selectById(addGoodsDTO.getShopId());
        if(shop==null){
            throw new ServiceException("门店不存在");
        }
        goodsShop.setShopName(shop.getName());
        goodsShop.setOwnerName(shop.getShopManager());
        goodsShop.setPhone(shop.getPhone());
        goodsShop.setAddress(shop.getAddress());
        goodsShopService.save(goodsShop);
        //判断是否参加秒杀活动
        if (addGoodsDTO.getIsActivity()==1){
            //秒杀活动
            SeckillActivityInfo seckillActivityInfo = new SeckillActivityInfo();
            seckillActivityInfo.setDelFlag(0);
            seckillActivityInfo.setCreateTime(LocalDateTime.now());
            seckillActivityInfo.setGoodId(goods.getId());
            seckillActivityInfo.setMaxNum(addGoodsDTO.getMaxNum());
            seckillActivityInfo.setStartTime(addGoodsDTO.getStartTime());
            seckillActivityInfo.setEndTime(addGoodsDTO.getEndTime());
            seckillActivityInfo.setIsShelves(1);//默认上架
            seckillActivityInfoService.save(seckillActivityInfo);
            //秒杀活动价格
            GoodsSeckill goodsSeckill = new GoodsSeckill();
            goodsSeckill.setSellingPrice(addGoodsDTO.getActivityPrice());
            goodsSeckill.setIntegral(getPoint(addGoodsDTO.getActivityPrice()));
            goodsSeckill.setSeckillActivityInfoId(seckillActivityInfo.getId());
            goodsSeckillService.save(goodsSeckill);
        }
        return goods.getId();
    }
    /**
     * 编辑商品
     * @param addGoodsDTO
     * @return
     */
    @Override
    public Integer editGoodsByShop(AddGoodsDTO addGoodsDTO) {
        if(addGoodsDTO.getPurchaseLimit()==null){
            addGoodsDTO.setPurchaseLimit(-1);
        }
        //先修改商品
        Goods goods = new Goods();
        BeanUtils.copyProperties(addGoodsDTO, goods);
        goods.setStatus(GoodsStatus.DOWN.getCode());//下架状态
        goods.setId(addGoodsDTO.getGoodId());
        goods.setIntegral(getPoint(addGoodsDTO.getSellingPrice()));//积分
        goods.setDelFlag(0);
        goods.setCreateTime(LocalDateTime.now());
        goodsService.updateById(goods);//添加商品
        //门店关系不变
        //判断是否参加秒杀活动
        if (addGoodsDTO.getIsActivity()==1){//参加
            //一个商品只有一个秒杀活动
            SeckillActivityInfo seckillActivityInfo = seckillActivityInfoService.getOne(new LambdaQueryWrapper<SeckillActivityInfo>()
                    .eq(SeckillActivityInfo::getGoodId, addGoodsDTO.getGoodId())
                    .eq(SeckillActivityInfo::getDelFlag, 0));
            if (seckillActivityInfo != null) {
                //删除原本活动
                goodsSeckillService.remove(new LambdaQueryWrapper<GoodsSeckill>().eq(GoodsSeckill::getSeckillActivityInfoId, seckillActivityInfo.getId()));
                //删除主表
                seckillActivityInfoService.removeById(seckillActivityInfo.getId());
            }
            //新增
            //秒杀活动
            SeckillActivityInfo seckillActivityInfo1 = new SeckillActivityInfo();
            seckillActivityInfo1.setDelFlag(0);
            seckillActivityInfo1.setCreateTime(LocalDateTime.now());
            seckillActivityInfo1.setGoodId(goods.getId());
            seckillActivityInfo1.setMaxNum(addGoodsDTO.getMaxNum());
            seckillActivityInfo1.setStartTime(addGoodsDTO.getStartTime());
            seckillActivityInfo1.setEndTime(addGoodsDTO.getEndTime());
            seckillActivityInfo1.setIsShelves(1);//默认上架
            seckillActivityInfoService.save(seckillActivityInfo1);
            //秒杀活动价格
            GoodsSeckill goodsSeckill = new GoodsSeckill();
            goodsSeckill.setSellingPrice(addGoodsDTO.getActivityPrice());
            goodsSeckill.setIntegral(getPoint(addGoodsDTO.getActivityPrice()));
            goodsSeckill.setSeckillActivityInfoId(seckillActivityInfo1.getId());
            goodsSeckillService.save(goodsSeckill);
        }else{
            //不参加秒杀活动,删除之前的活动
            //一个商品只有一个秒杀活动
            SeckillActivityInfo seckillActivityInfo = seckillActivityInfoService.getOne(new LambdaQueryWrapper<SeckillActivityInfo>()
                    .eq(SeckillActivityInfo::getGoodId, addGoodsDTO.getGoodId())
                    .eq(SeckillActivityInfo::getDelFlag, 0));
            if (seckillActivityInfo != null) {
                //删除原本活动
                goodsSeckillService.remove(new LambdaQueryWrapper<GoodsSeckill>().eq(GoodsSeckill::getSeckillActivityInfoId, seckillActivityInfo.getId()));
                //删除主表
                seckillActivityInfoService.removeById(seckillActivityInfo.getId());
            }
        }
        return goods.getId();
    }
    @Override
    public PageInfo<ShopBalanceListVO> getBalanceList(String name, Integer pageCurr, Integer pageSize) {
        PageInfo<ShopBalanceListVO> pageInfo = new PageInfo<>(pageCurr, pageSize);
        List<ShopBalanceListVO> list = shopMapper.getBalanceList(pageInfo,name);
        pageInfo.setRecords(list);
        return pageInfo;
    }
    /**
     * 获取商品当前的价格,就是看当前商品是否在秒杀活动中
     */
    public Price getPrice( Integer goodsId){
        //判断是否有在秒杀活动时间中
        Price price = new Price();
        SeckillActivityInfo one = seckillActivityInfoService.getOne(new LambdaQueryWrapper<SeckillActivityInfo>().eq(SeckillActivityInfo::getGoodId, goodsId)
                .eq(SeckillActivityInfo::getIsShelves, 1).eq(SeckillActivityInfo::getDelFlag, 0)
                .last(" and now() between start_time and end_time order by create_time desc limit 0, 1"));
        GoodsSeckill goodsSeckill = null;//秒杀配置
        if(null != one){
            //有秒杀活动,查看秒杀价格
            goodsSeckill = goodsSeckillService.getOne(new LambdaQueryWrapper<GoodsSeckill>().eq(GoodsSeckill::getSeckillActivityInfoId, one.getId()));
        }
        //没有秒杀活动或者添加的普通商品则使用秒杀活动价格
        if(null == goodsSeckill ){
            return null;
        }
        //秒杀活动价格
        price.setCash(goodsSeckill.getSellingPrice());
        //计算对应积分
        price.setPoint(getPoint(price.getCash()));
        price.setStartTime(one.getStartTime());
        price.setEndTime(one.getEndTime());
        price.setPurchaseLimit(one.getMaxNum());
        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);
        }
    }
}