From 34f741f39e22bf48df33321230380b40c23110c3 Mon Sep 17 00:00:00 2001
From: huliguo <2023611923@qq.com>
Date: 星期五, 18 四月 2025 21:34:13 +0800
Subject: [PATCH] 店铺、积分、订单
---
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java | 442 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 398 insertions(+), 44 deletions(-)
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java
index 8a43b04..ac388e0 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.other.service.impl;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -8,24 +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.ServletUtils;
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.common.security.utils.SecurityUtils;
-import com.ruoyi.other.api.domain.Shop;
-import com.ruoyi.other.mapper.ShopMapper;
-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;
/**
@@ -41,13 +48,42 @@
@Resource
private ShopMapper shopMapper;
@Resource
+ private GoodsService goodsService;
+ @Resource
+ private PhoneMapper phoneMapper;
+ @Resource
+ private ShopScoreService shopScoreService;
+ @Resource
private AppUserClient appUserClient;
@Resource
private TokenService tokenService;
@Resource
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;
+ /**
+ * 获取门店列表
+ * @param PageNum
+ * @param pageSize
+ * @param shop
+ * @return
+ */
@Override
public IPage<Shop> getShopList(Integer PageNum, Integer pageSize, Shop shop) {
Page<Shop> page = new Page<>();
@@ -56,52 +92,33 @@
return shopMapper.selectShopList(page, shop);
}
- @Override
- public List<NearbyShopVO> nearbyShopList(BigDecimal longitude, BigDecimal latitude) {
- String token = SecurityUtils.getToken(ServletUtils.getRequest());
- AppUser appUser = null;
- if(StringUtils.isNotEmpty(token)){
- Long userid = tokenService.getLoginUserApplet().getUserid();
- appUser = appUserClient.getAppUserById(userid);
- }
- List<NearbyShopVO> nearbyShopVOS = shopMapper.selectNearbyShopList();
+ /**
+ * 获取最近的门店
+ * @param longitude
+ * @param latitude
+ * @return
+ */
+ @Override
+ public List<NearbyShopVO> nearbyShopList(BigDecimal longitude, BigDecimal latitude,Shop shop) {
+ //获取所有店
+ List<NearbyShopVO> nearbyShopVOS = shopMapper.selectNearbyShopList(shop);
+ if (nearbyShopVOS == null || nearbyShopVOS.isEmpty()) {
+ return Collections.emptyList();
+ }
+ //计算距离
for (NearbyShopVO nearbyShopVO : nearbyShopVOS) {
Double wgs84 = GeodesyUtil.getDistance(nearbyShopVO.getLongitude() + "," + nearbyShopVO.getLatitude(), longitude + "," + latitude).get("WGS84");
nearbyShopVO.setDistance(new BigDecimal(wgs84).setScale(2, RoundingMode.HALF_EVEN).doubleValue());
}
+ /*//排序
nearbyShopVOS.sort(new Comparator<NearbyShopVO>() {
@Override
public int compare(NearbyShopVO o1, NearbyShopVO o2) {
return o1.getDistance().compareTo(o2.getDistance());
}
- });
+ });*/
- if(null != appUser && null != appUser.getShopId()){
- AppUser finalAppUser = appUser;
- Optional<NearbyShopVO> first = nearbyShopVOS.stream().filter(s -> s.getId().equals(finalAppUser.getShopId().longValue())).findFirst();
- if(first.isPresent()){
- NearbyShopVO nearbyShopVO = first.get();
- if(null != nearbyShopVO){
- nearbyShopVOS.remove(nearbyShopVO);
- }
- }
-
- Shop shop = shopMapper.selectById(appUser.getShopId());
- if(null != shop && shop.getDelFlag() == 0 && shop.getStatus() == 1){
- NearbyShopVO vo = new NearbyShopVO();
- vo.setId(appUser.getShopId().longValue());
- vo.setName(shop.getName());
- vo.setAddress(shop.getAddress());
- vo.setHomePicture(shop.getHomePicture());
- Double wgs84 = GeodesyUtil.getDistance(longitude.toString() + "," + latitude.toString(), shop.getLongitude() + "," + shop.getLatitude()).get("WGS84");
- vo.setDistance(new BigDecimal(wgs84).setScale(2, RoundingMode.HALF_EVEN).doubleValue());
- nearbyShopVOS.add(0, vo);
- }
- }
- if (nearbyShopVOS == null || nearbyShopVOS.isEmpty()) {
- return Collections.emptyList();
- }
return sortByDistance(nearbyShopVOS);
}
@@ -122,9 +139,28 @@
if (shopDetailVO == null) {
throw new ServiceException("查询店铺不存在");
}
+ //查询客服电话
+ Phone phone = phoneMapper.selectOne(new LambdaQueryWrapper<Phone>().eq(Phone::getShopId, shopDetailVO.getId()));
+ ArrayList<String> phones = new ArrayList<>();
+ if (phone != null) {
+ if (phone.getPhoneOne() != null) {
+ phones.add(phone.getPhoneOne());
+ }
+ if (phone.getPhoneTwo() != null) {
+ phones.add(phone.getPhoneTwo());
+ }
+ }
+ shopDetailVO.setPhones(phones);
+
+ //我的评分
+ if (userid != null){
+ ShopScore one = shopScoreService.getOne(new LambdaQueryWrapper<ShopScore>().eq(ShopScore::getAppUserId, userid).eq(ShopScore::getShopId, shopId).last(" order by create_time desc limit 0, 1"));
+ shopDetailVO.setMyScore(null == one ? BigDecimal.ZERO : one.getScore());
+ }
// 计算距离
- 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);
@@ -133,6 +169,8 @@
}
return shopDetailVO;
}
+
+
@Override
public Boolean cheUserByPhone(String phone) {
@@ -161,4 +199,320 @@
this.updateById(shop);
}
}
+
+ /**
+ * 门店余额统计
+ * @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) {
+ 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::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());
+ }
+
+ 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());
+ 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();
+ }
+
+ /**
+ * 获取商品当前的价格,就是看当前商品是否在秒杀活动中
+ */
+ 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);
+ }
+
+ }
}
--
Gitblit v1.7.1