This commit is contained in:
2025-12-09 18:41:30 +08:00
parent 82efd1886f
commit 76b93cf8b2
93 changed files with 2131 additions and 3112 deletions

View File

@@ -1,16 +0,0 @@
package com.czg.service.account.mapper;
import com.czg.account.entity.MemberPointsLog;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 会员积分变动记录
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Mapper
public interface MemberPointsLogMapper extends BaseMapper<MemberPointsLog> {
}

View File

@@ -1,16 +0,0 @@
package com.czg.service.account.mapper;
import com.czg.account.entity.MemberPoints;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 会员积分
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Mapper
public interface MemberPointsMapper extends BaseMapper<MemberPoints> {
}

View File

@@ -1,16 +0,0 @@
package com.czg.service.account.mapper;
import com.czg.account.entity.PointsBasicSetting;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 积分基本设置 映射层。
*
* @author ww
* @since 2025-02-20
*/
@Mapper
public interface PointsBasicSettingMapper extends BaseMapper<PointsBasicSetting> {
}

View File

@@ -1,19 +0,0 @@
package com.czg.service.account.mapper;
import com.czg.account.entity.PointsExchangeRecord;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 积分兑换记录
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Mapper
public interface PointsExchangeRecordMapper extends BaseMapper<PointsExchangeRecord> {
/**
* 自动取消兑换订单
*/
int authCancel();
}

View File

@@ -1,16 +0,0 @@
package com.czg.service.account.mapper;
import com.czg.account.entity.PointsGoodsSetting;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 积分商品设置
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Mapper
public interface PointsGoodsSettingMapper extends BaseMapper<PointsGoodsSetting> {
}

View File

@@ -1,119 +0,0 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.account.dto.points.MemberPointsLogDTO;
import com.czg.account.entity.MemberPointsLog;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.MemberPointsLogService;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.account.vo.PointsShopListVO;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.MemberPointsLogMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static com.czg.account.entity.table.MemberPointsLogTableDef.MEMBER_POINTS_LOG;
import static com.czg.account.entity.table.MemberPointsTableDef.MEMBER_POINTS;
import static com.czg.account.entity.table.ShopUserTableDef.SHOP_USER;
/**
* 会员积分变动记录
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Service
public class MemberPointsLogServiceImpl extends ServiceImpl<MemberPointsLogMapper, MemberPointsLog> implements MemberPointsLogService {
@Resource
private ShopUserService shopUserService;
@Resource
private ShopInfoService shopInfoService;
private QueryWrapper buildQueryWrapper(MemberPointsLogDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
if (ObjUtil.isNotNull(param.getUserId())) {
queryWrapper.eq(MemberPointsLog::getShopUserId, param.getUserId());
}
if (StrUtil.isNotBlank(param.getNickName())) {
queryWrapper.like(ShopUser::getNickName, param.getNickName());
}
if (StrUtil.isNotBlank(param.getPhone())) {
queryWrapper.like(ShopUser::getPhone, param.getPhone());
}
if (StrUtil.isNotBlank(param.getContent())) {
queryWrapper.like(MemberPointsLog::getContent, param.getContent());
}
if (StrUtil.isNotBlank(param.getFloatType())) {
queryWrapper.eq(MemberPointsLog::getFloatType, param.getFloatType());
}
if (StrUtil.isNotBlank(param.getOrderNo())) {
queryWrapper.eq(MemberPointsLog::getOrderNo, param.getOrderNo());
}
if (StrUtil.isNotEmpty(param.getBeginDate())) {
queryWrapper.ge(MemberPointsLog::getCreateTime, param.getBeginDate() + " 00:00:00");
}
if (StrUtil.isNotEmpty(param.getEndDate())) {
queryWrapper.le(MemberPointsLog::getCreateTime, param.getEndDate() + " 23:59:59");
}
Long shopId = StpKit.USER.getShopId(0L);
queryWrapper.eq(MemberPointsLog::getShopId, shopId);
queryWrapper.orderBy(MemberPointsLog::getId, false);
return queryWrapper;
}
private QueryWrapper buildFullQueryWrapper(MemberPointsLogDTO param) {
QueryWrapper queryWrapper = buildQueryWrapper(param);
queryWrapper.select(MEMBER_POINTS.DEFAULT_COLUMNS)
.select(SHOP_USER.NICK_NAME.as(MemberPointsLogDTO::getNickName), SHOP_USER.HEAD_IMG.as(MemberPointsLogDTO::getHeadImg), SHOP_USER.PHONE.as(MemberPointsLogDTO::getPhone))
.from(MEMBER_POINTS_LOG)
.leftJoin(SHOP_USER).on(SHOP_USER.ID.eq(MEMBER_POINTS.SHOP_USER_ID));
return queryWrapper;
}
@Override
public Page<MemberPointsLogDTO> getMemberPointsLogPage(MemberPointsLogDTO param) {
QueryWrapper queryWrapper = buildFullQueryWrapper(param);
return super.pageAs(PageUtil.buildPage(), queryWrapper, MemberPointsLogDTO.class);
}
@Override
public List<PointsShopListVO> getList(long userId, String shopName) {
ArrayList<PointsShopListVO> pointsShopListVOS = new ArrayList<>();
List<ShopUser> shopUserList = shopUserService.list(new QueryWrapper().eq(ShopUser::getUserId, userId).gt(ShopUser::getAccountPoints, 0));
if (shopUserList.isEmpty()) {
return pointsShopListVOS;
}
Set<Long> shopIdList = shopUserList.stream().map(ShopUser::getSourceShopId).collect(Collectors.toSet());
QueryWrapper queryWrapper = new QueryWrapper().in(ShopInfo::getId, shopIdList);
if (StrUtil.isNotBlank(shopName)) {
queryWrapper.like(ShopInfo::getShopName, shopName);
}
Map<Long, ShopInfo> shopInfoMap = shopInfoService.list(queryWrapper).stream().collect(Collectors.toMap(ShopInfo::getId, item -> item));
for (ShopUser shopUser : shopUserList) {
ShopInfo shopInfo = shopInfoMap.get(shopUser.getSourceShopId());
if (shopInfo == null) {
continue;
}
pointsShopListVOS.add(new PointsShopListVO()
.setShopName(shopInfo.getShopName())
.setLogo(shopInfo.getLogo())
.setAccountPoints(shopUser.getAccountPoints())
.setShopId(shopInfo.getId()));
}
return pointsShopListVOS;
}
}

View File

@@ -1,291 +0,0 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.account.dto.points.OrderDeductionPointsDTO;
import com.czg.account.entity.MemberPoints;
import com.czg.account.entity.MemberPointsLog;
import com.czg.account.entity.PointsBasicSetting;
import com.czg.account.entity.ShopInfo;
import com.czg.account.enums.PointUserGroupEnum;
import com.czg.account.param.MemberPointsParam;
import com.czg.account.service.MemberPointsService;
import com.czg.account.service.ShopInfoService;
import com.czg.enums.YesNoEnum;
import com.czg.exception.CzgException;
import com.czg.order.entity.OrderInfo;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.MemberPointsLogMapper;
import com.czg.service.account.mapper.MemberPointsMapper;
import com.czg.service.account.mapper.PointsBasicSettingMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
/**
* 会员积分变动记录
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@DubboService
public class MemberPointsServiceImpl extends ServiceImpl<MemberPointsMapper, MemberPoints> implements MemberPointsService {
@Resource
private PointsBasicSettingMapper pointsBasicSettingMapper;
@Resource
private MemberPointsLogMapper memberPointsLogMapper;
@Resource
private ShopInfoService shopInfoService;
private QueryWrapper buildQueryWrapper(MemberPointsParam param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
if (StrUtil.isNotBlank(param.getNickName())) {
queryWrapper.like(MemberPoints::getNickName, param.getNickName());
}
if (StrUtil.isNotBlank(param.getPhone())) {
queryWrapper.like(MemberPoints::getPhone, param.getPhone());
}
Long shopId = StpKit.USER.getShopId();
ShopInfo byId = shopInfoService.getById(shopId);
if (byId == null) {
throw new CzgException("店铺不存在");
}
if (byId.getIsEnableVipSync().equals(1)) {
shopId = byId.getMainId();
}
queryWrapper.eq(MemberPoints::getSourceShopId, shopId);
queryWrapper.orderBy(MemberPoints::getShopUserId, false);
return queryWrapper;
}
@Override
public Page<MemberPoints> getMemberPointsPage(MemberPointsParam param) {
QueryWrapper queryWrapper = buildQueryWrapper(param);
return super.page(PageUtil.buildPage(), queryWrapper);
}
@Override
public MemberPoints initMemberPoints(Long shopUserId) {
MemberPoints entity = super.getOne(query().eq(MemberPoints::getShopUserId, shopUserId));
if (entity == null) {
throw new CzgException("会员信息不存在");
}
if (entity.getAccountPoints() == null) {
entity.setAccountPoints(0);
super.updateById(entity);
}
return entity;
}
@Override
public MemberPoints getMemberPoints(Long shopUserId) {
return initMemberPoints(shopUserId);
}
@Override
public OrderDeductionPointsDTO getMemberUsablePoints(Long shopUserId, BigDecimal orderAmount) {
MemberPoints entity = initMemberPoints(shopUserId);
Long shopId = entity.getMainShopId();
Integer accountPoints = entity.getAccountPoints();
OrderDeductionPointsDTO dto = new OrderDeductionPointsDTO();
dto.setAccountPoints(accountPoints);
dto.setUsable(false);
dto.setMaxDeductionAmount(BigDecimal.ZERO);
dto.setMinDeductionAmount(BigDecimal.ZERO);
PointsBasicSetting basic = pointsBasicSettingMapper.selectOneById(shopId);
if (basic == null) {
dto.setUnusableReason("商家未启用积分抵扣功能");
return dto;
}
if (basic.getEnableDeduction() == 0) {
dto.setUnusableReason("商家未启用积分抵扣功能");
return dto;
}
if (PointUserGroupEnum.VIP.value().equals(basic.getDeductionGroup()) && ObjectUtil.defaultIfNull(entity.getVip(), YesNoEnum.NO.value()) != YesNoEnum.YES.value()) {
dto.setUnusableReason("仅VIP用户可用");
return dto;
}
dto.setMinPaymentAmount(basic.getMinPaymentAmount());
dto.setOrderAmount(orderAmount);
if (NumberUtil.isLess(orderAmount, basic.getMinPaymentAmount())) {
dto.setUnusableReason(StrUtil.format("实付金额不足¥{}元,无法进行抵扣", basic.getMinPaymentAmount()));
return dto;
}
dto.setEquivalentPoints(basic.getEquivalentPoints());
// 最低抵扣积分 = 1元等值积分 = 1.0元
dto.setMinDeductionPoints(basic.getEquivalentPoints());
// 计算抵扣门槛=?元
dto.setMinDeductionAmount(BigDecimal.ONE);
if (accountPoints == 0 || accountPoints < dto.getMinDeductionPoints()) {
dto.setUnusableReason("积分不足或小于最低使用门槛" + dto.getMinDeductionPoints());
return dto;
}
if (basic.getEquivalentPoints() == 0) {
return dto;
}
// 下单抵扣积分比例 1元=?积分
Integer equivalentPoints = basic.getEquivalentPoints();
// 计算账户积分=?元
BigDecimal accountYuan = NumberUtil.div(accountPoints, equivalentPoints);
// 下单最高抵扣比例
BigDecimal maxDeductionRatio = basic.getMaxDeductionRatio();
// 计算订单最多可以抵扣多少元,向下取整
BigDecimal orderYuan = NumberUtil.roundDown(NumberUtil.mul(orderAmount, NumberUtil.div(maxDeductionRatio, new BigDecimal("100"))), 0);
// 积分余额足够
if (NumberUtil.isGreaterOrEqual(accountYuan, orderYuan)) {
dto.setMaxDeductionAmount(orderYuan);
} else {
dto.setMaxDeductionAmount(NumberUtil.roundDown(accountYuan, 0));
}
if (NumberUtil.isLess(dto.getMaxDeductionAmount(), BigDecimal.ONE)) {
dto.setUnusableReason("积分不足1元无法进行抵扣");
return dto;
}
dto.setUsable(true);
// 计算最多可抵扣的积分
BigDecimal mul = NumberUtil.mul(dto.getMaxDeductionAmount(), equivalentPoints);
BigDecimal round = NumberUtil.round(mul, 0, RoundingMode.CEILING);
dto.setMaxUsablePoints(round.intValue());
return dto;
}
@Override
public int calcUsedPoints(Long shopUserId, BigDecimal orderAmount, BigDecimal deductionAmount) {
OrderDeductionPointsDTO core = getMemberUsablePoints(shopUserId, orderAmount);
if (!core.getUsable()) {
throw new CzgException(core.getUnusableReason());
}
if (NumberUtil.isGreater(deductionAmount, core.getMaxDeductionAmount())) {
throw new CzgException(StrUtil.format("抵扣金额不能超过最大抵扣金额{}元", core.getMaxDeductionAmount()));
}
if (NumberUtil.isGreater(deductionAmount, orderAmount)) {
throw new CzgException(StrUtil.format("抵扣金额不能超过订单金额{}元", orderAmount));
}
// 计算可抵扣的积分
BigDecimal mul = NumberUtil.mul(deductionAmount, core.getEquivalentPoints());
BigDecimal round = NumberUtil.round(mul, 0, RoundingMode.CEILING);
return round.intValue();
}
@Override
public BigDecimal calcDeductionAmount(Long shopUserId, BigDecimal orderAmount, int points) {
OrderDeductionPointsDTO core = getMemberUsablePoints(shopUserId, orderAmount);
if (!core.getUsable()) {
throw new CzgException(core.getUnusableReason());
}
if (points < core.getMinDeductionPoints()) {
throw new CzgException(StrUtil.format("使用积分不能低于使用门槛(每次最少使用{}积分)", core.getMinDeductionPoints()));
}
if (points > core.getMaxUsablePoints()) {
throw new CzgException(StrUtil.format("使用积分不能超过最大使用限制{}", core.getMaxUsablePoints()));
}
BigDecimal money = NumberUtil.mul(points, NumberUtil.div(BigDecimal.ONE, core.getEquivalentPoints()));
BigDecimal maxDeductionAmount = NumberUtil.roundDown(money, 0);
if (NumberUtil.isGreater(maxDeductionAmount, core.getMaxDeductionAmount())) {
return core.getMaxDeductionAmount();
}
return maxDeductionAmount;
}
@Override
public boolean deductPoints(Long shopUserId, int points, String content, OrderInfo orderInfo) {
MemberPoints entity = initMemberPoints(shopUserId);
// 扣除账户积分
entity.setAccountPoints(entity.getAccountPoints() - points);
entity.setLastPointsChangeTime(LocalDateTime.now());
entity.setLastFloatPoints(-points);
// 记录积分变动记录
MemberPointsLog log = new MemberPointsLog();
log.setShopId(entity.getSourceShopId());
log.setShopUserId(entity.getShopUserId());
log.setContent(content);
log.setFloatType("subtract");
log.setFloatPoints(-points);
// 有关联订单的需要回置订单表的相关积分使用字段
if (orderInfo != null) {
log.setOrderNo(orderInfo.getOrderNo());
// TODO 是否需要回执“使用的积分数量(points_num)”和“积分抵扣金额(points_discount_amount)”,目前不清楚是创建订单的时候置入还是支付完成后回调时置入需要商议后决定
}
super.updateById(entity);
memberPointsLogMapper.insert(log);
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean addPoints(Long shopUserId, int points, String content, OrderInfo orderInfo) {
MemberPoints entity = initMemberPoints(shopUserId);
// 增加账户积分
entity.setAccountPoints(entity.getAccountPoints() + points);
entity.setLastPointsChangeTime(LocalDateTime.now());
entity.setLastFloatPoints(points);
// 记录积分变动记录
MemberPointsLog log = new MemberPointsLog();
log.setShopId(entity.getSourceShopId());
log.setShopUserId(entity.getShopUserId());
log.setContent(content);
log.setFloatType("add");
log.setFloatPoints(points);
// 有关联订单的需要回置订单表的相关积分使用字段
if (orderInfo != null) {
log.setOrderNo(orderInfo.getOrderNo());
}
super.updateById(entity);
memberPointsLogMapper.insert(log);
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void consumeAwardPoints(Long shopUserId, OrderInfo orderInfo) {
if (orderInfo == null) {
throw new CzgException("订单不存在");
}
BigDecimal payAmount = orderInfo.getPayAmount();
if (NumberUtil.isLessOrEqual(payAmount, BigDecimal.ZERO)) {
return;
}
PointsBasicSetting basicSetting = pointsBasicSettingMapper.selectOneById(orderInfo.getShopId());
if (basicSetting == null) {
return;
}
Integer enableRewards = basicSetting.getEnableRewards();
if (enableRewards == 0) {
return;
}
String rewardsGroup = basicSetting.getRewardsGroup();
MemberPoints entity;
try {
entity = initMemberPoints(shopUserId);
} catch (Exception e) {
return;
}
Integer vip = entity.getVip();
if (PointUserGroupEnum.VIP.value().equals(rewardsGroup) && ObjectUtil.defaultIfNull(vip, 0) != 1) {
return;
}
BigDecimal consumeAmount = basicSetting.getConsumeAmount();
if (consumeAmount == null) {
return;
}
if (NumberUtil.isLessOrEqual(consumeAmount, BigDecimal.ZERO)) {
return;
}
BigDecimal awardPoints = NumberUtil.roundDown(NumberUtil.div(payAmount, consumeAmount), 0);
addPoints(shopUserId, awardPoints.intValue(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()), orderInfo);
}
}

View File

@@ -1,27 +0,0 @@
package com.czg.service.account.service.impl;
import com.czg.account.entity.PointsBasicSetting;
import com.czg.account.service.PointsBasicSettingService;
import com.czg.service.account.mapper.PointsBasicSettingMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.apache.dubbo.config.annotation.DubboService;
/**
* 积分基本设置 服务层实现。
*
* @author ww
* @since 2025-02-20
*/
@DubboService
public class PointsBasicSettingServiceImpl extends ServiceImpl<PointsBasicSettingMapper, PointsBasicSetting> implements PointsBasicSettingService{
@Override
public void initInfo(Long id) {
PointsBasicSetting record = getById(id);
if (record == null) {
PointsBasicSetting pointsBasicSetting = new PointsBasicSetting();
pointsBasicSetting.setShopId(id);
save(pointsBasicSetting);
}
}
}

