修复优惠卷问题 修复售后订单问题

This commit is contained in:
徐唯轩
2023-11-15 09:38:42 +08:00
parent 406fa693b9
commit 1597f5aaa0
20 changed files with 147 additions and 65 deletions

View File

@ -17,6 +17,8 @@ public interface ErrorCodeConstants {
ErrorCode SELECT_ADDRESS = new ErrorCode(1008007008, "请选择收货地址");
ErrorCode ORDER_GEN_FAIL = new ErrorCode(1008007009, "订单生成失败");
ErrorCode ORDER_PAY_FINISH = new ErrorCode(1008007010, "该订单已支付");
ErrorCode USER_NOT_BINDING_WX_APPLET = new ErrorCode(1008007011, "该用户未绑定微信小程序openid为空");
ErrorCode PAY_YUE_NOT = new ErrorCode(1008007011, "余额不足");
ErrorCode ORDER_STATUS_ERROR = new ErrorCode(1008007012, "订单状态错误");
ErrorCode COMMENT_PRODUCT_NOT_EXISTS = new ErrorCode(1008007013, "评价产品不存在");

View File

@ -18,18 +18,18 @@ import java.util.stream.Stream;
@AllArgsConstructor
public enum PayTypeEnum {
ALI("alipay","支付宝支付"),
WEIXIN("weixin","微信支付"),
WEIXIN_H5("weixin_h5","微信H5支付"),
WEIXIN_APPLET("weixin_applet","微信小程序支付"),
WEIXIN_APP("weixin_app","微信app支付"),
YUE("yue","余额支付"),
INTEGRAL("integral","积分兑换");
ALI("alipay","支付宝支付","1"),
WEIXIN("weixin","微信支付","6"),
WEIXIN_H5("weixin_h5","微信H5支付","4"),
WEIXIN_APPLET("weixin_applet","微信小程序支付","3"),
WEIXIN_APP("weixin_app","微信app支付","2"),
YUE("yue","余额支付","10"),
INTEGRAL("integral","积分兑换","11");
private String value;
private String desc;
private String code;
public static PayTypeEnum toType(String value) {
return Stream.of(PayTypeEnum.values())
.filter(p -> p.value.equals(value))

View File

@ -75,7 +75,7 @@ public class StoreOrderBaseVO {
private BigDecimal deductionPrice;
@Schema(description = "优惠券id", required = true, example = "3299")
@NotNull(message = "优惠券id不能为空")
// @NotNull(message = "优惠券id不能为空")
private Long couponId;
@Schema(description = "优惠券金额", required = true, example = "22157")

View File

@ -13,4 +13,9 @@ public class AppProsuctParam {
*/
private Long productId;
/**
* 商品规格
*/
private String productAttrUnique;
}

View File

@ -48,9 +48,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -99,26 +97,54 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
BigDecimal totalPrice = BigDecimal.ZERO;
//拿到所有的商品
List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery().eq(StoreOrderCartInfoDO::getOid, yxStoreOrder.getId()));
List<StoreAfterSalesItemDO> insertAfterSalesItems = new ArrayList<>();
// 所有商品规格合集
Set<String> allProductAttrUniqueSet = new HashSet<>();
for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
AppStoreCartQueryVo cartInfo = JSONObject.parseObject(yxStoreOrderCartInfo.getCartInfo(), AppStoreCartQueryVo.class);
AppProsuctParam productParam = storeAfterSalesParam.getProductParamList().stream().filter(item -> item.getProductId().equals(yxStoreOrderCartInfo.getProductId())).findFirst().orElse(new AppProsuctParam());
allProductAttrUniqueSet.add(cartInfo.getProductAttrUnique());
// 过滤出对应规格的商品
AppProsuctParam productParam = storeAfterSalesParam.getProductParamList().stream()
.filter(item -> cartInfo.getProductAttrUnique().equals(item.getProductAttrUnique()))
.findFirst().orElse(new AppProsuctParam());
if (productParam.getProductId() != null) {
//商品优惠前总金额
BigDecimal totalAmountOfGoods = NumberUtil.mul(cartInfo.getTruePrice(), cartInfo.getCartNum());
//商品优惠总金额
BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
//该项商品优惠金额
BigDecimal commodityDiscountAmount = null;
if (yxStoreOrder.getTotalPrice().compareTo(yxStoreOrder.getPayPostage()) == 0) {
commodityDiscountAmount = totalAmountOfGoods;
} else {
commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil
.sub(yxStoreOrder.getTotalPrice().add(yxStoreOrder.getCouponPrice()),
yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
}
//商品优惠后总金额
totalPrice = NumberUtil.add(totalPrice, NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount));
// todo 根据自己的业务逻辑修改,是否退运费,默认不退运费
// 未收货退运费
if (OrderInfoEnum.STATUS_DEFAULT.getValue().equals(yxStoreOrder.getStatus())) {
totalPrice = NumberUtil.add(totalPrice, yxStoreOrder.getPayPostage());
}
yxStoreOrderCartInfo.setIsAfterSales(0);
storeOrderCartInfoMapper.updateById(yxStoreOrderCartInfo);
// 售后明细
StoreAfterSalesItemDO storeAfterSalesItem = new StoreAfterSalesItemDO();
storeAfterSalesItem.setProductId(yxStoreOrderCartInfo.getProductId());
storeAfterSalesItem.setCartInfo(yxStoreOrderCartInfo.getCartInfo());
insertAfterSalesItems.add(storeAfterSalesItem);
}
}
// 退货商品规格合集
Set<String> returnProductAttrUniqueSet =
storeAfterSalesParam.getProductParamList().stream()
.map(AppProsuctParam::getProductAttrUnique).collect(Collectors.toSet());
// 全部退货且未发货退运费
if (allProductAttrUniqueSet.equals(returnProductAttrUniqueSet) &&
OrderInfoEnum.STATUS_DEFAULT.getValue().equals(yxStoreOrder.getStatus())) {
totalPrice = NumberUtil.add(totalPrice, yxStoreOrder.getPayPostage());
}
//更新订单状态
yxStoreOrder.setStatus(OrderInfoEnum.STATUS_APPLY_REFUND.getValue());
yxStoreOrder.setRefundStatus(OrderInfoEnum.REFUND_STATUS_BEING_REFUNDED.getValue());
@ -140,15 +166,22 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
storeAfterSales.setCreateTime(LocalDateTime.now());
storeAfterSales.setUserId(userId);
this.baseMapper.insert(storeAfterSales);
//售后商品详情
for (AppProsuctParam productParam : storeAfterSalesParam.getProductParamList()) {
StoreOrderCartInfoDO yxStoreOrderCartInfo = yxStoreOrderCartInfos.stream().filter(item -> item.getProductId().equals(productParam.getProductId())).findFirst().orElse(new StoreOrderCartInfoDO());
insertAfterSalesItems.forEach(res -> {
res.setStoreAfterSalesId(storeAfterSales.getId());
});
// 售后明细批量保存
storeAfterSalesItemMapper.insertBatch(insertAfterSalesItems);
/*for (AppProsuctParam productParam : storeAfterSalesParam.getProductParamList()) {
StoreOrderCartInfoDO yxStoreOrderCartInfo =
yxStoreOrderCartInfos.stream().filter(item -> productParam.getProductId().equals(item.getProductId()))
.findFirst().orElse(new StoreOrderCartInfoDO());
StoreAfterSalesItemDO storeAfterSalesItem = new StoreAfterSalesItemDO();
storeAfterSalesItem.setStoreAfterSalesId(storeAfterSales.getId());
storeAfterSalesItem.setProductId(yxStoreOrderCartInfo.getProductId());
storeAfterSalesItem.setCartInfo(yxStoreOrderCartInfo.getCartInfo());
storeAfterSalesItemMapper.insert(storeAfterSalesItem);
}
}*/
StoreOrderStatusDO orderStatusDO = StoreOrderStatusDO.builder()
.oid(yxStoreOrder.getId()).changeType(APPLY_AFTER_SALES.getValue())
.changeMessage(APPLY_AFTER_SALES.getDesc()).changeTime(LocalDateTime.now()).build();
@ -256,7 +289,15 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
//商品优惠总金额
// BigDecimal commodityDiscountAmount = BigDecimal.ZERO;
// if()
BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
BigDecimal commodityDiscountAmount = null;
// 运费金额等于商品总价
if (yxStoreOrder.getTotalPrice().compareTo(yxStoreOrder.getPayPostage()) == 0) {
commodityDiscountAmount = totalAmountOfGoods;
} else {
commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil
.sub(yxStoreOrder.getTotalPrice().add(yxStoreOrder.getCouponPrice()),
yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
}
yxStoreOrderCartInfoVo.setRefundablePrice(NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount));
@ -271,6 +312,7 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
/**
* 查询列表
*
* @param uid 用户id
* @param status 状态 //状态 0已提交等待平台审核 1平台已审核 等待用户发货/退款 2 用户已发货 3退款成功
* @param page 页
@ -282,8 +324,8 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
public List<AppStoreAfterSalesVo> salesList(Long uid, Integer type, Integer page, String orderCode, Integer limit) {
Page<StoreAfterSalesDO> storeAfterSalesPage = new Page<>(page, limit);
List<Integer> afterSalesStatusList = getAfterSalesStatus(type);
LambdaQueryWrapper<StoreAfterSalesDO> wrappers = new LambdaQueryWrapper<>();
wrappers.eq(uid != null, StoreAfterSalesDO::getUserId, uid)
LambdaQueryWrapper<StoreAfterSalesDO> wrappers = new LambdaQueryWrapper<>();
wrappers.eq(uid != null, StoreAfterSalesDO::getUserId, uid)
.in(!type.equals(AfterSalesStatusEnum.PENDING_REVIEW.getValue()), StoreAfterSalesDO::getState, afterSalesStatusList)
.eq(StringUtils.isNotBlank(orderCode), StoreAfterSalesDO::getOrderCode, orderCode);
baseMapper.selectPage(storeAfterSalesPage, wrappers.
@ -465,7 +507,7 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
StoreOrderDO storeOrderDO =
storeOrderMapper.selectOne(new LambdaQueryWrapper<StoreOrderDO>()
.eq(StoreOrderDO::getOrderId, storeAfterSalesVo.getOrderCode()));
if(storeOrderDO!= null ) {
if (storeOrderDO != null) {
storeAfterSalesVo.setOrderId(storeOrderDO.getId());
storeAfterSalesVo.setCompleteTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 3).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
storeAfterSalesVo.setDeliveryTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 2).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());

View File

@ -451,20 +451,16 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, Stor
if (ObjectUtil.isNull(orderInfo)) {
throw exception(STORE_ORDER_NOT_EXISTS);
}
if (orderInfo.getPaid().equals(OrderInfoEnum.PAY_STATUS_HAVE_PAID.getValue())) {
throw exception(ORDER_PAY_FINISH);
}
if (orderInfo.getPayInfo() == null) {
return false;
}
if (PayTypeEnum.WEIXIN.getValue().equals(param.getPaytype())) {
//微信查单
MerchantDetailsDO merchantDetailsDO = merchantDetailsService.getMerchantDetails("4");
PayInfo payInfo = JsonUtils.parseObject(orderInfo.getPayInfo(), PayInfo.class);
if (payInfo == null) return false;
if (payInfo.getTransaction_id() == null) return false;
Map map = PaymentApi.queryByTransactionId(merchantDetailsDO.getAppid(), merchantDetailsDO.getMchId(), merchantDetailsDO.getKeyPrivate(), payInfo.getTransaction_id());
Map<String, String> map = PaymentApi.queryByTransactionId(merchantDetailsDO.getAppid(), merchantDetailsDO.getMchId(), merchantDetailsDO.getKeyPrivate(), payInfo.getTransaction_id());
log.info("查询到微信订单信息:" + map.toString());
return map.get("return_code").equals("SUCCESS") && map.get("result_code").equals("SUCCESS") && map.get("trade_state").equals("SUCCESS");
} else {
@ -490,15 +486,17 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, Stor
if (orderInfo.getPaid().equals(OrderInfoEnum.PAY_STATUS_HAVE_PAID.getValue())) {
throw exception(ORDER_PAY_FINISH);
}
//如果是小程序或APP 先获取用户openid
MemberUserDO userDO = memberUserService.getUser(uid);
if (PayTypeEnum.WEIXIN_APPLET.getValue().equals(param.getPaytype())) {
//小程序支付需要openid
if (Objects.isNull(userDO.getRoutineOpenid())) throw exception(USER_NOT_BINDING_WX_APPLET);
}
//微信h5支付商户配置
MerchantDetailsDO merchantDetailsDO = merchantDetailsService.getMerchantDetails("4");
// paySuccess(orderInfo.getOrderId(), PayTypeEnum.WEIXIN.getValue());
// Map<String, String> packageParams = new HashMap<String, String>();
// packageParams.put("mwebUrl",URLEncoder.encode(merchantDetailsDO.getReturnUrl(), "GBK"));
MerchantDetailsDO merchantDetailsDO = merchantDetailsService.getMerchantDetails(PayTypeEnum.toType(param.getPaytype()).getCode());
PayContext payContext = new PayContext();
Map<String, String> packageParams = payContext.selectPayWay(PayEnum.WEIXIN.getCode(),
new PayParam(orderInfo.getOrderId(), orderInfo.getPayPrice(), "", ServletUtils.getClientIP(),
new PayParam(orderInfo.getOrderId(), orderInfo.getPayPrice(), userDO.getRoutineOpenid(), ServletUtils.getClientIP(),
param.getPaytype(), "Yshop商城", merchantDetailsDO));
PayInfo payInfo = new PayInfo();
payInfo.setOrderId(orderInfo.getOrderId());
@ -514,7 +512,6 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, Stor
asyncStoreOrderService.orderData(uid);
return packageParams;
}
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void wxPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
@ -1025,6 +1022,8 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, Stor
this.regressionStock(order, 0);
// 取消订单退回优惠券
appCouponRelationService.returnCoupon(order.getCouponId());
this.regressionCoupon(order, 0);
storeOrderMapper.deleteById(order.getId());

View File

@ -55,7 +55,7 @@ public interface ErrorCodeConstants {
ErrorCode PRODUCT_COUPON_NOT_EXISTS = new ErrorCode(1008006001, "优惠券不存在!");
ErrorCode NOT_PRODUCT_COUPON_ERROR = new ErrorCode(1008006002, "无可优惠券!");
ErrorCode NOT_PRODUCT_COUPON_ERROR = new ErrorCode(1008006002, "无可优惠券!");
}

View File

@ -28,11 +28,19 @@ public interface AppCouponRelationService extends IService<ProductCouponRelation
/**
* 核销优惠券
*
* @param id 优惠券id
* @param id 优惠券明细id
* @return
*/
void verificationCoupon(Long id);
/**
* 回退优惠券
*
* @param id 优惠券明细id
* @return
*/
void returnCoupon(Long id);
/**
* 查询用户已有优惠券
*

View File

@ -16,6 +16,7 @@ import co.yixiang.yshop.module.product.enums.coupon.CouponTypeEnum;
import co.yixiang.yshop.module.product.enums.couponrelation.CouponIsUsedEnum;
import co.yixiang.yshop.module.product.enums.couponrelation.CouponSearchTypeEnum;
import co.yixiang.yshop.module.product.service.productcouponrelation.dto.CartCouponDto;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@ -54,10 +55,14 @@ public class AppCouponRelationServiceImpl extends ServiceImpl<ProductCouponRelat
}
long count = count(new LambdaQueryWrapperX<ProductCouponRelationDO>()
.eq(ProductCouponRelationDO::getCouponId, id).eq(ProductCouponRelationDO::getUid, uid));
if (CouponReceiveTypeEnum.UNLIMITED.getValue().equals(couponDO.getReceiveType()) || count < couponDO.getLimitNumber()) {
if (couponDO.getNumber() < 1) throw exception(NOT_PRODUCT_COUPON_ERROR);
if (CouponReceiveTypeEnum.UNLIMITED.getValue().equals(couponDO.getReceiveType())
|| count < couponDO.getLimitNumber()) {
ProductCouponRelationDO relationDO = ProductCouponRelationDO.builder().couponId(id).uid(uid).build();
relationDO.setReceiveTime(LocalDateTime.now());
save(relationDO);
couponMapper.updateById(ProductCouponDO.builder().id(couponDO.getId()).number(couponDO.getNumber() - 1).build());
} else {
throw exception(PRODUCT_COUPON_RECEIVE_ERROR);
}
@ -69,13 +74,21 @@ public class AppCouponRelationServiceImpl extends ServiceImpl<ProductCouponRelat
if (productCouponDO == null) {
throw exception(PRODUCT_COUPON_NOT_EXISTS);
}
// 使用优惠券
// 使用优惠券
productCouponDO.setIsUsed(CouponIsUsedEnum.USED.getValue());
productCouponDO.setUsageTime(LocalDateTime.now());
updateById(productCouponDO);
}
@Override
public void returnCoupon(Long id) {
// 重置优惠券状态
update(new LambdaUpdateWrapper<ProductCouponRelationDO>()
.set(ProductCouponRelationDO::getIsUsed, CouponIsUsedEnum.NOT_USED.getValue())
.set(ProductCouponRelationDO::getUsageTime, null)
.eq(ProductCouponRelationDO::getId, id));
}
@Override
public List<UserCouponVO> searchUserCoupon(Integer type, Long id) {
List<UserCouponVO> userCouponVOS = this.baseMapper.searchUserCoupon(type, getLoginUserId(), id);

View File

@ -45,6 +45,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -244,7 +245,7 @@ public class AppStoreProductServiceImpl extends ServiceImpl<StoreProductMapper,
//获取运费模板名称
String tempName = "";
if (storeProduct.getPostage().intValue() == 0 && storeProduct.getTempId() == 0) {
if(storeProduct.getPostage().compareTo(BigDecimal.ZERO) == 0 && storeProduct.getTempId() == 0) {
tempName = ProductConstants.FREE_POSTAGE;
} else {
ShippingTemplatesDO shippingTemplates = shippingTemplatesService.getById(storeProduct.getTempId());