From 83fc611574f5be8a8da20a155fcd7b3a03e8c666 Mon Sep 17 00:00:00 2001 From: wyn <1074145239@qq.com> Date: Thu, 6 Aug 2026 17:24:35 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=84=E5=90=88=E5=95=86=E5=93=81=20?= =?UTF-8?q?=E5=A4=A9=E5=8C=BB=E5=B8=81=E6=8A=A5=E8=A1=A8=E3=80=81=E5=AE=9E?= =?UTF-8?q?=E7=89=A9=E6=8A=A5=E8=A1=A8=E3=80=81=E8=AF=BE=E7=A8=8B=E6=8A=A5?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../book/controller/BuyOrderController.java | 2 +- .../service/impl/BuyOrderServiceImpl.java | 86 +++++++-- .../modules/common/dao/InvProductCostDao.java | 9 + .../modules/common/dao/InvStockRecordDao.java | 9 + .../common/dao/TransactionDetailsDao.java | 5 + .../modules/common/entity/InvProductCost.java | 30 ++++ .../modules/common/entity/ShopProduct.java | 2 +- .../common/entity/ShopProductBookEntity.java | 6 + .../entity/ShopProductCourseEntity.java | 6 + .../service/impl/BuyOrderServiceImpl.java | 4 +- .../impl/TransactionDetailsServiceImpl.java | 94 +++++++++- .../modules/common/vo/CourseCatalogueVo.java | 5 + .../service/impl/ShopProductServiceImpl.java | 1 + .../impl/UserCourseBuyServiceImpl.java | 13 +- .../resources/mapper/book/BuyOrderDao.xml | 73 +++++++- .../mapper/book/ShopProductBookDao.xml | 1 + .../mapper/book/TransactionDetailsDao.xml | 53 +++++- .../mapper/master/UserCourseBuyDao.xml | 168 +++++++++++++++--- 18 files changed, 498 insertions(+), 69 deletions(-) create mode 100644 src/main/java/com/peanut/modules/common/dao/InvProductCostDao.java create mode 100644 src/main/java/com/peanut/modules/common/dao/InvStockRecordDao.java create mode 100644 src/main/java/com/peanut/modules/common/entity/InvProductCost.java diff --git a/src/main/java/com/peanut/modules/book/controller/BuyOrderController.java b/src/main/java/com/peanut/modules/book/controller/BuyOrderController.java index 391c487..d879aba 100644 --- a/src/main/java/com/peanut/modules/book/controller/BuyOrderController.java +++ b/src/main/java/com/peanut/modules/book/controller/BuyOrderController.java @@ -1357,7 +1357,7 @@ public class BuyOrderController { return false; } System.out.println("=======GoodsType======"+product.getGoodsType()); - return "02".equals(product.getGoodsType()) || "03".equals(product.getGoodsType()) || "04".equals(product.getGoodsType()); + return "02".equals(product.getGoodsType()) || "03".equals(product.getGoodsType()) || "04".equals(product.getGoodsType()) || "07".equals(product.getGoodsType()); } /** diff --git a/src/main/java/com/peanut/modules/book/service/impl/BuyOrderServiceImpl.java b/src/main/java/com/peanut/modules/book/service/impl/BuyOrderServiceImpl.java index 5e45fc3..43f6c62 100644 --- a/src/main/java/com/peanut/modules/book/service/impl/BuyOrderServiceImpl.java +++ b/src/main/java/com/peanut/modules/book/service/impl/BuyOrderServiceImpl.java @@ -498,7 +498,7 @@ public class BuyOrderServiceImpl extends ServiceImpl impl b1.setProduct(byId); b1.setExpressOrder(expressOrderDao.selectById(b1.getExpressOrderId())); boolean refundableStatusProduct = false; - if(b1.getProduct()!=null && b1.getProduct().getGoodsType().equals("05") && (paymentDateTime > timestamp-7*24*60*60*1000 || isHT)){ + if(b1.getProduct()!=null && ("05".equals(b1.getProduct().getGoodsType()) || "07".equals(b1.getProduct().getGoodsType())) && (paymentDateTime > timestamp-7*24*60*60*1000 || isHT)){ refundableStatusProduct = true; }else if(b1.getProduct()!=null && !b1.getProduct().getGoodsType().equals("05") && b.getOrderStatus().equals("1") && b1.getExpressOrderId()==0){ refundableStatusProduct = true; @@ -609,7 +609,7 @@ public class BuyOrderServiceImpl extends ServiceImpl impl bb.setRecordId(userRecord.getId()); } boolean refundableStatusProduct = false; - if (bb.getProduct()!=null && bb.getProduct().getGoodsType().equals("05") && paymentDateTime > timestamp - 7 * 24 * 60 * 60 * 1000) { + if (bb.getProduct()!=null && ("05".equals(bb.getProduct().getGoodsType()) || "07".equals(bb.getProduct().getGoodsType())) && paymentDateTime > timestamp - 7 * 24 * 60 * 60 * 1000) { refundableStatusProduct = true; } else if (bb.getProduct()!=null && !bb.getProduct().getGoodsType().equals("05") && b.getOrderStatus().equals(Constants.ORDER_STATUS_TO_BE_SHIPPED) && bb.getExpressOrderId()==0){ refundableStatusProduct = true; @@ -665,8 +665,8 @@ public class BuyOrderServiceImpl extends ServiceImpl impl ExpressCommodity commodity = new ExpressCommodity(); String productName = product.getProductName()+" ×"+buyOrderProduct.getQuantity()+";"; remark += productName; - //商品类型01挂图02书籍03预售书04仪器05课程06小店商品 - if ("02".equals(product.getGoodsType())||"03".equals(product.getGoodsType())){ + //商品类型01挂图02书籍03预售书04仪器05课程06小店商品07书课组合 + if ("02".equals(product.getGoodsType())||"03".equals(product.getGoodsType())||"07".equals(product.getGoodsType())){ commodity.setGoodsName("书籍"); }else if ("01".equals(product.getGoodsType())){ commodity.setGoodsName("挂图"); @@ -885,6 +885,42 @@ public class BuyOrderServiceImpl extends ServiceImpl impl @Override public void addCourseToUser(String payType,BuyOrder orderEntity){ List orderCourse = getOrderCourse(orderEntity.getOrderSn()); + BigDecimal realMoney = orderEntity.getRealMoney() == null ? BigDecimal.ZERO : orderEntity.getRealMoney(); + BigDecimal jfDeduction = orderEntity.getJfDeduction() == null ? BigDecimal.ZERO : orderEntity.getJfDeduction(); + + // 07 书课组合:按 shop_product_book/course.product_price 占比分摊实付与积分 + Map comboTotalMap = new HashMap<>(); + Map comboCourseSumMap = new HashMap<>(); + Map comboAllocatedFee = new HashMap<>(); + Map comboAllocatedJf = new HashMap<>(); + Map comboRemainCount = new HashMap<>(); + Set comboProductIds = orderCourse.stream() + .filter(c -> "07".equals(c.getGoodsType()) && c.getProductId() != null) + .map(ShopProductCourseEntity::getProductId) + .collect(Collectors.toSet()); + for (Integer productId : comboProductIds) { + BigDecimal bookSum = shopProductBookDao.selectList(new LambdaQueryWrapper() + .eq(ShopProductBookEntity::getProductId, productId)) + .stream() + .map(ShopProductBookEntity::getProductPrice) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal courseSum = shopProductCourseDao.selectList(new LambdaQueryWrapper() + .eq(ShopProductCourseEntity::getProductId, productId)) + .stream() + .map(ShopProductCourseEntity::getProductPrice) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + comboTotalMap.put(productId, bookSum.add(courseSum)); + comboCourseSumMap.put(productId, courseSum); + comboAllocatedFee.put(productId, BigDecimal.ZERO); + comboAllocatedJf.put(productId, BigDecimal.ZERO); + long cnt = orderCourse.stream() + .filter(c -> "07".equals(c.getGoodsType()) && productId.equals(c.getProductId())) + .count(); + comboRemainCount.put(productId, (int) cnt); + } + for (int i=0;i wrapper2 = new LambdaQueryWrapper<>(); @@ -926,16 +962,44 @@ public class BuyOrderServiceImpl extends ServiceImpl impl userCourseBuyLog.setBeginDay(0); userCourseBuyLog.setDays(s.getDays()); } - //商品类型不是课程,视为赠送课程,报表金额为0 - if (!"05".equals(s.getGoodsType())){ + if ("07".equals(s.getGoodsType())) { + // 书课组合:课价部分进摊销,书价部分不进 + Integer productId = s.getProductId(); + BigDecimal total = comboTotalMap.getOrDefault(productId, BigDecimal.ZERO); + BigDecimal courseSum = comboCourseSumMap.getOrDefault(productId, BigDecimal.ZERO); + BigDecimal coursePrice = s.getProductPrice() == null ? BigDecimal.ZERO : s.getProductPrice(); + if (total.compareTo(BigDecimal.ZERO) <= 0 || courseSum.compareTo(BigDecimal.ZERO) <= 0) { + userCourseBuyLog.setFee(BigDecimal.ZERO); + userCourseBuyLog.setJf(BigDecimal.ZERO); + } else { + int remain = comboRemainCount.getOrDefault(productId, 1); + BigDecimal coursePool = realMoney.multiply(courseSum).divide(total, 2, RoundingMode.HALF_UP); + BigDecimal jfPool = jfDeduction.multiply(courseSum).divide(total, 2, RoundingMode.HALF_UP); + BigDecimal fee; + BigDecimal jf; + if (remain <= 1) { + fee = coursePool.subtract(comboAllocatedFee.getOrDefault(productId, BigDecimal.ZERO)); + jf = jfPool.subtract(comboAllocatedJf.getOrDefault(productId, BigDecimal.ZERO)); + } else { + fee = realMoney.multiply(coursePrice).divide(total, 2, RoundingMode.HALF_UP); + jf = jfDeduction.multiply(coursePrice).divide(total, 2, RoundingMode.HALF_UP); + comboAllocatedFee.put(productId, comboAllocatedFee.get(productId).add(fee)); + comboAllocatedJf.put(productId, comboAllocatedJf.get(productId).add(jf)); + } + comboRemainCount.put(productId, remain - 1); + userCourseBuyLog.setFee(fee); + userCourseBuyLog.setJf(jf); + } + } else if (!"05".equals(s.getGoodsType())){ + //商品类型不是课程,视为赠送课程,报表金额为0 userCourseBuyLog.setFee(BigDecimal.ZERO); userCourseBuyLog.setJf(BigDecimal.ZERO); }else { - BigDecimal fee = orderEntity.getRealMoney().divide(new BigDecimal(orderCourse.size()),2, BigDecimal.ROUND_HALF_UP); - BigDecimal jf = orderEntity.getJfDeduction().divide(new BigDecimal(orderCourse.size()),2, BigDecimal.ROUND_HALF_UP); + BigDecimal fee = realMoney.divide(new BigDecimal(orderCourse.size()),2, RoundingMode.HALF_UP); + BigDecimal jf = jfDeduction.divide(new BigDecimal(orderCourse.size()),2, RoundingMode.HALF_UP); if (i==(orderCourse.size()-1)){ - userCourseBuyLog.setFee(orderEntity.getRealMoney().subtract(fee.multiply(new BigDecimal(orderCourse.size()-1)))); - userCourseBuyLog.setJf(orderEntity.getJfDeduction().subtract(jf.multiply(new BigDecimal(orderCourse.size()-1)))); + userCourseBuyLog.setFee(realMoney.subtract(fee.multiply(new BigDecimal(orderCourse.size()-1)))); + userCourseBuyLog.setJf(jfDeduction.subtract(jf.multiply(new BigDecimal(orderCourse.size()-1)))); }else { userCourseBuyLog.setFee(fee); userCourseBuyLog.setJf(jf); @@ -949,7 +1013,7 @@ public class BuyOrderServiceImpl extends ServiceImpl impl public boolean checkWlOrder(String orderSn) { BuyOrder one = this.getOne(new LambdaQueryWrapper().eq(BuyOrder::getOrderSn, orderSn)); List collect = buyOrderProductDao.selectList(new LambdaQueryWrapper().eq(BuyOrderProduct::getOrderId, one.getOrderId())).stream().map(BuyOrderProduct::getProductId).collect(Collectors.toList()); - List shopProducts = shopProductDao.selectList(new LambdaQueryWrapper().in(ShopProduct::getProductId, collect).ne(ShopProduct::getGoodsType,5)); + List shopProducts = shopProductDao.selectList(new LambdaQueryWrapper().in(ShopProduct::getProductId, collect).ne(ShopProduct::getGoodsType,"05")); return shopProducts.size()>0?true:false; } diff --git a/src/main/java/com/peanut/modules/common/dao/InvProductCostDao.java b/src/main/java/com/peanut/modules/common/dao/InvProductCostDao.java new file mode 100644 index 0000000..89836a5 --- /dev/null +++ b/src/main/java/com/peanut/modules/common/dao/InvProductCostDao.java @@ -0,0 +1,9 @@ +package com.peanut.modules.common.dao; + +import com.github.yulichang.base.MPJBaseMapper; +import com.peanut.modules.common.entity.InvProductCost; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface InvProductCostDao extends MPJBaseMapper { +} diff --git a/src/main/java/com/peanut/modules/common/dao/InvStockRecordDao.java b/src/main/java/com/peanut/modules/common/dao/InvStockRecordDao.java new file mode 100644 index 0000000..0020cfb --- /dev/null +++ b/src/main/java/com/peanut/modules/common/dao/InvStockRecordDao.java @@ -0,0 +1,9 @@ +package com.peanut.modules.common.dao; + +import com.github.yulichang.base.MPJBaseMapper; +import com.peanut.modules.common.entity.InvStockRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface InvStockRecordDao extends MPJBaseMapper { +} diff --git a/src/main/java/com/peanut/modules/common/dao/TransactionDetailsDao.java b/src/main/java/com/peanut/modules/common/dao/TransactionDetailsDao.java index 6512340..dc38566 100644 --- a/src/main/java/com/peanut/modules/common/dao/TransactionDetailsDao.java +++ b/src/main/java/com/peanut/modules/common/dao/TransactionDetailsDao.java @@ -25,4 +25,9 @@ public interface TransactionDetailsDao extends BaseMapper> getTransactionDetailsInfo(@Param("date") String date); List> getRefundTransactionDetails(@Param("date") String date); + + /** + * 书课组合(07)订单拆分标价与名称,按 order_sn 批量查询 + */ + List> getComboSplitByOrderSns(@Param("orderSns") List orderSns); } diff --git a/src/main/java/com/peanut/modules/common/entity/InvProductCost.java b/src/main/java/com/peanut/modules/common/entity/InvProductCost.java new file mode 100644 index 0000000..cc5ce9f --- /dev/null +++ b/src/main/java/com/peanut/modules/common/entity/InvProductCost.java @@ -0,0 +1,30 @@ +package com.peanut.modules.common.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 商品成本价 + */ +@Data +@TableName("inv_product_cost") +public class InvProductCost { + + @TableId(type = IdType.AUTO) + private Long id; + /** 商品ID */ + private Integer productId; + /** 商品名称 */ + private String name; + /** 成本价 */ + private BigDecimal costPrice; + /** 商户标识 1灵枢 2众秒 */ + private Integer merchantId; + private Date createTime; + private Date updateTime; +} diff --git a/src/main/java/com/peanut/modules/common/entity/ShopProduct.java b/src/main/java/com/peanut/modules/common/entity/ShopProduct.java index 3aa8f15..992a757 100644 --- a/src/main/java/com/peanut/modules/common/entity/ShopProduct.java +++ b/src/main/java/com/peanut/modules/common/entity/ShopProduct.java @@ -137,7 +137,7 @@ public class ShopProduct implements Serializable { */ private Integer sumSales; /** - * 商品类型01挂图02书籍03预售书04仪器05课程06小店商品 + * 商品类型01挂图02书籍03预售书04仪器05课程06小店商品07书课组合 */ private String goodsType; private String goodsTypeCode; diff --git a/src/main/java/com/peanut/modules/common/entity/ShopProductBookEntity.java b/src/main/java/com/peanut/modules/common/entity/ShopProductBookEntity.java index d9df834..e49224e 100644 --- a/src/main/java/com/peanut/modules/common/entity/ShopProductBookEntity.java +++ b/src/main/java/com/peanut/modules/common/entity/ShopProductBookEntity.java @@ -3,6 +3,7 @@ package com.peanut.modules.common.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; @@ -30,6 +31,11 @@ public class ShopProductBookEntity { */ @TableField("book_ids") private Integer bookIds; + /** + * 书籍拆分标价(组合商品按比例分摊用) + */ + @TableField("product_price") + private BigDecimal productPrice; /** * 删除标记 */ diff --git a/src/main/java/com/peanut/modules/common/entity/ShopProductCourseEntity.java b/src/main/java/com/peanut/modules/common/entity/ShopProductCourseEntity.java index c0ee3ab..7426aef 100644 --- a/src/main/java/com/peanut/modules/common/entity/ShopProductCourseEntity.java +++ b/src/main/java/com/peanut/modules/common/entity/ShopProductCourseEntity.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import java.math.BigDecimal; import java.util.Date; @Data @@ -23,6 +24,11 @@ public class ShopProductCourseEntity { private Integer days; + /** + * 课程拆分标价(组合商品按比例分摊用) + */ + private BigDecimal productPrice; + private Date createTime; @TableLogic diff --git a/src/main/java/com/peanut/modules/common/service/impl/BuyOrderServiceImpl.java b/src/main/java/com/peanut/modules/common/service/impl/BuyOrderServiceImpl.java index f1c25b9..c41f8f1 100644 --- a/src/main/java/com/peanut/modules/common/service/impl/BuyOrderServiceImpl.java +++ b/src/main/java/com/peanut/modules/common/service/impl/BuyOrderServiceImpl.java @@ -124,7 +124,7 @@ public class BuyOrderServiceImpl extends ServiceImpl impl w.disableLogicDel().eq(ShopProduct::getProductId,bb.getProductId()); bb.setProduct(shopProductDao.selectOne(w)); boolean refundableStatusProduct = false; - if(bb.getProduct()!=null && bb.getProduct().getGoodsType().equals("05") && (paymentDateTime > timestamp-7*24*60*60*1000)){ + if(bb.getProduct()!=null && ("05".equals(bb.getProduct().getGoodsType()) || "07".equals(bb.getProduct().getGoodsType())) && (paymentDateTime > timestamp-7*24*60*60*1000)){ refundableStatusProduct = true; }else if(bb.getProduct()!=null && !bb.getProduct().getGoodsType().equals("05") && b.getOrderStatus().equals("1") && bb.getExpressOrderId()==0){ refundableStatusProduct = true; @@ -203,7 +203,7 @@ public class BuyOrderServiceImpl extends ServiceImpl impl List productInfo = buyOrderProductDao.selectJoinList(ShopProduct.class,buyOrderProductWrapper); //添加关联课程id for (ShopProduct sp:productInfo){ - if (sp.getGoodsType()!=null&&"05".equals(sp.getGoodsType())){ + if (sp.getGoodsType()!=null&&("05".equals(sp.getGoodsType()) || "07".equals(sp.getGoodsType()))){ List list = shopProductCourseDao.selectList(new LambdaQueryWrapper() .eq(ShopProductCourseEntity::getProductId,sp.getProductId())); sp.setCourseIds(list); diff --git a/src/main/java/com/peanut/modules/common/service/impl/TransactionDetailsServiceImpl.java b/src/main/java/com/peanut/modules/common/service/impl/TransactionDetailsServiceImpl.java index b5cbf3c..234eca9 100644 --- a/src/main/java/com/peanut/modules/common/service/impl/TransactionDetailsServiceImpl.java +++ b/src/main/java/com/peanut/modules/common/service/impl/TransactionDetailsServiceImpl.java @@ -7,8 +7,15 @@ import com.peanut.modules.common.service.TransactionDetailsService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; @Slf4j @Service("commonTransactionDetailsService") @@ -31,6 +38,91 @@ public class TransactionDetailsServiceImpl extends ServiceImpl> getTransactionDetailsInfo(String date) { - return this.baseMapper.getTransactionDetailsInfo(date); + List> list = this.baseMapper.getTransactionDetailsInfo(date); + List comboOrderSns = list.stream() + .filter(row -> "实物、课程".equals(Objects.toString(row.get("goodsType"), ""))) + .map(row -> Objects.toString(row.get("payNo"), "")) + .filter(sn -> !sn.isEmpty()) + .distinct() + .collect(Collectors.toList()); + if (comboOrderSns.isEmpty()) { + return list; + } + Map> splitBySn = new HashMap<>(); + for (Map split : this.baseMapper.getComboSplitByOrderSns(comboOrderSns)) { + splitBySn.put(Objects.toString(split.get("orderSn"), ""), split); + } + List> result = new ArrayList<>(list.size() + comboOrderSns.size()); + for (Map row : list) { + if (!"实物、课程".equals(Objects.toString(row.get("goodsType"), ""))) { + result.add(row); + continue; + } + Map split = splitBySn.get(Objects.toString(row.get("payNo"), "")); + if (split == null + || toInt(split.get("comboCnt")) <= 0 + || toInt(split.get("otherCnt")) > 0) { + result.add(row); + continue; + } + BigDecimal coursePrice = toBd(split.get("coursePriceSum")); + BigDecimal bookPrice = toBd(split.get("bookPriceSum")); + BigDecimal priceSum = coursePrice.add(bookPrice); + if (priceSum.compareTo(BigDecimal.ZERO) <= 0) { + result.add(row); + continue; + } + BigDecimal total = toBd(row.get("changeAmount")); + BigDecimal courseAmt = total.multiply(coursePrice).divide(priceSum, 2, RoundingMode.HALF_UP); + BigDecimal bookAmt = total.subtract(courseAmt); + String originName = Objects.toString(row.get("productName"), ""); + String courseNames = Objects.toString(split.get("courseNames"), ""); + String bookNames = Objects.toString(split.get("bookNames"), ""); + + Map courseRow = new LinkedHashMap<>(row); + courseRow.put("goodsType", "课程"); + courseRow.put("productName", courseNames.isEmpty() ? originName : courseNames); + courseRow.put("changeAmount", courseAmt); + + Map bookRow = new LinkedHashMap<>(row); + bookRow.put("goodsType", "实物"); + bookRow.put("productName", bookNames.isEmpty() ? originName : bookNames); + bookRow.put("changeAmount", bookAmt); + + result.add(courseRow); + result.add(bookRow); + } + return result; + } + + private static int toInt(Object v) { + if (v == null) { + return 0; + } + if (v instanceof Number) { + return ((Number) v).intValue(); + } + try { + return new BigDecimal(v.toString()).intValue(); + } catch (Exception e) { + return 0; + } + } + + private static BigDecimal toBd(Object v) { + if (v == null) { + return BigDecimal.ZERO; + } + if (v instanceof BigDecimal) { + return (BigDecimal) v; + } + if (v instanceof Number) { + return BigDecimal.valueOf(((Number) v).doubleValue()); + } + try { + return new BigDecimal(v.toString()); + } catch (Exception e) { + return BigDecimal.ZERO; + } } } diff --git a/src/main/java/com/peanut/modules/common/vo/CourseCatalogueVo.java b/src/main/java/com/peanut/modules/common/vo/CourseCatalogueVo.java index a51f914..0b53783 100644 --- a/src/main/java/com/peanut/modules/common/vo/CourseCatalogueVo.java +++ b/src/main/java/com/peanut/modules/common/vo/CourseCatalogueVo.java @@ -2,6 +2,8 @@ package com.peanut.modules.common.vo; import lombok.Data; +import java.math.BigDecimal; + @Data public class CourseCatalogueVo { @@ -16,4 +18,7 @@ public class CourseCatalogueVo { private String image; private Integer days; + + /** 课程拆分标价(组合商品分摊用) */ + private BigDecimal productPrice; } diff --git a/src/main/java/com/peanut/modules/master/service/impl/ShopProductServiceImpl.java b/src/main/java/com/peanut/modules/master/service/impl/ShopProductServiceImpl.java index 45a01ad..3381779 100644 --- a/src/main/java/com/peanut/modules/master/service/impl/ShopProductServiceImpl.java +++ b/src/main/java/com/peanut/modules/master/service/impl/ShopProductServiceImpl.java @@ -282,6 +282,7 @@ public class ShopProductServiceImpl extends ServiceImpl refundChapterCountMap = new HashMap<>(); - for (Map refund : refundMap.values()) { - String orderCourseKey = String.valueOf(refund.get("orderSn")) + "|" + String.valueOf(refund.get("ctitle")); - refundChapterCountMap.merge(orderCourseKey, 1, Integer::sum); - } for (Map refund : refundMap.values()) { String key = refundKey(refund); if (matchedKeys.contains(key)) { continue; } + // fee 已在 getRefundInfo 按目录数/组合占比拆好,此处不再按课程名二次平分 Map adjustedRefund = new HashMap<>(refund); - String orderCourseKey = String.valueOf(refund.get("orderSn")) + "|" + String.valueOf(refund.get("ctitle")); - int chapterCount = refundChapterCountMap.getOrDefault(orderCourseKey, 1); - if (chapterCount > 1) { - BigDecimal dividedFee = toBigDecimal(refund.get("fee")) - .divide(BigDecimal.valueOf(chapterCount), 2, RoundingMode.HALF_UP); - adjustedRefund.put("fee", dividedFee); - } String payMonth = getPayMonth(refund); if (exportMonth.equals(payMonth)) { Map paidRow = buildPaidRowFromRefund(adjustedRefund); diff --git a/src/main/resources/mapper/book/BuyOrderDao.xml b/src/main/resources/mapper/book/BuyOrderDao.xml index feb3e85..4a738f1 100644 --- a/src/main/resources/mapper/book/BuyOrderDao.xml +++ b/src/main/resources/mapper/book/BuyOrderDao.xml @@ -50,13 +50,66 @@ + + + + left join ( + select bop05.order_id, + SUM(IF(sp05.activity_price < sp05.price, sp05.activity_price, sp05.price)) course05Sum + from buy_order_product bop05 + inner join shop_product sp05 on sp05.product_id = bop05.product_id and sp05.goods_type = '05' + group by bop05.order_id + ) c05 on c05.order_id = t.order_id + left join ( + select bop07.order_id, + IFNULL(SUM(spc_sum.s), 0) cs, + IFNULL(SUM(spb_sum.s), 0) bs + from buy_order_product bop07 + inner join shop_product sp07 on sp07.product_id = bop07.product_id and sp07.goods_type = '07' + left join ( + select product_id, SUM(IFNULL(product_price, 0)) s + from shop_product_course + where del_flag = 0 + group by product_id + ) spc_sum on spc_sum.product_id = sp07.product_id + left join ( + select product_id, SUM(IFNULL(product_price, 0)) s + from shop_product_book + where del_flag = 0 + group by product_id + ) spb_sum on spb_sum.product_id = sp07.product_id + group by bop07.order_id + ) c07 on c07.order_id = t.order_id + + + + + ${baseAmount} + - IFNULL(c05.course05Sum, 0) + - IFNULL(ROUND(${baseAmount} * IFNULL(c07.cs, 0) / NULLIF(IFNULL(c07.cs, 0) + IFNULL(c07.bs, 0), 0), 2), 0) + + + + GROUP_CONCAT( + IF(sp.goods_type = '07', + IFNULL(( + select GROUP_CONCAT(bk.name SEPARATOR '/') + from shop_product_book spb + inner join book bk on bk.id = spb.book_id + where spb.product_id = sp.product_id and spb.del_flag = 0 + ), sp.product_name), + sp.product_name + ) SEPARATOR ', ' + ) + + diff --git a/src/main/resources/mapper/book/TransactionDetailsDao.xml b/src/main/resources/mapper/book/TransactionDetailsDao.xml index e8908d2..4053ed9 100644 --- a/src/main/resources/mapper/book/TransactionDetailsDao.xml +++ b/src/main/resources/mapper/book/TransactionDetailsDao.xml @@ -30,7 +30,7 @@ select q.*,pzo.trade_no zfbOrder from ( select t.*, - IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF((GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,'),'实物、课程',IF(GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05','课程',IF(bo.order_type='relearn','课程',IF(bo.order_type='trainingClass','培训班',IF(bo.order_type='vip','VIP','实物')))))) goodsType, + IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF(FIND_IN_SET('07',GROUP_CONCAT(sp.goods_type SEPARATOR ',')) or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,'),'实物、课程',IF(GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05','课程',IF(bo.order_type='relearn','课程',IF(bo.order_type='trainingClass','培训班',IF(bo.order_type='vip','VIP','实物')))))) goodsType, IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ','))) productName from ( select td.transaction_id id,DATE_FORMAT(td.create_time,'%Y-%m-%d %H:%i:%s') createTime,u.name,if(u.tel is null,if(u.email is null,'',u.email),u.tel) tel @@ -61,8 +61,8 @@ IF(bo.order_type='relearn','课程', IF(bo.order_type='trainingClass','培训班', IF(bo.order_type='vip','VIP', - IF((GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05'), - IF((GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,%'),'实物、课程','课程'), + IF(FIND_IN_SET('07',GROUP_CONCAT(sp.goods_type SEPARATOR ',')) or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05'), + IF(FIND_IN_SET('07',GROUP_CONCAT(sp.goods_type SEPARATOR ',')) or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,%'),'实物、课程','课程'), '实物')))) goodsType, IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ','))) productName from ( @@ -92,7 +92,7 @@ select q.*,pzo.trade_no zfbOrder from ( select t.*, - IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF((GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,'),'实物、课程',IF(GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05','课程',IF(bo.order_type='relearn','课程',IF(bo.order_type='trainingClass','培训班',IF(bo.order_type='vip','VIP','实物')))))) goodsType, + IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF(FIND_IN_SET('07',GROUP_CONCAT(sp.goods_type SEPARATOR ',')) or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '%,05%') or (GROUP_CONCAT(sp.goods_type SEPARATOR ',') like '05,'),'实物、课程',IF(GROUP_CONCAT(sp.goods_type SEPARATOR ',')='05','课程',IF(bo.order_type='relearn','课程',IF(bo.order_type='trainingClass','培训班',IF(bo.order_type='vip','VIP','实物')))))) goodsType, IF(IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ',')) is NULL,'',IF(GROUP_CONCAT(sp.product_name SEPARATOR ',') is NULL,IF(bo.order_type='vip',vbc.title,bo.remark),GROUP_CONCAT(sp.product_name SEPARATOR ','))) productName from ( select td.transaction_id id,DATE_FORMAT(td.create_time,'%Y-%m-%d %H:%i:%s') createTime,u.name,if(u.tel is null,if(u.email is null,'',u.email),u.tel) tel @@ -113,4 +113,49 @@ left join pay_zfb_order pzo on pzo.relevanceOid = q.payNo and pzo.trade_no is not null + + \ No newline at end of file diff --git a/src/main/resources/mapper/master/UserCourseBuyDao.xml b/src/main/resources/mapper/master/UserCourseBuyDao.xml index 16f9969..99f2767 100644 --- a/src/main/resources/mapper/master/UserCourseBuyDao.xml +++ b/src/main/resources/mapper/master/UserCourseBuyDao.xml @@ -68,7 +68,33 @@ select pay_type,SUM(fee) fee from ( select IF(bo.payment_method='1','App微信',IF(bo.payment_method='2','App支付宝',IF(bo.payment_method='4','App天医币','其他'))) pay_type, - bor.fee + CASE + WHEN EXISTS ( + select 1 from buy_order_product bop0 + inner join shop_product sp0 on sp0.product_id = bop0.product_id + where bop0.order_id = bo.order_id and sp0.goods_type = '07' + ) THEN ROUND(bor.fee * ( + (select IFNULL(SUM(spc.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_course spc on spc.product_id = sp1.product_id and spc.del_flag = 0 + where bop1.order_id = bo.order_id) + / NULLIF(( + (select IFNULL(SUM(spc.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_course spc on spc.product_id = sp1.product_id and spc.del_flag = 0 + where bop1.order_id = bo.order_id) + + + (select IFNULL(SUM(spb.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_book spb on spb.product_id = sp1.product_id and spb.del_flag = 0 + where bop1.order_id = bo.order_id) + ), 0) + ), 2) + ELSE bor.fee + END as fee from buy_order_refund bor inner join buy_order bo on bo.order_id = bor.order_id and bo.del_flag = 0 where bo.order_status = '6' @@ -78,7 +104,7 @@ and (bo.order_type = 'relearn' or exists ( select 1 from buy_order_product bop inner join shop_product sp on sp.product_id = bop.product_id - where bop.order_id = bo.order_id and sp.goods_type = '05' + where bop.order_id = bo.order_id and sp.goods_type in ('05','07') )) ) t GROUP BY pay_type @@ -87,7 +113,33 @@ select pay_type,SUM(fee) fee from ( select IF(bo.payment_method='1','微信',IF(bo.payment_method='2','支付宝',IF(bo.payment_method='4','天医币','其他'))) pay_type, - bor.fee + CASE + WHEN EXISTS ( + select 1 from buy_order_product bop0 + inner join shop_product sp0 on sp0.product_id = bop0.product_id + where bop0.order_id = bo.order_id and sp0.goods_type = '07' + ) THEN ROUND(bor.fee * ( + (select IFNULL(SUM(spc.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_course spc on spc.product_id = sp1.product_id and spc.del_flag = 0 + where bop1.order_id = bo.order_id) + / NULLIF(( + (select IFNULL(SUM(spc.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_course spc on spc.product_id = sp1.product_id and spc.del_flag = 0 + where bop1.order_id = bo.order_id) + + + (select IFNULL(SUM(spb.product_price), 0) + from buy_order_product bop1 + inner join shop_product sp1 on sp1.product_id = bop1.product_id and sp1.goods_type = '07' + inner join shop_product_book spb on spb.product_id = sp1.product_id and spb.del_flag = 0 + where bop1.order_id = bo.order_id) + ), 0) + ), 2) + ELSE bor.fee + END as fee from buy_order_refund bor inner join buy_order bo on bo.order_id = bor.order_id and bo.del_flag = 0 where bo.order_status = '6' @@ -98,7 +150,7 @@ and (bo.order_type = 'relearn' or exists ( select 1 from buy_order_product bop inner join shop_product sp on sp.product_id = bop.product_id - where bop.order_id = bo.order_id and sp.goods_type = '05' + where bop.order_id = bo.order_id and sp.goods_type in ('05','07') )) ) t GROUP BY pay_type @@ -112,31 +164,89 @@ DATE_FORMAT(IF(bo.success_time is null,bo.create_time,bo.success_time),'%Y-%m-%d %H:%i:%s') payTime, bo.order_sn orderSn,pzo.trade_no zfbOrder, 0 beginDay,IFNULL(spc.days,0) days, - ROUND( - bor.fee / ( - case - when bo.order_type='relearn' then - IFNULL(( - select count(1) - from shop_product_course spc2 - where spc2.product_id = ( - case - when bo.remark is null or bo.remark = '' then null - else cast(SUBSTRING_INDEX(bo.remark, ',', 1) as unsigned) - end - ) - and spc2.del_flag = 0 - ),1) - else - IFNULL(( + CASE + WHEN sp.goods_type = '07' THEN + CASE + WHEN spc.id = ( + select MAX(spc_last.id) from shop_product_course spc_last + where spc_last.product_id = sp.product_id and spc_last.del_flag = 0 + ) THEN + ROUND(bor.fee * ( + select IFNULL(SUM(spc_cs.product_price), 0) from shop_product_course spc_cs + where spc_cs.product_id = sp.product_id and spc_cs.del_flag = 0 + ) / NULLIF(( + (select IFNULL(SUM(spc_cs.product_price), 0) from shop_product_course spc_cs where spc_cs.product_id = sp.product_id and spc_cs.del_flag = 0) + + (select IFNULL(SUM(spb.product_price), 0) from shop_product_book spb where spb.product_id = sp.product_id and spb.del_flag = 0) + ), 0), 2) + - IFNULL(( + select SUM(ROUND(bor.fee * IFNULL(spc_o.product_price, 0) / NULLIF(( + (select IFNULL(SUM(spc_cs.product_price), 0) from shop_product_course spc_cs where spc_cs.product_id = sp.product_id and spc_cs.del_flag = 0) + + (select IFNULL(SUM(spb.product_price), 0) from shop_product_book spb where spb.product_id = sp.product_id and spb.del_flag = 0) + ), 0), 2)) + from shop_product_course spc_o + where spc_o.product_id = sp.product_id and spc_o.del_flag = 0 + and spc_o.id <> ( + select MAX(spc_last.id) from shop_product_course spc_last + where spc_last.product_id = sp.product_id and spc_last.del_flag = 0 + ) + ), 0) + ELSE + ROUND(bor.fee * IFNULL(spc.product_price, 0) / NULLIF(( + (select IFNULL(SUM(spc_cs.product_price), 0) from shop_product_course spc_cs where spc_cs.product_id = sp.product_id and spc_cs.del_flag = 0) + + (select IFNULL(SUM(spb.product_price), 0) from shop_product_book spb where spb.product_id = sp.product_id and spb.del_flag = 0) + ), 0), 2) + END + WHEN bo.order_type = 'relearn' THEN + CASE + WHEN spc.id = ( + select MAX(spc_last.id) from shop_product_course spc_last + where spc_last.product_id = sp.product_id and spc_last.del_flag = 0 + ) THEN + bor.fee - ROUND(bor.fee / IFNULL(( + select count(1) from shop_product_course spc2 + where spc2.product_id = sp.product_id and spc2.del_flag = 0 + ), 1), 2) * (IFNULL(( + select count(1) from shop_product_course spc2 + where spc2.product_id = sp.product_id and spc2.del_flag = 0 + ), 1) - 1) + ELSE + ROUND(bor.fee / IFNULL(( + select count(1) from shop_product_course spc2 + where spc2.product_id = sp.product_id and spc2.del_flag = 0 + ), 1), 2) + END + ELSE + CASE + WHEN spc.id = ( + select MAX(spc_last.id) + from buy_order_product bop_last + inner join shop_product sp_last on sp_last.product_id = bop_last.product_id and sp_last.goods_type = '05' + inner join shop_product_course spc_last on spc_last.product_id = sp_last.product_id and spc_last.del_flag = 0 + where bop_last.order_id = bo.order_id + ) THEN + bor.fee - ROUND(bor.fee / IFNULL(( select count(1) from buy_order_product bop2 - inner join shop_product sp2 on sp2.product_id = bop2.product_id - where bop2.order_id = bo.order_id and sp2.goods_type = '05' - ),1) - end - ),2 - ) fee, + inner join shop_product sp2 on sp2.product_id = bop2.product_id and sp2.goods_type = '05' + inner join shop_product_course spc2 on spc2.product_id = sp2.product_id and spc2.del_flag = 0 + where bop2.order_id = bo.order_id + ), 1), 2) * (IFNULL(( + select count(1) + from buy_order_product bop2 + inner join shop_product sp2 on sp2.product_id = bop2.product_id and sp2.goods_type = '05' + inner join shop_product_course spc2 on spc2.product_id = sp2.product_id and spc2.del_flag = 0 + where bop2.order_id = bo.order_id + ), 1) - 1) + ELSE + ROUND(bor.fee / IFNULL(( + select count(1) + from buy_order_product bop2 + inner join shop_product sp2 on sp2.product_id = bop2.product_id and sp2.goods_type = '05' + inner join shop_product_course spc2 on spc2.product_id = sp2.product_id and spc2.del_flag = 0 + where bop2.order_id = bo.order_id + ), 1), 2) + END + END fee, if(bo.remark like '%退%',bo.remark,if(bor.remark is null,'',bor.remark)) remark, DATE_FORMAT(bor.create_time,'%Y-%m-%d %H:%i:%s') refundTime, '已退款' orderStatus @@ -154,7 +264,7 @@ else bop.product_id end ) - and sp.goods_type = '05' + and sp.goods_type in ('05','07') left join shop_product_course spc on spc.product_id = sp.product_id and spc.del_flag = 0 left join course c on c.id = spc.course_id left join course_catalogue cc on cc.id = spc.catalogue_id @@ -219,7 +329,7 @@ left join user_course_buy_log ucbl on ucbl.user_course_buy_id = ucb.id left join buy_order bo on bo.order_sn = ucbl.order_sn left join buy_order_product bop on bop.order_id = bo.order_id - left join shop_product sp on sp.product_id = bop.product_id and sp.goods_type = '05' + left join shop_product sp on sp.product_id = bop.product_id and sp.goods_type in ('05','07') where u.del_flag = 0 and u.tester_flag = 0 and ucb.course_id = #{courseId} and catalogue_id = #{catalogueId} order by pay_time desc