View File

@@ -1,456 +0,0 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.czg.account.dto.points.PointsExchangeRecordDTO;
import com.czg.account.entity.*;
import com.czg.account.enums.PointsExchangeStatusEnum;
import com.czg.account.enums.PointsOrderPayTypeEnum;
import com.czg.account.param.PointsExchangeCfParam;
import com.czg.account.param.PointsExchangeRecordParam;
import com.czg.account.param.PointsOrderCreateParam;
import com.czg.account.param.PointsOrderPayParam;
import com.czg.account.service.PointsExchangeRecordService;
import com.czg.account.vo.PointsExchangeSummaryVo;
import com.czg.exception.CzgException;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.*;
import com.czg.utils.HttpContextUtil;
import com.czg.utils.PageUtil;
import com.czg.validator.ValidatorUtil;
import com.czg.validator.group.DefaultGroup;
import com.czg.validator.group.InsertGroup;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 积分兑换记录
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@AllArgsConstructor
@Service
public class PointsExchangeRecordServiceImpl extends ServiceImpl<PointsExchangeRecordMapper, PointsExchangeRecord> implements PointsExchangeRecordService {
private final PointsGoodsSettingMapper pointsGoodsSettingMapper;
private final MemberPointsMapper memberPointsMapper;
private final MemberPointsLogMapper memberPointsLogMapper;
private final ShopInfoMapper shopInfoMapper;
private final ShopMerchantMapper shopMerchantMapper;
private final PointsBasicSettingMapper pointsBasicSettingMapper;
private QueryWrapper buildQueryWrapper(PointsExchangeRecordParam param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
if (StrUtil.isNotEmpty(param.getPickupMethod())) {
queryWrapper.eq(PointsExchangeRecord::getPickupMethod, param.getPickupMethod());
}
if (StrUtil.isNotEmpty(param.getStatus())) {
queryWrapper.eq(PointsExchangeRecord::getStatus, param.getStatus());
}
if (ObjUtil.isNotNull(param.getShopUserId())) {
queryWrapper.eq(PointsExchangeRecord::getShopUserId, param.getShopUserId());
}
if (StrUtil.isNotEmpty(param.getKeywords())) {
queryWrapper.and(q -> {
q.like(PointsExchangeRecord::getOrderNo, param.getKeywords()).or(r -> {
r.like(PointsExchangeRecord::getCouponCode, param.getKeywords());
});
});
}
if (StrUtil.isNotEmpty(param.getBeginDate())) {
queryWrapper.ge(PointsExchangeRecord::getCreateTime, param.getBeginDate() + " 00:00:00");
}
if (StrUtil.isNotEmpty(param.getEndDate())) {
queryWrapper.le(PointsExchangeRecord::getCreateTime, param.getEndDate() + " 23:59:59");
}
Long shopId = StpKit.USER.getShopId(0L);
queryWrapper.eq(PointsExchangeRecord::getShopId, shopId);
queryWrapper.orderBy(PointsExchangeRecord::getId, false);
return queryWrapper;
}
@Override
public Page<PointsExchangeRecordDTO> getPointsExchangeRecordPage(PointsExchangeRecordParam param) {
QueryWrapper queryWrapper = buildQueryWrapper(param);
return super.pageAs(PageUtil.buildPage(), queryWrapper, PointsExchangeRecordDTO.class);
}
@Override
public PointsExchangeRecordDTO getPointsExchangeRecordById(Long id) {
Long shopId = StpKit.USER.getShopId(0L);
return super.mapper.selectOneByQueryAs(query().eq(PointsExchangeRecord::getShopId, shopId).eq(PointsExchangeRecord::getId, id), PointsExchangeRecordDTO.class);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void checkout(String couponCode) {
if (StrUtil.isBlank(couponCode)) {
throw new CzgException("兑换券券码不能为空");
}
PointsExchangeRecord entity = super.getOne(query().eq(PointsExchangeRecord::getCouponCode, couponCode));
if (entity == null) {
throw new CzgException("兑换券券码无效");
}
entity.setStatus(PointsExchangeStatusEnum.DONE.value());
super.updateById(entity);
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(entity.getPointsGoodsId());
if (goods == null) {
throw new CzgException("积分商品不存在");
}
// 更新累计兑换数量
goods.setTotalExchangeCount(goods.getTotalExchangeCount() + 1);
pointsGoodsSettingMapper.update(goods);
}
private Object[] verify(PointsOrderCreateParam param) {
ValidatorUtil.validateEntity(param, InsertGroup.class);
PointsBasicSetting basic = pointsBasicSettingMapper.selectOneByQuery(query().eq(PointsBasicSetting::getShopId, param.getShopId()));
if (basic == null) {
throw new CzgException("商家未配置积分锁客基本设置");
}
if (basic.getEnablePointsMall() != 1) {
throw new CzgException("积分商城未开启");
}
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(param.getPointsGoodsId());
if (goods == null) {
throw new CzgException("兑换的商品信息不存在");
}
if (goods.getDelFlag() == 1) {
throw new CzgException("兑换的商品信息不存在");
}
param.setPointsGoodsName(goods.getGoodsName());
param.setGoodsImageUrl(goods.getGoodsImageUrl());
Integer status = goods.getStatus();
if (status != 1) {
throw new CzgException("兑换的商品已下架");
}
Integer quantity = goods.getQuantity();
if (quantity <= 0) {
throw new CzgException("兑换的商品库存不足");
}
MemberPoints memberPoints = memberPointsMapper.selectOneByQuery(query().eq(MemberPoints::getShopUserId, param.getUserId()));
if (memberPoints == null) {
throw new CzgException("会员积分不足无法兑换此商品");
}
Integer accountPoints = memberPoints.getAccountPoints();
Integer requiredPoints = goods.getRequiredPoints();
if (accountPoints < requiredPoints) {
throw new CzgException("会员积分不足无法兑换此商品");
}
return new Object[]{basic, goods, memberPoints};
}
@Override
public PointsExchangeRecordDTO create(PointsOrderCreateParam param) {
Long shopId = StpKit.USER.getShopId(0L);
param.setShopId(shopId);
Object[] verify = verify(param);
PointsBasicSetting basic = (PointsBasicSetting) verify[0];
PointsGoodsSetting goods = (PointsGoodsSetting) verify[1];
MemberPoints memberPoints = (MemberPoints) verify[2];
PointsExchangeRecord entity = BeanUtil.copyProperties(param, PointsExchangeRecord.class);
entity.setExtraPaymentAmount(goods.getExtraPrice());
entity.setSpendPoints(goods.getRequiredPoints());
Snowflake seqNo = IdUtil.getSnowflake(0, 0);
String orderNo = DateUtil.format(new Date(), "yyyyMMddHH") + StrUtil.subSuf(seqNo.nextIdStr(), -12);
entity.setOrderNo(orderNo);
entity.setStatus(PointsExchangeStatusEnum.UNPAID.value());
// 生成订单
super.save(entity);
return BeanUtil.copyProperties(entity, PointsExchangeRecordDTO.class);
}
@Override
@Transactional(rollbackFor = Exception.class)
public PointsExchangeRecordDTO pay(PointsOrderPayParam param) {
ValidatorUtil.validateEntity(param, DefaultGroup.class);
PointsExchangeRecord entity = super.getById(param.getId());
if (entity == null) {
throw new CzgException("订单不存在");
}
try {
PointsOrderCreateParam pointsOrderCreateParam = BeanUtil.copyProperties(entity, PointsOrderCreateParam.class);
verify(pointsOrderCreateParam);
} catch (Exception e) {
throw new CzgException(e.getMessage().concat(",请您取消订单"));
}
if (!PointsExchangeStatusEnum.UNPAID.value().equals(entity.getStatus())) {
throw new CzgException("订单状态异常,请刷新后重试");
}
entity.setPayType(param.getPayType().toUpperCase());
if (!PointsOrderPayTypeEnum.getValues().contains(param.getPayType().toUpperCase())) {
throw new CzgException("支付方式不合法");
}
// 设置支付方式
entity.setPayMethod(PointsOrderPayTypeEnum.getText(param.getPayType().toUpperCase()));
// 纯积分支付并且商品需要额外支付金额,需要抛出异常
if (PointsOrderPayTypeEnum.POINTS.getValue().equals(entity.getPayType()) && NumberUtil.isGreater(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
throw new CzgException("此商品需要额外支付金额");
}
if (!PointsOrderPayTypeEnum.POINTS.getValue().equals(entity.getPayType()) && NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
throw new CzgException("此商品不需要额外支付金额");
}
// 如果不需要额外支付
if (NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
// 设置核销券码
entity.setCouponCode(IdUtil.getSnowflakeNextIdStr());
entity.setStatus("waiting");
entity.setPayTime(LocalDateTime.now());
entity.setPayType(param.getPayType().toUpperCase());
super.updateById(entity);
waitingAfter(entity);
return BeanUtil.copyProperties(entity, PointsExchangeRecordDTO.class);
}
if (StrUtil.isBlank(param.getOpenId())) {
throw new CzgException("openId/userId不能为空");
}
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
String ip = null;
if (request != null) {
ip = JakartaServletUtil.getClientIP(request);
}
if (StrUtil.isBlank(ip)) {
throw new CzgException("无法获取用户ip地址");
}
// 需要额外支付
ShopInfo shopInfo = shopInfoMapper.selectOneById(entity.getShopId());
if (shopInfo == null) {
throw new CzgException("店铺信息不存在");
}
ShopMerchant shopMerchant = shopMerchantMapper.selectOneById(shopInfo.getId());
if (shopMerchant == null) {
throw new CzgException("支付通道不存在");
}
if ("alipay".equalsIgnoreCase(entity.getPayType()) && StrUtil.isBlank(shopMerchant.getAlipaySmallAppid())) {
throw new CzgException("店铺未配置支付宝小程序appId");
}
if (1 == 1) {
// TODO 对接支付接口
throw new CzgException("TODO暂未对接支付接口");
}
return null;
/*// 准备支付参数
// 应用ID
String appId = thirdApply.getAppId();
String appToken = thirdApply.getAppToken();
String storeId = thirdApply.getStoreId();
// 订单标题(商品名称)
String subject = entity.getPointsGoodsName();
// 商品描述
String body = StrUtil.format("兑换商品:{} * {}", entity.getPointsGoodsName(), "1");
// 交易金额 单位分 100 表示1元
long amount = NumberUtil.mul(entity.getExtraPaymentAmount(), new BigDecimal("100")).longValue();
// 支付方式
String payType = entity.getPayType().toUpperCase();
// 子商户APPID
String subAppid = thirdApply.getSmallAppid();
if ("alipay".equalsIgnoreCase(entity.getPayType())) {
subAppid = thirdApply.getAlipaySmallAppid();
}
// 用户唯一标识 微信支付时传入用户的openId支付宝支付和银联支付时传入用户的userId
String openId = record.getOpenId();
// 用户IP
String clientIp = record.getIp();
// 商户订单号 mchOrderNo
String mchOrderNo = IdUtil.getSnowflakeNextIdStr();
// 回调地址
String notifyUrl = pointsGoodsOrderCallBack;
// 支付成功后的跳转页面
String returnUrl = null;
PublicResp<WxScanPayResp> publicResp;
try {
publicResp = thirdPayService.scanpay(thirdUrl, appId, subject, body, amount, payType, subAppid, openId, clientIp, mchOrderNo, storeId, notifyUrl, returnUrl, appToken);
} catch (Exception e) {
log.error("拉起支付失败:", e);
throw new MsgException(StrUtil.format("拉起支付失败:{}", e.getMessage()));
}
if (publicResp == null) {
throw new MsgException("拉起支付失败:无响应");
}
if (!"000000".equals(publicResp.getCode())) {
throw new MsgException(publicResp.getMsg());
}
WxScanPayResp payResp = publicResp.getObjData();
if (!"TRADE_AWAIT".equals(payResp.getState())) {
throw new MsgException(StrUtil.format("拉起支付失败:{}", payResp.getState()));
}
entity.setPayOrderId(payResp.getPayOrderId());
super.updateById(entity);
entity.setPayInfo(payResp.getPayInfo());
return entity;*/
}
/**
* 支付完成的后续操作
*
* @param entity 积分兑换实体
*/
private void waitingAfter(PointsExchangeRecord entity) {
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(entity.getPointsGoodsId());
if (goods == null) {
throw new CzgException("积分商品不存在");
}
MemberPoints memberPoints = memberPointsMapper.selectOneById(entity.getShopUserId());
if (memberPoints == null) {
throw new CzgException("会员积分不足无法兑换此商品");
}
Integer quantity = goods.getQuantity();
Integer accountPoints = memberPoints.getAccountPoints();
Integer requiredPoints = goods.getRequiredPoints();
// 扣减积分
memberPoints.setAccountPoints(accountPoints - requiredPoints);
memberPoints.setLastPointsChangeTime(LocalDateTime.now());
memberPoints.setLastFloatPoints(-requiredPoints);
memberPointsMapper.update(memberPoints);
// 扣减库存
goods.setQuantity(quantity - 1);
pointsGoodsSettingMapper.update(goods);
// 记录积分浮动流水
MemberPointsLog log = new MemberPointsLog();
log.setShopId(entity.getShopId());
log.setShopUserId(entity.getShopUserId());
log.setContent(StrUtil.format("兑换商品:{} * {}", entity.getPointsGoodsName(), "1"));
log.setFloatType("subtract");
log.setFloatPoints(-requiredPoints);
memberPointsLogMapper.insert(log);
}
@Override
public void cancel(PointsExchangeCfParam param) {
if (param.getId() == null) {
throw new CzgException("订单ID不能为空");
}
PointsExchangeRecord entity = super.getById(param.getId());
if (entity == null) {
throw new CzgException("订单不存在");
}
if (!PointsExchangeStatusEnum.UNPAID.value().equals(entity.getStatus())) {
throw new CzgException("当前订单状态不支持取消");
}
entity.setStatus(PointsExchangeStatusEnum.CANCEL.value());
entity.setCancelOrRefundReason(param.getCancelOrRefundReason());
entity.setCancelOrRefundTime(LocalDateTime.now());
super.updateById(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void refund(PointsExchangeCfParam param) {
if (param.getId() == null) {
throw new CzgException("订单ID不能为空");
}
PointsExchangeRecord entity = super.getById(param.getId());
if (entity == null) {
throw new CzgException("订单不存在");
}
if (!PointsExchangeStatusEnum.WAITING.value().equals(entity.getStatus())) {
throw new CzgException("当前订单状态不支持退款");
}
// 先退积分
entity.setStatus(PointsExchangeStatusEnum.CANCEL.value());
entity.setCancelOrRefundReason(param.getCancelOrRefundReason());
entity.setCancelOrRefundTime(LocalDateTime.now());
super.updateById(entity);
MemberPoints memberPoints = memberPointsMapper.selectOneByQuery(query().eq(MemberPoints::getShopUserId, entity.getShopUserId()));
if (memberPoints == null) {
throw new CzgException("会员信息不存在");
}
memberPoints.setAccountPoints(memberPoints.getAccountPoints() + entity.getSpendPoints());
memberPoints.setLastPointsChangeTime(LocalDateTime.now());
memberPoints.setLastFloatPoints(entity.getSpendPoints());
memberPointsMapper.update(memberPoints);
// 回滚库存
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(entity.getPointsGoodsId());
if (goods == null) {
throw new CzgException("积分商品不存在");
}
goods.setQuantity(goods.getQuantity() + 1);
pointsGoodsSettingMapper.update(goods);
// 记录积分浮动流水
MemberPointsLog log = new MemberPointsLog();
log.setShopId(entity.getShopId());
log.setShopUserId(entity.getShopUserId());
log.setContent(StrUtil.format("(退单)兑换商品:{} * {}", entity.getPointsGoodsName(), "1"));
log.setFloatType("add");
log.setFloatPoints(+entity.getSpendPoints());
log.setCreateTime(LocalDateTime.now());
memberPointsLogMapper.insert(log);
// 如果额外付款了则需要退款
if (NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
return;
}
// 需要额外退款
ShopInfo shopInfo = shopInfoMapper.selectOneById(entity.getShopId());
if (shopInfo == null) {
throw new CzgException("店铺信息不存在");
}
ShopMerchant shopMerchant = shopMerchantMapper.selectOneById(shopInfo.getId());
if (shopMerchant == null) {
throw new CzgException("支付通道不存在");
}
if ("alipay".equalsIgnoreCase(entity.getPayType()) && StrUtil.isBlank(shopMerchant.getAlipaySmallAppid())) {
throw new CzgException("店铺未配置支付宝小程序appId");
}
// 准备退款参数
// 应用ID
// TODO 对接退款接口
/* String appId = thirdApply.getAppId();
String appToken = thirdApply.getAppToken();
// 交易金额 单位分 100 表示1元
long amount = NumberUtil.mul(record.getExtraPaymentAmount(), new BigDecimal("100")).longValue();
// 退款订单号
String mchRefundNo = entity.getOrderNo();
PublicResp<OrderReturnResp> publicResp;
try {
publicResp = thirdPayService.returnOrder(thirdUrl, appId, mchRefundNo, entity.getPayOrderId(), null, entity.getCancelOrRefundReason(), amount, null, null, appToken);
} catch (Exception e) {
super.log.error("发起退款失败:", e);
throw new CzgException(StrUtil.format("发起退款失败:{}", e.getMessage()));
}
if (publicResp == null) {
throw new CzgException("发起退款失败:无响应");
}
if (!"000000".equals(publicResp.getCode())) {
throw new CzgException(publicResp.getMsg());
}
OrderReturnResp returnResp = publicResp.getObjData();
if (!"SUCCESS".equals(returnResp.getState())) {
throw new CzgException(StrUtil.format("退款失败原因:{}", returnResp.getState()));
}*/
}
@Override
public PointsExchangeSummaryVo total(PointsExchangeRecordParam param) {
QueryWrapper queryWrapper = buildQueryWrapper(param);
queryWrapper.select("count(*) as count,sum(extra_payment_amount) as totalAmount");
PointsExchangeRecord summary = super.getOne(queryWrapper);
PointsExchangeSummaryVo result = new PointsExchangeSummaryVo();
result.setCount(summary.getCount());
result.setTotalAmount(NumberUtil.nullToZero(summary.getTotalAmount()));
return result;
}
@Override
public void authCancel() {
super.mapper.authCancel();
}
}

View File

@@ -1,50 +0,0 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.account.dto.points.PointsGoodsSettingDTO;
import com.czg.account.entity.PointsGoodsSetting;
import com.czg.account.service.PointsGoodsSettingService;
import com.czg.enums.DeleteEnum;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.PointsGoodsSettingMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* 积分商品设置
*
* @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-25
*/
@Service
public class PointsGoodsSettingServiceImpl extends ServiceImpl<PointsGoodsSettingMapper, PointsGoodsSetting> implements PointsGoodsSettingService {
private QueryWrapper buildQueryWrapper(PointsGoodsSettingDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
if (StrUtil.isNotEmpty(param.getGoodsName())) {
queryWrapper.like(PointsGoodsSetting::getGoodsName, param.getGoodsName());
}
if (StrUtil.isNotEmpty(param.getGoodsCategory())) {
queryWrapper.eq(PointsGoodsSetting::getGoodsCategory, param.getGoodsCategory());
}
if (ObjUtil.isNotNull(param.getStatus())) {
queryWrapper.eq(PointsGoodsSetting::getStatus, param.getStatus());
}
Long shopId = StpKit.USER.getShopId(0L);
queryWrapper.eq(PointsGoodsSetting::getDelFlag, DeleteEnum.NORMAL.value());
queryWrapper.eq(PointsGoodsSetting::getShopId, shopId);
queryWrapper.orderBy(PointsGoodsSetting::getSort, false);
queryWrapper.orderBy(PointsGoodsSetting::getId, false);
return queryWrapper;
}
@Override
public Page<PointsGoodsSettingDTO> getPointsGoodsSettingPage(PointsGoodsSettingDTO param) {
QueryWrapper queryWrapper = buildQueryWrapper(param);
return super.pageAs(PageUtil.buildPage(), queryWrapper, PointsGoodsSettingDTO.class);
}
}

View File

@@ -75,8 +75,6 @@ public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> i
@Resource
private FreeDineConfigService freeDineConfigService;
@Resource
private PointsBasicSettingService pointsBasicSettingService;
@Resource
private ShopConfigService shopConfigService;
@DubboReference
@@ -203,7 +201,6 @@ public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> i
shopPayTypeService.addInfo(shopInfo.getId());
// 初始化积分霸王餐设置
freeDineConfigService.getConfig(shopInfo.getId());
pointsBasicSettingService.initInfo(shopInfo.getId());
updateById(shopInfo);
syncSaveConfig(shopInfo, shopInfoAddDTO);

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.account.mapper.MemberPointsLogMapper">
</mapper>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.account.mapper.PointsBasicSettingMapper">
</mapper>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.account.mapper.PointsExchangeRecordMapper">
<update id="authCancel">
update tb_points_exchange_record
set status = 'cancel',
cancel_or_refund_time = now(),
cancel_or_refund_reason = '超时未支付,系统自动取消订单'
where status = 'unpaid'
and TIMESTAMPDIFF(MINUTE, create_time, NOW()) >= 5
</update>
</mapper>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.account.mapper.PointsGoodsSettingMapper">
</mapper>

View File

@@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkPointsConfig;
/**
* 积分基本设置 映射层。
*
* @author ww
* @since 2025-12-08
*/
public interface MkPointsConfigMapper extends BaseMapper<MkPointsConfig> {
}

View File

@@ -0,0 +1,17 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkPointsGoods;
import java.util.List;
/**
* 积分商品设置 映射层。
*
* @author ww
* @since 2025-12-08
*/
public interface MkPointsGoodsMapper extends BaseMapper<MkPointsGoods> {
List<MkPointsGoods> getPointsGoodsPageByUser(Long shopId, Long userId);
}

View File

@@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkPointsGoodsRecord;
/**
* 积分兑换记录 映射层。
*
* @author ww
* @since 2025-12-08
*/
public interface MkPointsGoodsRecordMapper extends BaseMapper<MkPointsGoodsRecord> {
}

View File

@@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkPointsUser;
/**
* 会员积分账户 映射层。
*
* @author ww
* @since 2025-12-08
*/
public interface MkPointsUserMapper extends BaseMapper<MkPointsUser> {
}

View File

@@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkPointsUserRecord;
/**
* 会员积分变动记录 映射层。
*
* @author ww
* @since 2025-12-08
*/
public interface MkPointsUserRecordMapper extends BaseMapper<MkPointsUserRecord> {
}

View File

@@ -0,0 +1,55 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.MkPointsUserService;
import com.czg.order.entity.OrderInfo;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkPointsConfig;
import com.czg.market.service.MkPointsConfigService;
import com.czg.service.market.mapper.MkPointsConfigMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 积分基本设置 服务层实现。
*
* @author ww
* @since 2025-12-08
*/
@Service
public class MkPointsConfigServiceImpl extends ServiceImpl<MkPointsConfigMapper, MkPointsConfig> implements MkPointsConfigService {
@Resource
private MkPointsUserService mkPointsUserService;
@Override
public void consumeAwardPoints(Long shopUserId, OrderInfo orderInfo) {
BigDecimal payAmount = orderInfo.getPayAmount();
if (NumberUtil.isLessOrEqual(payAmount, BigDecimal.ZERO)) {
return;
}
MkPointsConfig pointsConfig = getOne(query().eq(MkPointsConfig::getShopId, orderInfo.getShopId()));
if (pointsConfig == null) {
return;
}
Integer enableRewards = pointsConfig.getEnableRewards();
if (enableRewards == 0) {
return;
}
BigDecimal consumeAmount = pointsConfig.getConsumeAmount();
if (consumeAmount == null) {
return;
}
if (NumberUtil.isLessOrEqual(consumeAmount, BigDecimal.ZERO)) {
return;
}
BigDecimal awardPoints = NumberUtil.roundDown(NumberUtil.div(payAmount, consumeAmount), 0);
mkPointsUserService.alterPoints(null, shopUserId, orderInfo.getShopId(), PointsConstant.ADD,
awardPoints.intValue(), orderInfo.getId().toString(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()));
}
}

View File

@@ -0,0 +1,85 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.util.NumberUtil;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.account.vo.PointsExchangeSummaryVo;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkPointsGoodsRecordDTO;
import com.czg.market.dto.MkPointsGoodsRecordQueryDTO;
import com.czg.sa.StpKit;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkPointsGoodsRecord;
import com.czg.market.service.MkPointsGoodsRecordService;
import com.czg.service.market.mapper.MkPointsGoodsRecordMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* 积分兑换记录 服务层实现。
*
* @author ww
* @since 2025-12-08
*/
@Service
public class MkPointsGoodsRecordServiceImpl extends ServiceImpl<MkPointsGoodsRecordMapper, MkPointsGoodsRecord> implements MkPointsGoodsRecordService {
@DubboReference
private ShopInfoService shopInfoService;
@DubboReference
private ShopUserService shopUserService;
@Override
public Page<MkPointsGoodsRecordDTO> getGoodsRecordPage(MkPointsGoodsRecordQueryDTO param) {
Long mainIdByShopId = shopInfoService.getMainIdByShopId(param.getShopId());
Page<MkPointsGoodsRecordDTO> pages = pageAs(
Page.of(param.getPage(), param.getSize())
, query().eq(MkPointsGoodsRecord::getShopId, param.getShopId())
.eq(MkPointsGoodsRecord::getShopUserId, param.getShopUserId())
.eq(MkPointsGoodsRecord::getStatus, param.getStatus())
.like(MkPointsGoodsRecord::getPointsGoodsName, param.getPointsGoodsName())
.like(MkPointsGoodsRecord::getGoodsCategory, param.getGoodsCategory())
, MkPointsGoodsRecordDTO.class);
pages.getRecords().forEach(data -> {
ShopUser shopUser = shopUserService.getOne(query().eq(ShopUser::getId, data.getShopUserId()).eq(ShopUser::getMainShopId, mainIdByShopId));
data.setHeadImg(shopUser.getHeadImg());
data.setNickName(shopUser.getNickName());
data.setPhone(shopUser.getPhone());
});
return pages;
}
@Override
public PointsExchangeSummaryVo total(MkPointsGoodsRecordQueryDTO param) {
QueryWrapper queryWrapper = query().eq(MkPointsGoodsRecord::getShopId, param.getShopId())
.between(MkPointsGoodsRecord::getCreateTime, param.getStartTime(), param.getEndTime())
.eq(MkPointsGoodsRecord::getShopUserId, param.getShopUserId())
.eq(MkPointsGoodsRecord::getStatus, param.getStatus())
.like(MkPointsGoodsRecord::getPointsGoodsName, param.getPointsGoodsName())
.like(MkPointsGoodsRecord::getGoodsCategory, param.getGoodsCategory());
queryWrapper.select("count(*) as count,sum(extra_payment_amount) as totalAmount");
return getOneAs(queryWrapper, PointsExchangeSummaryVo.class);
}
@Override
public boolean checkout(String couponCode, Long shopId) {
MkPointsGoodsRecord record = getOne(query().eq(MkPointsGoodsRecord::getCouponCode, couponCode).eq(MkPointsGoodsRecord::getShopId, shopId));
if (record == null) {
throw new CzgException("未找到该兑换码");
}
if (!record.getStatus().equals("待核销") && !record.getStatus().equals("退款中")) {
throw new CzgException("核销失败,该商品不可核销");
}
MkPointsGoodsRecord upRecord = new MkPointsGoodsRecord();
upRecord.setCheckoutTime(LocalDateTime.now());
upRecord.setStatus("已完成");
return update(upRecord, query().eq(MkPointsGoodsRecord::getId, record.getId()));
}
}

View File

@@ -0,0 +1,105 @@
package com.czg.service.market.service.impl;
import com.czg.BaseQueryParam;
import com.czg.exception.CzgException;
import com.czg.market.entity.MkPointsGoodsRecord;
import com.czg.market.entity.MkPointsUserRecord;
import com.czg.market.service.MkPointsGoodsRecordService;
import com.czg.order.dto.PointGoodsRefundDTO;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkPointsGoods;
import com.czg.market.service.MkPointsGoodsService;
import com.czg.service.market.mapper.MkPointsGoodsMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* 积分商品设置 服务层实现。
*
* @author ww
* @since 2025-12-08
*/
@Service
public class MkPointsGoodsServiceImpl extends ServiceImpl<MkPointsGoodsMapper, MkPointsGoods> implements MkPointsGoodsService {
@Resource
private MkPointsGoodsRecordService goodsRecordService;
@Override
public Page<MkPointsGoods> getPointsGoodsPage(BaseQueryParam param, Long shopId) {
return page(Page.of(param.getPage(), param.getSize()),
query()
.eq(MkPointsGoods::getShopId, shopId)
.eq(MkPointsGoods::getDelFlag, 0)
.orderBy(MkPointsGoods::getSort, false)
.orderBy(MkPointsGoods::getId, false)
);
}
@Override
public Page<MkPointsGoods> getPointsGoodsPageByUser(Integer page, Integer size, Long shopId, Long userId) {
PageHelper.startPage(page, size);
List<MkPointsGoods> list = mapper.getPointsGoodsPageByUser(shopId, userId);
return PageUtil.convert(new PageInfo<>(list));
}
@Override
public Page<MkPointsGoodsRecord> getGoodsRecordPage(Integer page, Integer size, Long shopId, Long userId) {
return goodsRecordService.page(Page.of(page, size), query().eq(MkPointsGoodsRecord::getUserId, userId).eq(MkPointsGoodsRecord::getShopId, shopId));
}
@Override
public boolean applyRefund(PointGoodsRefundDTO param, Long userId) {
MkPointsGoodsRecord record = new MkPointsGoodsRecord();
record.setStatus("退款中");
record.setCancelOrRefundReason(param.getReason());
record.setCancelOrRefundTime(LocalDateTime.now());
return goodsRecordService.update(record, query()
.eq(MkPointsGoodsRecord::getId, param.getRecordId())
.eq(MkPointsGoodsRecord::getOrderNo, param.getOrderNo())
.eq(MkPointsGoodsRecord::getUserId, userId)
);
}
@Override
public boolean cancelRefund(PointGoodsRefundDTO param, Long userId) {
MkPointsGoodsRecord record1 = goodsRecordService.getById(param.getRecordId());
if (record1 == null) {
throw new CzgException("取消失败,订单不存在");
}
if (record1.getStatus().equals("退款中")) {
throw new CzgException("取消失败,订单不处于退款中");
}
MkPointsGoodsRecord record = new MkPointsGoodsRecord();
if (record1.getCheckoutTime() != null) {
record.setStatus("已完成");
}else {
record.setStatus("待核销");
}
record.setCancelOrRefundReason(param.getReason());
record.setCancelOrRefundTime(LocalDateTime.now());
return goodsRecordService.update(record, query()
.eq(MkPointsGoodsRecord::getId, param.getRecordId())
.eq(MkPointsGoodsRecord::getOrderNo, param.getOrderNo())
.eq(MkPointsGoodsRecord::getUserId, userId)
);
}
@Override
public boolean upNumberById(Long id, Integer quantity, Integer totalExchangeCount) {
MkPointsGoods goodUp = new MkPointsGoods();
goodUp.setQuantity(quantity);
goodUp.setTotalExchangeCount(totalExchangeCount);
return updateById(goodUp);
}
}

View File

@@ -0,0 +1,28 @@
package com.czg.service.market.service.impl;
import com.czg.account.vo.PointsShopListVO;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkPointsUserRecord;
import com.czg.market.service.MkPointsUserRecordService;
import com.czg.service.market.mapper.MkPointsUserRecordMapper;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 会员积分变动记录 服务层实现。
*
* @author ww
* @since 2025-12-08
*/
@Service
public class MkPointsUserRecordServiceImpl extends ServiceImpl<MkPointsUserRecordMapper, MkPointsUserRecord> implements MkPointsUserRecordService {
@Override
public Page<MkPointsUserRecord> pageByPointsUserId(Integer page, Integer size, Long mkPointsUserId) {
return page(Page.of(page, size), query().eq(MkPointsUserRecord::getMkPointsUserId, mkPointsUserId).orderBy(MkPointsUserRecord::getCreateTime, false));
}
}

View File

@@ -0,0 +1,146 @@
package com.czg.service.market.service.impl;
import cn.hutool.core.util.StrUtil;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.account.vo.PointsShopListVO;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkPointsUserDTO;
import com.czg.market.entity.MkPointsUserRecord;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.MkPointsUserRecordService;
import com.czg.sa.StpKit;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkPointsUser;
import com.czg.market.service.MkPointsUserService;
import com.czg.service.market.mapper.MkPointsUserMapper;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.stringtemplate.v4.ST;
import java.util.List;
/**
* 会员积分账户 服务层实现。
*
* @author ww
* @since 2025-12-08
*/
@Service
public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkPointsUser> implements MkPointsUserService {
@DubboReference
private ShopInfoService shopInfoService;
@DubboReference
private ShopUserService shopUserService;
@Resource
private MkPointsUserRecordService pointsUserRecordService;
@Override
public Page<MkPointsUserDTO> getPointsUserPage(String phone, Integer page, Integer size) {
Long shopUserId = null;
Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());
if (StrUtil.isBlankIfStr(phone)) {
ShopUser one = shopUserService.getOne(query().eq(ShopUser::getPhone, phone).eq(ShopUser::getMainShopId, mainIdByShopId));
if (one == null) {
return new Page<>();
}
shopUserId = one.getId();
}
Page<MkPointsUserDTO> pages = pageAs(Page.of(page, size), query()
.eq(MkPointsUser::getShopId, StpKit.USER.getShopId())
.eq(MkPointsUser::getShopUserId, shopUserId)
.orderBy(MkPointsUser::getUpdateTime, false),
MkPointsUserDTO.class);
pages.getRecords().forEach(s -> {
ShopUser shopUser = shopUserService.getOne(query().eq(ShopUser::getId, s.getShopUserId()).eq(ShopUser::getMainShopId, mainIdByShopId));
s.setHeadImg(shopUser.getHeadImg());
s.setNickName(shopUser.getNickName());
s.setPhone(shopUser.getPhone());
});
return pages;
}
@Override
public List<PointsShopListVO> pointsShopList(Long userId, String shopName) {
return listAs(query().select(MkPointsUser::getShopId).select(ShopInfo::getShopName, ShopInfo::getLogo, ShopInfo::getCoverImg)
.eq(MkPointsUser::getUserId, userId).leftJoin(ShopInfo.class).on(MkPointsUser::getShopId, ShopInfo::getId),
PointsShopListVO.class);
}
public MkPointsUser getPointsUser(Long shopId, Long shopUserId, Long userId) {
MkPointsUser pointsUser;
if (userId == null && shopUserId == null) {
throw new CzgException("积分操作失败用户ID和店铺用户ID不能同时为空");
}
if (shopUserId != null) {
pointsUser = getOne(query().eq(MkPointsUser::getShopUserId, shopUserId).eq(MkPointsUser::getShopId, shopId));
if (pointsUser == null) {
ShopUser shopUser = shopUserService.getById(shopUserId);
if (shopUser == null) {
throw new CzgException("积分操作失败,店铺用户不存在");
}
pointsUser = MkPointsUser.builder()
.userId(userId)
.shopId(shopId)
.shopUserId(shopUserId)
.pointBalance(0L)
.build();
}
} else {
pointsUser = getOne(query().eq(MkPointsUser::getUserId, userId).eq(MkPointsUser::getShopId, shopId));
if (pointsUser == null) {
ShopUser shopUser = shopUserService.getUserInfo(shopId, userId);
if (shopUser == null) {
throw new CzgException("积分操作失败,店铺用户不存在");
}
pointsUser = MkPointsUser.builder()
.userId(userId)
.shopId(shopId)
.shopUserId(shopUser.getId())
.pointBalance(0L)
.build();
}
}
return pointsUser;
}
@Override
public Long alterPoints(Long userId, Long shopUserId, Long shopId, PointsConstant floatType, Integer points, String sourceId, String reason) {
MkPointsUser pointsUser = getPointsUser(shopId, shopUserId, userId);
if (floatType == null) {
throw new CzgException("积分变动类型不能为空");
}
switch (floatType) {
case ADD:
pointsUser.setPointBalance(pointsUser.getPointBalance() + points);
break;
case SUB:
pointsUser.setPointBalance(pointsUser.getPointBalance() - points);
if (pointsUser.getPointBalance() < 0) {
throw new CzgException("积分操作失败,积分不足");
}
points = -points;
break;
default:
throw new CzgException("不支持的积分变动类型:" + floatType);
}
saveOrUpdate(pointsUser);
MkPointsUserRecord record = MkPointsUserRecord.builder()
.mkPointsUserId(pointsUser.getId())
.floatType(floatType.getValue())
.floatPoints(points)
.sourceId(sourceId)
.content(reason)
.build();
boolean save = pointsUserRecordService.save(record);
if (!save) {
throw new CzgException("积分操作失败,积分记录保存失败");
}
return record.getId();
}
}

View File

@@ -4,10 +4,8 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.entity.ShopConfig;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.MemberPointsService;
import com.czg.account.service.ShopConfigService;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
@@ -16,29 +14,22 @@ import com.czg.exception.CzgException;
import com.czg.market.dto.CouponInfoDTO;
import com.czg.market.dto.MkRewardCouponDTO;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.dto.MkShopRechargeDetailDTO;
import com.czg.market.entity.MkShopRechargeDetail;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.service.MkShopCouponRecordService;
import com.czg.market.service.MkShopRechargeDetailService;
import com.czg.market.service.ShopCouponService;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*;
import com.czg.market.vo.*;
import com.czg.order.entity.OrderInfo;
import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.utils.AssertUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopRecharge;
import com.czg.market.service.MkShopRechargeService;
import com.czg.service.market.mapper.MkShopRechargeMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -57,8 +48,8 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
private ShopCouponService shopCouponService;
@DubboReference
private ShopUserService shopUserService;
@DubboReference
private MemberPointsService memberPointsService;
@Resource
private MkPointsUserService pointsUserService;
@Resource
private MkShopCouponRecordService shopCouponRecordService;
@DubboReference
@@ -190,11 +181,11 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
.setBizEnum(ShopUserFlowBizEnum.AWARD_IN)
.setRelationId(paymentId);
shopUserMoneyEditRewardDTO.setMoney(rechargeDetail.getRewardAmount());
shopUserService.updateMoney(shopUserMoneyEditRewardDTO);
Long editId = shopUserService.updateMoney(shopUserMoneyEditRewardDTO);
// 发放积分
if (rechargeDetail.getRewardPoints() != null) {
memberPointsService.addPoints(shopUserId, rechargeDetail.getRewardPoints(), "会员消费送积分", null);
pointsUserService.alterPoints(null, shopUserId, shopUser.getMainShopId(), PointsConstant.ADD, rechargeDetail.getRewardPoints(), editId.toString(), "会员充值送积分");
}
// 发放优惠券
@@ -205,7 +196,7 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
.setNum(item.getNum())
.setUserId(shopUser.getUserId())
.setShopId(shopId), "充值赠券");
}catch (Exception e) {
} catch (Exception e) {
log.warn("发放优惠券失败", e);
}
});
@@ -254,7 +245,7 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
});
});
shopIdList = null;
}else {
} else {
shopIdList.add(shopId);
queryWrapper.in(ShopInfo::getId, shopIdList);
}

