ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java
@@ -23,7 +23,6 @@ public AppUserClient create(Throwable cause) { return new AppUserClient() { @PostMapping("/appUser/getAppUserById") @Override public AppUser getAppUserById(Long id) { log.error("根据id获取用户失败:{}", cause.getMessage()); ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/GoodsEvaluate.java
@@ -70,4 +70,14 @@ private LocalDateTime createTime; @ApiModelProperty(value = "头像") @TableField(exist = false) private String avatar; @ApiModelProperty(value = "名字") @TableField(exist = false) private String userName; } ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/PointSetting.java
@@ -105,7 +105,7 @@ @ApiModelProperty(value = "门店业绩积分") @TableField("shop_point") private BigDecimal shopPoint; private Integer shopPoint; @ApiModelProperty(value = "门店业绩积分 1开0关") @TableField("shop_point_open") @@ -129,7 +129,7 @@ @ApiModelProperty(value = "拉新人积分") @TableField("get_new_point") private BigDecimal getNewPoint; private Integer getNewPoint; @ApiModelProperty(value = "拉新人积分 1开0关") @TableField("get_new_point_open") ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/PhoneNumberValidator.java
New file @@ -0,0 +1,28 @@ package com.ruoyi.common.core.utils; public class PhoneNumberValidator { // 定义一个匹配中国手机号的正则表达式 private static final String CHINA_PHONE_REGEX = "^1[3-9]\\d{9}$"; /** * 验证给定的字符串是否符合中国手机号的格式. * * @param phoneNumber 要验证的手机号 * @return 如果手机号格式正确返回true,否则返回false */ public static boolean isValidChinaPhoneNumber(String phoneNumber) { if (phoneNumber == null || phoneNumber.isEmpty()) { return false; } return phoneNumber.matches(CHINA_PHONE_REGEX); } public static void main(String[] args) { // 测试几个号码 String[] phoneNumbers = {"13800138000", "15912345678", "18612345678", "110", "12345678901", "19912345678"}; for (String phoneNumber : phoneNumbers) { System.out.println("Phone number: " + phoneNumber + " is valid: " + isValidChinaPhoneNumber(phoneNumber)); } } } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java
@@ -12,12 +12,11 @@ import com.ruoyi.common.security.service.TokenService; import com.ruoyi.other.api.domain.Shop; import com.ruoyi.other.api.feignClient.StoreClient; import io.swagger.annotations.*; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import javax.annotation.Resource; import java.util.List; @@ -25,8 +24,6 @@ import com.ruoyi.account.vo.*; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.page.TableDataInfo; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import org.springframework.web.bind.annotation.*; /** @@ -178,7 +175,7 @@ @ResponseBody @PostMapping("/recommend") @GetMapping("/recommend") @ApiOperation(value = "推广中心", tags = {"小程序-推广中心"}) public R<AppUser> recommend(){ Long userId = tokenService.getLoginUserApplet().getUserid(); @@ -221,6 +218,18 @@ return R.ok(user); } @ResponseBody @GetMapping("/change") @ApiOperation(value = "推广中心", tags = {"小程序-推广中心"}) public R<AppUser> change(@ApiParam("换绑用户id") Long userId){ Long userId1 = tokenService.getLoginUserApplet().getUserid(); //获取绑定门店 AppUser user = appUserService.getById(userId1); user.setInviteUserId(userId); appUserService.updateById(user); return R.ok(); } @GetMapping("/index") ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/UserPointController.java
@@ -1,10 +1,7 @@ package com.ruoyi.account.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.account.api.model.UserPoint; import com.ruoyi.account.service.AppUserService; import com.ruoyi.account.service.UserPointService; import com.ruoyi.account.vo.UserPointDetailVO; import com.ruoyi.account.vo.UserPointVO; @@ -40,8 +37,6 @@ public class UserPointController extends BaseController { @Resource private UserPointService userPointService; @Resource private AppUserService appUserService; /** @@ -86,15 +81,8 @@ */ @PostMapping("/transferPoint") @ApiOperation("转赠积分") public R<Void> transferPoint(@ApiParam("积分") BigDecimal point, @ApiParam("手机号") Long phone) { AppUser appUser = appUserService.getOne(new LambdaQueryWrapper<AppUser>() .eq(AppUser::getPhone, phone)); if (null == appUser) { return R.fail("用户不存在"); } public R<Void> transferPoint(@ApiParam("积分") @RequestParam BigDecimal point, @ApiParam("手机号") @RequestParam String phone) { userPointService.transferPoint(point, phone); return R.ok(); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/VipCenter.java
New file @@ -0,0 +1,14 @@ package com.ruoyi.account.controller; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/vipCenter") @Api(tags = "小程序-会员中心") public class VipCenter { } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/PointSettingService.java
New file @@ -0,0 +1,8 @@ package com.ruoyi.account.service; import com.ruoyi.other.api.domain.PointSetting; public interface PointSettingService { PointSetting getPointSettingByAppUserId(Long appUserId); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/UserPointService.java
@@ -24,5 +24,5 @@ List<UserPointDetailVO> getUserPointDetail(Long userId, LocalDateTime startTime, LocalDateTime endTime, Integer type); void transferPoint(BigDecimal point, Long phone); void transferPoint(BigDecimal point, String phone); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/PointSettingServiceImpl.java
New file @@ -0,0 +1,29 @@ package com.ruoyi.account.service.impl; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.account.service.AppUserService; import com.ruoyi.account.service.PointSettingService; import com.ruoyi.common.core.domain.R; import com.ruoyi.other.api.domain.PointSetting; import com.ruoyi.other.api.feignClient.PointSettingClient; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class PointSettingServiceImpl implements PointSettingService { @Resource private PointSettingClient pointSettingClient; @Resource private AppUserService appUserService; @Override public PointSetting getPointSettingByAppUserId(Long appUserId) { AppUser appUser = appUserService.getById(appUserId); R<PointSetting> r = pointSettingClient.getPointSetting(appUser.getVipId()); if (!R.isSuccess(r)){ throw new RuntimeException("获取积分设置失败"); } return r.getData(); } } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserPointServiceImpl.java
@@ -3,19 +3,25 @@ import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.account.api.model.BalanceChangeRecord; import com.ruoyi.account.api.model.UserPoint; import com.ruoyi.account.enums.PointChangeType; import com.ruoyi.account.mapper.UserPointMapper; import com.ruoyi.account.service.AppUserService; import com.ruoyi.account.service.PointSettingService; import com.ruoyi.account.service.UserPointService; import com.ruoyi.account.service.VipSettingService; import com.ruoyi.account.vo.UserPointDetailVO; import com.ruoyi.account.vo.UserPointVO; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.PhoneNumberValidator; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.other.api.domain.PointSetting; import com.ruoyi.other.api.domain.VipSetting; import com.ruoyi.other.api.feignClient.RemoteVipSettingClient; import com.ruoyi.system.api.model.LoginUser; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; @@ -23,6 +29,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; /** @@ -34,25 +41,26 @@ * @since 2024-11-21 */ @Service @Slf4j public class UserPointServiceImpl extends ServiceImpl<UserPointMapper, UserPoint> implements UserPointService { @Resource private AppUserClient appUserClient; private AppUserService appUserService; @Resource private RemoteVipSettingClient remoteVipSettingClient; private TokenService tokenService; @Resource private VipSettingService vipSettingService; @Resource private PointSettingService pointSettingService; @Override public UserPointVO getUserPoint(Long userId) { AppUser appUser = appUserClient.getAppUserById(userId); AppUser appUser = appUserService.getById(userId); List<UserPoint> userPointList = list(new LambdaQueryWrapper<UserPoint>() .eq(UserPoint::getAppUserId, userId)); Map<Integer, Integer> userBalanceMap = userPointList.stream() .collect(Collectors.toMap(UserPoint::getType, UserPoint::getBalance)); R<VipSetting> r = remoteVipSettingClient.getVipSettingById(appUser.getVipId()); if (!R.isSuccess(r)){ throw new RuntimeException("会员等级获取失败"); } VipSetting vipSetting = vipSettingService.getVipSettingByUserId(userId); Integer lavePoint = appUser.getLavePoint(); UserPointVO userPointVO = new UserPointVO(); @@ -63,7 +71,7 @@ userPointVO.setPullNewPoint(userBalanceMap.get(PointChangeType.NEW_USER_REFERRAL.getCode())); userPointVO.setShopAchievementPoint(userBalanceMap.get(PointChangeType.STORE_PERFORMANCE.getCode())); userPointVO.setShopSharePoint(userBalanceMap.get(PointChangeType.STORE_COMMISSION_RETURN.getCode())); userPointVO.setGiftPoint(r.getData().getVipGiftRole()); userPointVO.setGiftPoint(vipSetting.getVipGiftRole()); return userPointVO; } @@ -87,8 +95,66 @@ @Override public void transferPoint(BigDecimal point, Long phone) { AppUser appUser = appUserService.getOne(new LambdaQueryWrapper<AppUser>() @Transactional public void transferPoint(BigDecimal point, String phone) { if (!PhoneNumberValidator.isValidChinaPhoneNumber(phone)) { throw new ServiceException("无效的电话号码"); } LoginUser loginUserApplet = tokenService.getLoginUserApplet(); Long userid = loginUserApplet.getUserid(); VipSetting vipSetting = vipSettingService.getVipSettingByUserId(userid); if (vipSetting == null) { throw new ServiceException("VIP 设置未找到"); } if (vipSetting.getVipGiftRole() == 0) { throw new ServiceException("转赠积分权限未开启"); } AppUser appUser = appUserService.getById(userid); if (appUser == null) { throw new ServiceException("用户未找到"); } Integer totalPoint = appUser.getLavePoint(); PointSetting pointSetting = pointSettingService.getPointSettingByAppUserId(userid); if (pointSetting == null) { throw new ServiceException("积分设置未找到"); } Integer buyPointOpen = pointSetting.getBuyPointOpen(); List<UserPoint> userPointList = list(new LambdaQueryWrapper<UserPoint>() .eq(UserPoint::getAppUserId, userid)); Map<Integer, Integer> userBalanceMap = userPointList.stream() .collect(Collectors.toMap(UserPoint::getType, UserPoint::getBalance)); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.CONSUME.getCode(), buyPointOpen == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.COMMISSION_RETURN.getCode(), pointSetting.getSharePointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.STORE_COMMISSION_RETURN.getCode(), pointSetting.getShopSharePointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.STORE_PERFORMANCE.getCode(), pointSetting.getShopPointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.TECHNICIAN_PERFORMANCE.getCode(), pointSetting.getPersonPointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.NEW_USER_REFERRAL.getCode(), pointSetting.getGetNewPointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.REGISTRATION.getCode(), pointSetting.getGetRegisPointOpen() == 0); totalPoint -= getAdjustedPoint(userBalanceMap, PointChangeType.WORK_PERFORMANCE.getCode(), pointSetting.getWorkPointOpen() == 0); if (point.compareTo(new BigDecimal(totalPoint)) > 0) { throw new ServiceException("转赠积分不足"); } AppUser appUserForPhoe = appUserService.getOne(new LambdaQueryWrapper<AppUser>() .eq(AppUser::getPhone, phone)); if (appUserForPhoe == null) { throw new ServiceException("目标用户未找到"); } appUserForPhoe.setLavePoint(appUserForPhoe.getLavePoint() + point.intValue()); appUserService.updateById(appUserForPhoe); log.info("积分转赠完成,用户ID: {}, 新积分: {}", appUserForPhoe.getId(), appUserForPhoe.getLavePoint()); } private int getAdjustedPoint(Map<Integer, Integer> userBalanceMap, int pointTypeCode, boolean isOpen) { return isOpen ? 0 : Optional.ofNullable(userBalanceMap.get(pointTypeCode)).orElse(0); } } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/vo/vip/Describe.java
New file @@ -0,0 +1,10 @@ package com.ruoyi.account.vo.vip; import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.annotations.ApiModelProperty; public class Describe { @ApiModelProperty(value = "会员专属权益") private String vipInfo; } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/vo/vip/Level.java
New file @@ -0,0 +1,11 @@ package com.ruoyi.account.vo.vip; public class Level { /** * 会员名称 */ private String name; } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/OrderController.java
@@ -7,13 +7,10 @@ import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.order.service.OrderService; import io.swagger.annotations.*; import org.springframework.web.bind.annotation.*; import com.ruoyi.order.vo.OrderDetailVO; import com.ruoyi.system.api.model.LoginUser; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import com.ruoyi.order.model.Order; import javax.annotation.Resource; @@ -44,8 +41,8 @@ @ApiImplicitParams({ @ApiImplicitParam(value = "订单状态", name = "status", required = true, dataType = "int"), }) @GetMapping("/getMyOrderList/{status}") public TableDataInfo getMyOrderList(@PathVariable("status") Integer status){ @GetMapping("/getMyOrderList") public TableDataInfo getMyOrderList(@ApiParam("订单状态") Integer status){ startPage(); LoginUser loginUserApplet = tokenService.getLoginUserApplet(); return getDataTable(orderService.selectOrderListByUserId(status, loginUserApplet.getUserid())); ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/OrderMapper.java
@@ -3,12 +3,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.order.vo.OrderVO; import com.ruoyi.order.model.Order; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> * Mapper 接口 * Mapper 接口 * </p> * * @author luodangjia @@ -18,5 +19,5 @@ /** * 查询用户id */ List<OrderVO> selectOrderListByUserId(Integer status, Long userId); List<OrderVO> selectOrderListByUserId(@Param("status") Integer status, @Param("userId") Long userId); } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/ShoppingCartServiceImpl.java
@@ -819,10 +819,18 @@ if(2 == shoppingCartPayment.getPaymentType()){ BigDecimal balance = appUser.getBalance(); if(balance.compareTo(paymentMoney.add(expressFee)) < 0){ if(balance.compareTo(paymentMoney) < 0){ return R.fail("账户余额不足"); } } //判断运费支付是否足够 if(2 == shoppingCartPayment.getFreightPaymentType() && expressFee.compareTo(BigDecimal.ZERO) > 0){ BigDecimal balance = appUser.getBalance(); if(balance.compareTo(expressFee) < 0){ return R.fail("账户余额不足"); } } orderService.save(order); //构建订单明细数据 for (MyShoppingCartVo myShoppingCartVo : goodsList) { @@ -960,11 +968,64 @@ userPoint.setObjectId(order.getId()); userPointClient.saveUserPoint(userPoint); } //修改订支付状态 order.setPayStatus(2); orderService.updateById(order); //删除购物车数据 this.removeBatchByIds(ids); //如果有运费,需要先扣除账户积分,再进行支付。支付成功后修改订单状态,未支付成功则回退积分,删除的订单 if(expressFee.compareTo(BigDecimal.ZERO) > 0){ if(shoppingCartPayment.getFreightPaymentType() == 1){ //调起微信支付 } if(shoppingCartPayment.getFreightPaymentType() == 2){ BigDecimal totalRedPacketAmount = appUser.getTotalRedPacketAmount(); BigDecimal totalDistributionAmount = appUser.getTotalDistributionAmount(); BigDecimal balance = appUser.getBalance(); if(expressFee.compareTo(totalRedPacketAmount) <= 0){ totalRedPacketAmount = totalRedPacketAmount.subtract(expressFee); balance = balance.subtract(expressFee); appUser.setTotalRedPacketAmount(totalRedPacketAmount); appUser.setBalance(balance); }else{ expressFee = expressFee.subtract(totalRedPacketAmount); totalRedPacketAmount = BigDecimal.ZERO; if(expressFee.compareTo(totalDistributionAmount) <= 0){ totalDistributionAmount = totalDistributionAmount.subtract(expressFee); balance = balance.subtract(expressFee); appUser.setTotalRedPacketAmount(totalRedPacketAmount); appUser.setTotalDistributionAmount(totalDistributionAmount); appUser.setBalance(balance); }else{ expressFee = expressFee.subtract(totalDistributionAmount); totalDistributionAmount = BigDecimal.ZERO; balance = balance.subtract(expressFee); appUser.setTotalRedPacketAmount(totalRedPacketAmount); appUser.setTotalDistributionAmount(totalDistributionAmount); appUser.setBalance(balance); } } appUserClient.editAppUserById(appUser); //构建余额明细变动记录 BalanceChangeRecord balanceChangeRecord = new BalanceChangeRecord(); balanceChangeRecord.setAppUserId(appUser.getId()); balanceChangeRecord.setOrderId(order.getId()); balanceChangeRecord.setChangeType(5); balanceChangeRecord.setBeforeAmount(balance.add(paymentMoney)); balanceChangeRecord.setChangeAmount(paymentMoney); balanceChangeRecord.setAfterAmount(balance); balanceChangeRecord.setDelFlag(0); balanceChangeRecord.setCreateTime(LocalDateTime.now()); balanceChangeRecordClient.saveBalanceChangeRecord(balanceChangeRecord); //修改订支付状态 order.setPayStatus(2); orderService.updateById(order); //删除购物车数据 this.removeBatchByIds(ids); } }else{ //修改订支付状态 order.setPayStatus(2); orderService.updateById(order); //删除购物车数据 this.removeBatchByIds(ids); } } return R.ok(); } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/ShoppingCartPayment.java
@@ -15,6 +15,8 @@ private String goodsJson; @ApiModelProperty(value = "支付方式(1=微信,2=账户余额,3=积分)", required = true) private Integer paymentType; @ApiModelProperty(value = "运费支付方式(1=微信,2=账户余额)", required = true) private Integer freightPaymentType; @ApiModelProperty(value = "核销门店id", required = true) private Integer shopId; @ApiModelProperty(value = "优惠券id", required = false) ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml
@@ -28,9 +28,11 @@ o.id, o.order_number, o.order_status, o.good_name, o.good_pics, o.num, o.point, o.payment_amount, o.create_time o.payment_amount ORDER BY o.create_time DESC </select> ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/GoodsEvaluateController.java
@@ -1,8 +1,21 @@ package com.ruoyi.other.controller; import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.other.api.domain.Goods; import com.ruoyi.other.api.domain.GoodsEvaluate; import com.ruoyi.other.service.GoodsEvaluateService; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; /** * <p> @@ -15,6 +28,22 @@ @RestController @RequestMapping("/goods-evaluate") public class GoodsEvaluateController { @Resource private GoodsEvaluateService goodsEvaluateService; @Resource private AppUserClient appUserClient; @GetMapping("/goodsList") @ApiOperation(value = "商品评价", tags = {"小程序-商品评价"}) public R<List<GoodsEvaluate>> goodsList(@ApiParam("商品id") Integer goodsId){ List<GoodsEvaluate> list = goodsEvaluateService.lambdaQuery().eq(GoodsEvaluate::getGoodsId, goodsId).list(); for (GoodsEvaluate goodsEvaluate : list) { AppUser appUserById = appUserClient.getAppUserById(goodsEvaluate.getAppUserId()); goodsEvaluate.setUserName(appUserById.getName()); goodsEvaluate.setAvatar(appUserById.getAvatar()); } return R.ok(list); } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/TechnicianSubscribeVO.java
@@ -54,4 +54,10 @@ */ @ApiModelProperty(value = "预约状态:0=待服务,1=已服务,2=已取消 4 已到期") private Integer status; @ApiModelProperty(value = "经度") private String longitude; @ApiModelProperty(value = "纬度") private String latitude; } ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TechnicianSubscribeMapper.xml
@@ -31,6 +31,8 @@ ts.`name` shopName, ts.address shopAddress, tt.name technicianName, ts.longitude, ts.latitude, tts.subscribe_time, tts.service_mode, CASE