View File

@@ -12,6 +12,7 @@ import com.czg.market.dto.*;
import com.czg.account.entity.*;
import com.czg.account.service.*;
import com.czg.market.entity.*;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*;
import com.czg.market.vo.*;
import com.czg.order.entity.OrderInfo;
@@ -55,8 +56,8 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
private OrderInfoService orderInfoService;
@DubboReference
private OrderPaymentService paymentService;
@DubboReference
private MemberPointsService memberPointsService;
@Resource
private MkPointsUserService pointsUserService;
@Resource
private MemberOrderService memberOrderService;
@Resource
@@ -69,7 +70,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
private ShopConfigService shopConfigService;
@Override
public MemberConfigVO detail(Long shopId) {
public MemberConfigVO detail(Long shopId) {
shopId = shopInfoService.getMainIdByShopId(shopId);
TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
if (memberConfig == null) {
@@ -188,8 +189,8 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList()));
}
shopConfigService.editStatusByShopIdList(memberConfig.getShopId(), memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0,false, "is_member_price",
"ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part",
shopConfigService.editStatusByShopIdList(memberConfig.getShopId(), memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0, false, "is_member_price",
"ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part",
StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList()) ? JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class) : new ArrayList<>());
return updateById(memberConfig, false);
@@ -235,7 +236,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
}
@Override
public Boolean editLevel(Long shopId, MemberLevelDTO levelDTO) {
public Boolean editLevel(Long shopId, MemberLevelDTO levelDTO) {
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getId, levelDTO.getId()).eq(MemberLevelConfig::getShopId, shopId));
Optional.ofNullable(levelConfig).orElseThrow(() -> new CzgException("会员等级不存在"));
Integer oldVal = levelConfig.getExperienceValue();
@@ -253,7 +254,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
if (!levelDTO.getExperienceValue().equals(oldVal)) {
List<ShopUser> shopUserList = shopUserService.list(new QueryWrapper().eq(ShopUser::getMainShopId, mainShopid));
shopUserList.forEach(item -> {
MemberLevelConfig configServiceOne = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, mainShopid)
MemberLevelConfig configServiceOne = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, mainShopid)
.le(MemberLevelConfig::getExperienceValue, item.getExperience()).orderBy(MemberLevelConfig::getExperienceValue, false).limit(1));
item.setMemberLevelId(configServiceOne == null ? item.getMemberLevelId() : configServiceOne.getId());
});
@@ -278,20 +279,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
return memberLevelVOS;
}
static void main() {
Integer expVal = 10;
TableValueConstant.MemberExpFlow.Type type = TableValueConstant.MemberExpFlow.Type.PAY;
long exp = 0;
switch (type) {
case PAY -> {
exp = expVal;
}
}
System.out.println(exp);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deliver(ShopUser shopUser, TableValueConstant.MemberExpFlow.Type type, BigDecimal money, Integer expVal, Long sourceId) {
@@ -331,7 +318,8 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
int points = (int) (money.floatValue() / levelVO.getCostRewardPoints());
log.info("消费送积分: {}", points);
if (points > 0) {
memberPointsService.addPoints(shopUser.getId(), points, "会员消费送积分", null);
pointsUserService.alterPoints(null, shopUser.getId(), shopUser.getMainShopId(), PointsConstant.ADD, points, sourceId.toString(), "会员消费送积分");
}
}
}
@@ -345,7 +333,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
if (levelVO.getIsCycleReward() == 1) {
if (levelVO.getCycleRewardPoints() != null) {
int points = levelVO.getCycleRewardPoints();
memberPointsService.addPoints(shopUser.getId(), points, "会员任务奖励", null);
pointsUserService.alterPoints(null, shopUser.getId(), shopUser.getMainShopId(), PointsConstant.ADD, points, sourceId.toString(), "会员奖励");
}
if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkPointsConfigMapper">
</mapper>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkPointsGoodsMapper">
<select id="getPointsGoodsPageByUser" resultType="com.czg.market.entity.MkPointsGoods">
select goods.*, count(record.id) as boughtCount
from mk_points_goods goods
left join mk_points_user_record record
on record.mk_points_goods_id = goods.id and record.user_id = #{userId} and record.status != '已退款'
where goods.shop_id = #{shopId}
and goods.del_flag = 0
and goods.status = 1
order by goods.sort desc, goods.id desc
</select>
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkPointsGoodsRecordMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkPointsUserMapper">
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkPointsUserRecordMapper">
</mapper>

View File

@@ -3,6 +3,8 @@ package com.czg.service.order.service;
import com.czg.entity.resp.CzgBaseResp;
import com.czg.entity.resp.CzgRefundResp;
import com.czg.order.dto.OrderInfoRefundDTO;
import com.czg.order.dto.PointGoodsExchangeDTO;
import com.czg.order.entity.OrderPayment;
import com.czg.resp.CzgResult;
import com.czg.service.order.dto.*;
import lombok.NonNull;
@@ -17,6 +19,8 @@ import java.util.Map;
* @author ww
*/
public interface PayService {
//-----------------------------------------------------------------订单支付--------------------------------------------------------------------
/**
* 挂账
*/
@@ -28,15 +32,10 @@ public interface PayService {
CzgResult<Object> cashPayOrder(OrderPayParamDTO payParam);
/**
* 会员支付
* 余额支付
*/
CzgResult<Object> vipPayOrder(OrderPayParamDTO payParam);
/**
* 充值并付款
*/
CzgResult<Map<String, Object>> rechargePayOrder(String clintIp, OrderPayParamDTO payParam);
/**
* h5支付
*/
@@ -47,6 +46,9 @@ public interface PayService {
*/
CzgResult<Map<String, Object>> jsPayOrder(String clintIp, OrderPayParamDTO payParam);
/**
* 空订单支付
*/
CzgResult<Map<String, Object>> js2PayOrder(@NonNull String clintIp, OrderPayParamDTO payParam);
/**
@@ -63,7 +65,13 @@ public interface PayService {
* 聚合反扫
*/
CzgResult<Map<String, Object>> microPayOrder(OrderPayParamDTO payParam);
//-----------------------------------------------------------------订单+会员 一起支付-----------------------------------------------------------
/**
* 充值并付款
*/
CzgResult<Map<String, Object>> rechargePayOrder(String clintIp, OrderPayParamDTO payParam);
//-----------------------------------------------------------------会员支付--------------------------------------------------------------------
/**
* 现金充值
@@ -89,6 +97,18 @@ public interface PayService {
* 聚合反扫
*/
CzgResult<Map<String, Object>> microPayVip(VipPayParamDTO payParam);
//-----------------------------------------------------------------会员开通购买 ----------------------------------------------------------
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
CzgResult<Map<String, Object>> recharge(String clientIP, VipPayParamDTO rechargeDTO, Long userId);
//-----------------------------------------------------------------积分商品 付款 ----------------------------------------------------------
CzgResult<Map<String, Object>> ltPayPointsGoods(String ip, PointGoodsExchangeDTO param, Long recordId);
//-----------------------------------------------------------------退款-----------------------------------------------------------------
/**
* 退款前校验
@@ -107,6 +127,21 @@ public interface PayService {
*/
void refundOrder(Long shopId, Long orderId, Long payOrderId, String refPayOrderNo, String refundReason, BigDecimal refundAmount);
/**
* 统一退款接口
*
* @param refPayOrderNo 自定义退单号
*/
void unifyRefund(Long shopId, Long sourceId, Long payOrderId, String refPayOrderNo, String refundReason, BigDecimal refundAmount);
/**
* 退款补偿使用
*/
void unifyRefund(OrderPayment payment, String refPayOrderNo);
//-----------------------------------------------------------------支付查询 ----------------------------------------------------------
/**
* 支付查询
*
@@ -122,8 +157,4 @@ public interface PayService {
* @param refundOrderId 平台退款订单号 二选一
*/
CzgResult<CzgRefundResp> queryRefund(Long shopId, String mchRefundNo, String refundOrderId);
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
CzgResult<Map<String, Object>> recharge(String clientIP, VipPayParamDTO rechargeDTO, Long userId);
}

View File

@@ -35,7 +35,7 @@ import java.util.Map;
public class DistributionPayServiceImpl implements DistributionPayService {
private final BigDecimal MONEY_RATE = new BigDecimal("100");
@DubboReference
@Resource
private OrderPaymentService orderPaymentService;
@Resource
private MkDistributionConfigService configService;

View File

@@ -25,8 +25,10 @@ import com.czg.exception.OrderCancelException;
import com.czg.exception.OrderValidateException;
import com.czg.market.dto.MkDiscountActivityDTO;
import com.czg.market.entity.MkDiscountThreshold;
import com.czg.market.entity.MkPointsConfig;
import com.czg.market.entity.MkShopCouponRecord;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*;
import com.czg.order.dto.*;
import com.czg.order.entity.CashierCart;
@@ -34,10 +36,7 @@ import com.czg.order.entity.OrderDetail;
import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.OrderPayment;
import com.czg.order.enums.PayEnums;
import com.czg.order.service.CashierCartService;
import com.czg.order.service.OrderDetailService;
import com.czg.order.service.OrderInfoCustomService;
import com.czg.order.service.OrderPaymentService;
import com.czg.order.service.*;
import com.czg.order.vo.*;
import com.czg.product.entity.Product;
import com.czg.product.service.ProductRpcService;
@@ -104,8 +103,6 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
@Resource
private MkDistributionUserService distributionUserService;
@DubboReference
private MemberPointsService pointsService;
@DubboReference
private ProductService productService;
@DubboReference
private ProductRpcService productRpcService;
@@ -119,11 +116,15 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
private ShopUserFlowService flowService;
@DubboReference
private ShopTableService shopTableService;
@DubboReference
private PointsBasicSettingService pointsBasicService;
@Resource
private MkShopConsumerCouponService consumerCouponService;
@Resource
private MkPointsUserService pointsUserService;
@Resource
private MkPointsConfigService pointsConfigService;
@Resource
private PointsGoodPayService goodPayService;
@Resource
private ShopCouponService couponService;
@Resource
private MkShopCouponRecordService couponRecordService;
@@ -132,8 +133,6 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
@Resource
private MkShopConsumeDiscountRecordService newConsumerDiscountRecordService;
@Resource
private MemberOrderService memberOrderService;
@Resource
private MkDiscountActivityService discountActService;
@Resource
private MkShopRechargeService shopRechargeService;
@@ -376,11 +375,10 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
param.getPointsDiscountAmount().compareTo(BigDecimal.ZERO) > 0);
}
// 积分校验
Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
PointsBasicSetting pointSetting = pointsBasicService.getById(mainShopId);
MkPointsConfig pointSetting = pointsConfigService.getOne(QueryWrapper.create().eq(MkPointsConfig::getShopId, shopId));
boolean usePointsDeduction = param.getPointsNum() > 0 || param.getPointsDiscountAmount().compareTo(BigDecimal.ZERO) > 0;
if (usePointsDeduction) {
if (pointSetting == null || !pointSetting.getEnableDeduction().equals(1)) {
if (pointSetting == null || !pointSetting.getEnableRewards().equals(1)) {
throw new OrderValidateException("生成支付订单失败,该店铺未开启积分抵扣");
}
if (param.getUserId() == null) {
@@ -396,24 +394,11 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
}
}
if (param.getPointsNum() > 0 && (!param.isFreeDine() || param.isWithPoints())) {
if (pointSetting == null || !pointSetting.getEnableDeduction().equals(1)) {
throw new OrderValidateException("生成支付订单失败,该店铺未开启积分抵扣");
}
if (param.getUserId() == null) {
throw new OrderValidateException("生成支付订单失败,请选择用户后再使用积分抵扣");
}
} else if (param.getPointsDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
throw new OrderValidateException("生成支付订单失败,已使用积分抵扣,积分数量不正确");
}
ShopUser shopUser = null;
if (param.getUserId() != null) {
UserInfo userInfo = userInfoService.getById(param.getUserId());
AssertUtil.isNull(userInfo, "生成支付订单失败,用户信息不存在");
shopUser = shopUserService.getShopUserInfo(shopId, param.getUserId());
if (param.getPointsNum() > 0 && !shopUser.getIsVip().equals(1) && pointSetting.getDeductionGroup().contains("vip")) {
throw new OrderValidateException("生成支付订单失败,该店铺仅会员可使用积分抵扣");
}
orderInfo.setUserId(userInfo.getId());
}
//会员价校验
@@ -1075,7 +1060,8 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
distributionUserService.costUpgradeLevelBefore(orderInfo.getUserId(), orderInfo.getShopId());
// 分销奖励
distributionUserService.distribute(orderInfo.getId(), orderInfo.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), orderInfo.getShopId(), "order");
} else if ("memberIn".equals(payment.getPayType()) || "free".equals(payment.getPayType())) {
}
else if ("memberIn".equals(payment.getPayType()) || "free".equals(payment.getPayType())) {
boolean isFree = "free".equals(payment.getPayType());
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
OrderInfo orderInfo = null;
@@ -1175,7 +1161,8 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
// if (orderInfo != null) {
// distributionUserService.distribute(payment.getId(), payment.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), payment.getShopId(), "recharge");
// }
} else if ("memberPay".equals(payment.getPayType())) {
}
else if ("memberPay".equals(payment.getPayType())) {
//购买会员
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
memberConfigService.joinMember(payment.getShopId(), shopUser.getUserId(), payment.getRelatedId());
@@ -1183,8 +1170,11 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
// memberConfigService.deliver(shopUser.getMainShopId(), shopUser.getUserId(), TableValueConstant.MemberExpFlow.Type.COST, payment.getAmount(), null, payment.getId());
// 分销员开通
} else if ("distribution".equals(payment.getPayType())) {
}
else if ("distribution".equals(payment.getPayType())) {
distributionUserService.open(payment.getSourceId(), payment.getAmount(), payment.getShopId(), payment.getId());
}else if("point".equals(payment.getPayType())){
goodPayService.payCallBack(payment.getSourceId());
}
}
paymentService.updateById(payment);
@@ -1274,7 +1264,9 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
}
//积分使用
if (orderInfo.getPointsNum() != null && orderInfo.getPointsNum() > 0) {
pointsService.deductPoints(shopUser.getId(), orderInfo.getPointsNum(), "积分抵扣账单", orderInfo);
pointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.SUB,
orderInfo.getPointsNum(), orderInfo.getId().toString(), "积分抵扣账单");
}
//更新优惠券信息
if (StrUtil.isNotBlank(orderInfo.getCouponInfoList()) && !"null".equals(orderInfo.getCouponInfoList())) {
@@ -1296,7 +1288,10 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
if ((orderInfo.getPayType() != null && !ArrayUtil.contains(payTypes, orderInfo.getPayType()))
|| (payType != null && !ArrayUtil.contains(payTypes, payType))) {
//下单赠送积分
pointsService.consumeAwardPoints(shopUser.getId(), orderInfo);
pointsConfigService.consumeAwardPoints(shopUser.getId(), orderInfo);
// pointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.ADD,
// rechargeDetail.getRewardPoints(), orderInfo.getId(), "下单赠送积分");
//消费返现
if (!orderInfo.getPayType().equals(PayEnums.CASH_PAY.getValue())) {
consumeCashbackService.cashback(orderInfo.getShopId(), shopUser.getUserId(), orderInfo.getPayAmount(), orderInfo.getId(), orderInfo.getOrderNo());
@@ -1509,7 +1504,8 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
}
//积分使用
if (orderInfo.getPointsNum() != null && orderInfo.getPointsNum() > 0) {
pointsService.deductPoints(shopUser.getId(), orderInfo.getPointsNum(), "积分抵扣账单", orderInfo);
pointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.ADD,
orderInfo.getPointsNum(), orderInfo.getId().toString(), "积分抵扣账单");
}
//更新优惠券信息
if (StrUtil.isNotBlank(orderInfo.getCouponInfoList()) && !"null".equals(orderInfo.getCouponInfoList())) {

View File

@@ -25,13 +25,13 @@ import com.czg.market.service.*;
import com.czg.market.vo.MkShopRechargeVO;
import com.czg.order.dto.CheckOrderPay;
import com.czg.order.dto.OrderInfoRefundDTO;
import com.czg.order.dto.PointGoodsExchangeDTO;
import com.czg.order.entity.OrderDetail;
import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.OrderPayment;
import com.czg.order.enums.PayEnums;
import com.czg.order.service.CreditBuyerOrderService;
import com.czg.order.service.OrderDetailService;
import com.czg.market.service.OrderInfoService;
import com.czg.order.service.OrderInfoCustomService;
import com.czg.order.service.OrderPaymentService;
import com.czg.resp.CzgRespCode;
@@ -88,8 +88,6 @@ public class PayServiceImpl implements PayService {
@Resource
private MkShopCouponRecordService recordService;
@DubboReference
private MemberPointsService pointsService;
@DubboReference
private FreeDineConfigService freeConfigService;
@Resource
private CzgPayService czgPayService;
@@ -227,7 +225,7 @@ public class PayServiceImpl implements PayService {
boolean exists = shopInfoService.exists(QueryWrapper.create()
.eq(ShopInfo::getMainId, shopInfo.getMainId())
.eq(ShopInfo::getId, orderInfo.getShopId()));
if(!exists){
if (!exists) {
return CzgResult.failure("违规操作,请确认店铺后重试");
}
}
@@ -253,7 +251,6 @@ public class PayServiceImpl implements PayService {
LocalDateTime.now(), flowId, PayEnums.VIP_PAY);
return CzgResult.success();
}
@@ -437,16 +434,6 @@ public class PayServiceImpl implements PayService {
shopUserService.updateById(updateInfo);
}
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(), payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN);
// ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
// .setId(shopUser.getId())
// .setMoney(payParam.getAmount())
// .setType(1)
// .setRemark("现金充值")
// .setBizEnum(ShopUserFlowBizEnum.CASH_IN);
// //更新会员余额 并生成流水
// Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO);
//TODO 以前的会员活动
//shopActivateService.giveActivate(shopUser, payParam.getAmount(), payParam.getActivateId(), flowId);
return CzgResult.success();
}
@@ -531,7 +518,8 @@ public class PayServiceImpl implements PayService {
initOrderPayment(new OrderPayment(rechargeDTO.getShopId(), shopUser.getId(), isFree ? "free" : "memberIn", payOrderNo,
"", amount, isFree ? rechargeDTO.getOrderId() : rechargeDTO.getRechargeDetailId()));
return ltPay(rechargeDTO.getShopId(), rechargeDTO.getPayType(), new CzgLtPayReq(payOrderNo, amount.multiply(MONEY_RATE).longValue(),
rechargeDTO.getPayType(), "会员充值", "wechatPay".equals(rechargeDTO.getPayType()) ? userInfo.getWechatOpenId() : userInfo.getAlipayOpenId(), clientIP, rechargeDTO.getReturnUrl(), rechargeDTO.getBuyerRemark(), ""));
rechargeDTO.getPayType(), "会员充值", "wechatPay".equals(rechargeDTO.getPayType()) ? userInfo.getWechatOpenId() : userInfo.getAlipayOpenId(),
clientIP, rechargeDTO.getReturnUrl(), rechargeDTO.getBuyerRemark(), ""));
}
@Override
@@ -563,6 +551,19 @@ public class PayServiceImpl implements PayService {
return mapCzgResult;
}
@Override
@Transactional
public CzgResult<Map<String, Object>> ltPayPointsGoods(String ip, PointGoodsExchangeDTO param, Long mkPointsGoodsRecordId) {
AssertUtil.isBlank(param.getOpenId(), "用户小程序ID不能为空");
AssertUtil.isBlank(param.getPayType(), "支付方式不能为空");
String payOrderNo = "DH" + IdUtil.getSnowflakeNextId();
initOrderPayment(new OrderPayment(param.getShopId(), mkPointsGoodsRecordId, "point", payOrderNo,
"", param.getPrice(), null));
return ltPay(param.getShopId(), param.getPayType(), new CzgLtPayReq(payOrderNo, param.getPrice().multiply(MONEY_RATE).longValue(),
param.getPayType(), "积分商品购买", param.getOpenId(), ip, "", "", ""));
}
@Override
public CzgResult<Map<String, BigDecimal>> refundVipBefore(VipRefundDTO payParam) {
Map<String, BigDecimal> resultMap = new HashMap<>(5);
@@ -645,7 +646,7 @@ public class PayServiceImpl implements PayService {
.setMoney(refPayParam.getRefAmount())
.setType(0)
.setRemark("退款")
.setBizEnum(refPayParam.isCashRefund() ? ShopUserFlowBizEnum.RECHARGE_CASH_REFUND : ShopUserFlowBizEnum.RECHARGE_REFUND )
.setBizEnum(refPayParam.isCashRefund() ? ShopUserFlowBizEnum.RECHARGE_CASH_REFUND : ShopUserFlowBizEnum.RECHARGE_REFUND)
.setRelationId(refPaymentId)
.setRechargeId(inFlow.getId());
//更新会员余额 并生成流水
@@ -708,7 +709,7 @@ public class PayServiceImpl implements PayService {
//可退数量=订单数量-退单数量-退菜数量
BigDecimal returnNum = orderDetail.getNum().subtract(orderDetail.getRefundNum()).subtract(orderDetail.getReturnNum());
if (returnNum.compareTo(BigDecimal.ZERO) <= 0 || returnNum.compareTo(refundDetail.getNum()) < 0) {
throw new CzgException("退单失败," + orderDetail.getProductName() + "可退数量不足");
throw new CzgException("退单失败," + orderDetail.getProductName() + "可退数量不足");
}
refundDetail.setReturnAmount(refundDetail.getNum().multiply(orderDetail.getUnitPrice()).setScale(2, RoundingMode.UP));
if (isPay) {
@@ -727,10 +728,10 @@ public class PayServiceImpl implements PayService {
orderDetail.setRefundNo(refPayOrderNo);
orderDetail.setRefundRemark(orderDetail.getRefundRemark() + param.getRefundReason());
// if (isPay) {
orderDetail.setReturnAmount(orderDetail.getReturnAmount().add(refundDetail.getReturnAmount()));
if (orderDetail.getReturnAmount().compareTo(orderDetail.getPayAmount()) > 0) {
orderDetail.setReturnAmount(orderDetail.getPayAmount());
}
orderDetail.setReturnAmount(orderDetail.getReturnAmount().add(refundDetail.getReturnAmount()));
if (orderDetail.getReturnAmount().compareTo(orderDetail.getPayAmount()) > 0) {
orderDetail.setReturnAmount(orderDetail.getPayAmount());
}
// }
orderDetailService.updateById(orderDetail);
if (orderDetail.getProductId() != null && orderDetail.getProductId() > 0) {
@@ -820,7 +821,7 @@ public class PayServiceImpl implements PayService {
@NonNull String refundReason, @NonNull BigDecimal refundAmount) {
OrderPayment payment = paymentService.getById(payOrderId);
AssertUtil.isNull(payment, "退款失败支付记录不存在");
Long refundId = initOrderPayment(new OrderPayment(shopId, orderId, "refund", refPayOrderNo, null, refundAmount));
Long refundId = initOrderPayment(new OrderPayment(shopId, orderId, "refund", refPayOrderNo, null, refundAmount, payment.getId()));
CzgResult<CzgRefundResp> refund = refund(shopId, new CzgRefundReq(refPayOrderNo, refundReason, refundAmount.multiply(MONEY_RATE).longValue(),
payment.getOrderNo(), ""));
if (refund.getCode() != 200 || refund.getData() == null || !"SUCCESS".equals(refund.getData().getState())) {
@@ -838,6 +839,59 @@ public class PayServiceImpl implements PayService {
}
}
@Override
@Transactional
public void unifyRefund(@NonNull Long shopId, @NonNull Long sourceId, @NonNull Long payOrderId, @NonNull String refPayOrderNo,
@NonNull String refundReason, @NonNull BigDecimal refundAmount) {
OrderPayment payment = paymentService.getById(payOrderId);
AssertUtil.isNull(payment, "退款失败,支付记录不存在");
Long refundId = initOrderPayment(new OrderPayment(shopId, sourceId, "refund", refPayOrderNo, null, refundAmount, payment.getId()));
CzgResult<CzgRefundResp> refund = refund(shopId, new CzgRefundReq(refPayOrderNo, refundReason, refundAmount.multiply(MONEY_RATE).longValue(),
payment.getOrderNo(), ""));
if (refund.getCode() != 200 || refund.getData() == null || !"SUCCESS".equals(refund.getData().getState())) {
paymentService.updateChain()
.eq(OrderPayment::getId, refundId)
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
.set(OrderPayment::getPayStatus, "fail")
.update();
} else {
paymentService.updateChain()
.eq(OrderPayment::getId, refundId)
.set(OrderPayment::getPayTime, refund.getData().getRefundTime())
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
.set(OrderPayment::getPayStatus, "success")
.update();
}
}
@Override
@Transactional
public void unifyRefund(OrderPayment refundPayment, String refPayOrderNo) {
OrderPayment payment = paymentService.getById(refundPayment.getRelatedId());
AssertUtil.isNull(payment, "退款失败,支付记录不存在");
Long refundId = refundPayment.getId();
CzgResult<CzgRefundResp> refund = refund(payment.getShopId(), new CzgRefundReq(refPayOrderNo, "退款补偿", refundPayment.getAmount().multiply(MONEY_RATE).longValue(),
payment.getOrderNo(), ""));
if (refund.getCode() != 200 || refund.getData() == null || !"SUCCESS".equals(refund.getData().getState())) {
paymentService.updateChain()
.eq(OrderPayment::getId, refundId)
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
.set(OrderPayment::getPayStatus, "fail")
.update();
} else {
paymentService.updateChain()
.eq(OrderPayment::getId, refundId)
.set(OrderPayment::getPayTime, refund.getData().getRefundTime())
.set(OrderPayment::getTradeNumber, refund.getData().getRefundOrderId())
.set(OrderPayment::getRespJson, JSONObject.toJSONString(refund.getData()))
.set(OrderPayment::getPayStatus, "success")
.update();
}
}
@Override
@Transactional
public CzgResult<CzgBaseResp> queryPayOrder(@NonNull Long shopId, String payOrderId, String mchOrderNo) {

View File

@@ -0,0 +1,172 @@
package com.czg.service.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopUserService;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkShopCouponGiftDTO;
import com.czg.market.entity.MkPointsGoods;
import com.czg.market.entity.MkPointsGoodsRecord;
import com.czg.market.entity.MkPointsUser;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.MkPointsGoodsRecordService;
import com.czg.market.service.MkPointsGoodsService;
import com.czg.market.service.MkPointsUserService;
import com.czg.market.service.MkShopCouponRecordService;
import com.czg.order.dto.PointGoodsExchangeDTO;
import com.czg.order.dto.PointGoodsRefundDTO;
import com.czg.order.service.PointsGoodPayService;
import com.czg.resp.CzgResult;
import com.czg.service.order.service.PayService;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
@Slf4j
@Service
public class PointsGoodPayServiceImpl implements PointsGoodPayService {
@Resource
private ShopUserService shopUserService;
@Resource
private MkPointsUserService pointsUserService;
@Resource
private MkPointsGoodsService goodsService;
@Resource
private MkPointsGoodsRecordService goodsRecordService;
@Resource
private MkShopCouponRecordService couponRecordService;
@Resource
@Lazy
private PayService payService;
@Override
@Transactional
public CzgResult<Map<String, Object>> exchange(String ip, PointGoodsExchangeDTO param) {
MkPointsGoods goods = goodsService.getById(param.getPointsGoodsId());
if (goods == null) {
throw new CzgException("兑换失败,商品不存在");
}
if (goods.getStatus() != 1) {
throw new CzgException("兑换失败,商品已下架");
}
Integer boughtCount = goodsRecordService.getOneAs(QueryWrapper.create().select("sum(number)")
.eq(MkPointsGoodsRecord::getPointsGoodsId, param.getPointsGoodsId())
.ne(MkPointsGoodsRecord::getStatus, "已退款")
.eq(MkPointsGoodsRecord::getUserId, param.getUserId()), Integer.class);
if (goods.getLimitQuota() > 0 && boughtCount != null && boughtCount >= goods.getLimitQuota()) {
throw new CzgException("兑换失败,该商品每人限制兑换" + goods.getLimitQuota() + "");
}
MkPointsUser pointsUser = pointsUserService.getPointsUser(param.getShopId(), null, param.getUserId());
if (pointsUser == null) {
throw new CzgException("兑换失败,用户积分不足");
}
if (goods.getRequiredPoints() > 0 && pointsUser.getPointBalance() < (long) goods.getRequiredPoints() * param.getNumber()) {
throw new CzgException("兑换失败,积分不足");
}
ShopUser shopUser = shopUserService.getUserInfo(param.getShopId(), param.getUserId());
if (shopUser == null) {
throw new CzgException("兑换失败,店铺用户不存在");
}
MkPointsGoodsRecord record = new MkPointsGoodsRecord();
record.setOrderNo("DH" + IdUtil.getSnowflakeNextId());
record.setShopId(param.getShopId());
record.setPointsGoodsId(param.getPointsGoodsId());
record.setPointsGoodsName(goods.getGoodsName());
record.setGoodsImageUrl(goods.getGoodsImageUrl());
record.setGoodsCategory(goods.getGoodsCategory());
record.setReceiveType(goods.getReceiveType());
record.setShopUserId(shopUser.getId());
record.setUserId(param.getUserId());
record.setNumber(param.getNumber());
record.setSpendPoints(goods.getRequiredPoints() * param.getNumber());
record.setExtraPaymentAmount(goods.getExtraPrice() != null ? goods.getExtraPrice().multiply(new BigDecimal(param.getNumber())) : BigDecimal.ZERO);
if (goods.getExtraPrice() != null && goods.getExtraPrice().compareTo(BigDecimal.ZERO) > 0) {
param.setPrice(record.getExtraPaymentAmount());
record.setStatus("待支付");
record.setIsDel(1);
goodsRecordService.save(record);
return payService.ltPayPointsGoods(ip, param, record.getId());
}
//正常处理
exchangeAfter(record, goods);
return CzgResult.success(BeanUtil.beanToMap(record));
}
@Override
public boolean applyRefund(PointGoodsRefundDTO param, Long shopId) {
MkPointsGoodsRecord record = goodsRecordService.getOne(QueryWrapper.create()
.eq(MkPointsGoodsRecord::getId, param.getRecordId())
.eq(MkPointsGoodsRecord::getShopId, shopId));
if (record == null) {
throw new CzgException("操作失败,记录不存在");
}
//退积分
if (record.getSpendPoints() != null && record.getSpendPoints() > 0) {
//回增积分
pointsUserService.alterPoints(record.getUserId(), record.getShopUserId(), record.getShopId(), PointsConstant.ADD,
record.getSpendPoints(), record.getId().toString(), "积分商品兑换退款");
}
//退钱
if (record.getExtraPaymentAmount() != null && record.getExtraPaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
String refPayOrderNo = "REP" + IdUtil.getSnowflakeNextId();
payService.unifyRefund(shopId, record.getId(), record.getPayOrderId(), refPayOrderNo, param.getReason(), record.getExtraPaymentAmount());
}
MkPointsGoodsRecord upRecord = new MkPointsGoodsRecord();
upRecord.setId(record.getId());
upRecord.setStatus("已退款");
upRecord.setCancelOrRefundReason(param.getReason());
upRecord.setCancelOrRefundTime(LocalDateTime.now());
return goodsRecordService.updateById(upRecord);
}
@Override
@Transactional
public void payCallBack(Long recordId) {
MkPointsGoodsRecord record = goodsRecordService.getById(recordId);
if (record == null) {
log.error("积分兑换商品发放失败,记录不存在");
}
exchangeAfter(record, null);
}
private MkPointsGoodsRecord exchangeAfter(MkPointsGoodsRecord record, MkPointsGoods goods) {
if (goods == null) {
goods = goodsService.getById(record.getPointsGoodsId());
}
//扣除积分
pointsUserService.alterPoints(record.getUserId(), null, record.getShopId(), PointsConstant.SUB,
record.getSpendPoints(), record.getId().toString(), "积分商品兑换");
record.setIsDel(0);
if (goods.getGoodsCategory().equals("优惠券")) {
record.setStatus("已完成");
record.setCheckoutTime(LocalDateTime.now());
goodsRecordService.save(record);
MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO()
.setCouponId(goods.getCouponId())
.setShopId(record.getShopId())
.setSourceId(record.getId())
.setShopUserId(record.getId())
.setSource("积分兑换");
couponRecordService.receiveCoupon(giftDTO, record.getNumber(), false);
return record;
}else {
record.setStatus("待核销");
record.setCouponCode(RandomUtil.randomNumbers(12));
}
goodsService.upNumberById(goods.getId(), goods.getQuantity() - record.getNumber(), goods.getTotalExchangeCount() + record.getNumber());
goodsRecordService.save(record);
return record;
}
}