licailing 5 лет назад
Родитель
Сommit
35829bda3a

+ 4 - 0
src/main/java/com/izouma/jiashanxia/domain/OrderInfo.java

@@ -66,4 +66,8 @@ public class OrderInfo extends BaseEntity {
     @NotFound(action = NotFoundAction.IGNORE)
     private User user;
 
+    private boolean isUse;
+
+    @ApiModelProperty(value = "多次使用")
+    private boolean repeatedly;
 }

+ 12 - 0
src/main/java/com/izouma/jiashanxia/domain/Package.java

@@ -55,6 +55,18 @@ public class Package extends BaseEntity {
     @ApiModelProperty(value = "多次使用")
     private boolean repeatedly;
 
+    @ApiModelProperty(value = "大达人奖励比例")
+    private BigDecimal bigExpertRatio;
+
+    @ApiModelProperty(value = "创客奖励比例")
+    private BigDecimal makerRatio;
+
+    @ApiModelProperty(value = "直推奖励比例")
+    private BigDecimal personalRatio0;
+
+    @ApiModelProperty(value = "间推奖励比例")
+    private BigDecimal personalRatio1;
+
     @Transient
     private String attractionsName;
 

+ 7 - 4
src/main/java/com/izouma/jiashanxia/domain/User.java

@@ -81,11 +81,14 @@ public class User extends BaseEntity implements Serializable {
     @ApiModelProperty(value = "暂存")
     private BigDecimal cacheAmount;
 
-    @ApiModelProperty(value = "分销")
-    private BigDecimal distribution;
+    @ApiModelProperty(value = "推广")
+    private BigDecimal promote;
 
-    @ApiModelProperty(value = "再分销")
-    private BigDecimal redistribution;
+    @ApiModelProperty(value = "间推")
+    private BigDecimal childPromote;
+
+    @ApiModelProperty(value = "大达人额外奖励")
+    private BigDecimal bigExpert;
 
     private Long parent;
 

+ 10 - 5
src/main/java/com/izouma/jiashanxia/dto/WriteOffSaveVO.java

@@ -1,6 +1,5 @@
 package com.izouma.jiashanxia.dto;
 
-import com.izouma.jiashanxia.domain.BaseEntity;
 import com.izouma.jiashanxia.enums.PackageType;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -15,7 +14,7 @@ import javax.persistence.*;
 @NoArgsConstructor
 @Builder
 @ApiModel(value = "核销记录保存")
-public class WriteOffSaveVO extends BaseEntity {
+public class WriteOffSaveVO {
 
     @ApiModelProperty(value = "被核销人")
     private Long userId;
@@ -23,15 +22,21 @@ public class WriteOffSaveVO extends BaseEntity {
     @ApiModelProperty(value = "核销人")
     private Long writeOffUserId;
 
-    @ApiModelProperty(value = "类型")
-    private PackageType type;
+//    @ApiModelProperty(value = "类型")
+//    private PackageType type;
 
 //    @ApiModelProperty(value = "套餐有效期id")
 //    private Long userPackagePeriodId;
 
     /*
+    单次使用传订单号
+     */
+    @ApiModelProperty(value = "订单号")
+    private Long orderInfoId;
+
+    /*
+    多次使用传内容
     存储内容
-    "userPackageId":1,
     [{"goodsInfoId":11,"num":1},{"goodsInfoId":12,"num":1}]
      */
     @Column(columnDefinition = "TEXT")

+ 5 - 1
src/main/java/com/izouma/jiashanxia/enums/FlowType.java

@@ -8,5 +8,9 @@ public enum FlowType {
     /*
     核销
      */
-    WRITE_OFF
+    WRITE_OFF,
+    /*
+    退款
+     */
+    REFUND
 }

+ 1 - 1
src/main/java/com/izouma/jiashanxia/enums/TransactionType.java

@@ -3,7 +3,7 @@ package com.izouma.jiashanxia.enums;
 public enum TransactionType {
     WITHDRAW("提现"),
     PROMOTE("推广新会员"),
-    CHILDREN_PROMOTE("下级推广新会员"),
+    CHILD_PROMOTE("下级推广新会员"),
     BIG_EXPERT("成为大达人额外奖励"),
     MAKER("创客奖励"),
     EMPLOYEES_PROMOTE("员工推广新会员"),

+ 35 - 2
src/main/java/com/izouma/jiashanxia/service/CommissionRecordService.java

@@ -9,6 +9,7 @@ import com.izouma.jiashanxia.domain.Withdraw;
 import com.izouma.jiashanxia.dto.CommissionRecordDTO;
 import com.izouma.jiashanxia.dto.PageQuery;
 import com.izouma.jiashanxia.enums.AuthorityName;
+import com.izouma.jiashanxia.enums.Member;
 import com.izouma.jiashanxia.enums.PayMethod;
 import com.izouma.jiashanxia.enums.TransactionType;
 import com.izouma.jiashanxia.repo.CommissionRecordRepo;
@@ -119,7 +120,7 @@ public class CommissionRecordService {
 
     }
 
-    // 退款流水
+    // 退款佣金流水
     public void refund(String orderId) {
         List<CommissionRecord> records = commissionRecordRepo.findAllByTransactionId(orderId);
         // 相关用户
@@ -132,7 +133,7 @@ public class CommissionRecordService {
             User user = userMap.get(record.getUserId());
             if (ObjectUtil.isNotEmpty(user)) {
                 user.setCacheAmount(user.getCacheAmount().subtract(record.getAmount()));
-                // 保存流水
+                // 保存佣金流水
                 CommissionRecord build = CommissionRecord.builder()
                         .amount(record.getAmount().negate())
                         .payMethod(PayMethod.YUE)
@@ -148,4 +149,36 @@ public class CommissionRecordService {
         });
         userRepo.saveAll(userMap.values());
     }
+
+    /*
+    变为可提现金额
+     */
+    public void canWithdraw(Long orderId) {
+        List<CommissionRecord> records = commissionRecordRepo.findAllByTransactionId(orderId.toString());
+        Set<Long> ids = records.stream().map(CommissionRecord::getUserId).collect(Collectors.toSet());
+        Map<Long, User> userMap = userRepo.findAllById(ids)
+                .stream()
+                .collect(Collectors.toMap(User::getId, user -> user));
+        records.forEach(record -> {
+            User user = userMap.get(record.getUserId());
+            if (ObjectUtil.isNotEmpty(user)) {
+                user.setCacheAmount(user.getCacheAmount().subtract(record.getAmount()));
+                switch (record.getTransactionType()) {
+                    case PROMOTE:
+                        user.setPromote(user.getPromote().add(record.getAmount()));
+                        break;
+                    case CHILD_PROMOTE:
+                        user.setChildPromote(user.getChildPromote().add(record.getAmount()));
+                        break;
+                    case BIG_EXPERT:
+                        if (Member.EXPERT.equals(user.getMember())) {
+                            user.setBigExpert(user.getBigExpert().add(record.getAmount()));
+                        } else {
+                            user.setPromote(user.getBigExpert().add(record.getAmount()));
+                        }
+                        break;
+                }
+            }
+        });
+    }
 }

+ 71 - 12
src/main/java/com/izouma/jiashanxia/service/OrderInfoService.java

@@ -4,8 +4,10 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.izouma.jiashanxia.domain.*;
 import com.izouma.jiashanxia.domain.Package;
+import com.izouma.jiashanxia.dto.GoodsDTO;
 import com.izouma.jiashanxia.dto.OrderInfoVO;
 import com.izouma.jiashanxia.dto.PackageGoodsDTO;
 import com.izouma.jiashanxia.dto.PageQuery;
@@ -39,6 +41,7 @@ public class OrderInfoService {
     private final UserPackageService   userPackageService;
     private final CompanyRepo          companyRepo;
     private final WithdrawService      withdrawService;
+    private final UserPackageFlowRepo  userPackageFlowRepo;
 
     public Page<OrderInfo> all(PageQuery pageQuery) {
         pageQuery.setSort("createdAt,desc");
@@ -76,6 +79,7 @@ public class OrderInfoService {
                 .orderNumber(localTime + num)
                 .price(aPackage.getAmount())
                 .name(aPackage.getName())
+                .repeatedly(aPackage.isRepeatedly())
                 .num(1)
                 .build();
         return orderInfoRepo.save(order);
@@ -113,6 +117,42 @@ public class OrderInfoService {
         }
     }
 
+    public void completed1(Long orderInfoId, String transactionId) {
+        // 修改订单状态
+        OrderInfo order = orderInfoRepo.findById(orderInfoId).orElseThrow(new BusinessException("无订单"));
+        order.setStatus(OrderInfoStatus.PAID);
+        order.setTransactionId(transactionId);
+        order.setPaidAt(LocalDateTime.now());
+        orderInfoRepo.save(order);
+
+        Long userId = order.getUserId();
+
+        // 套餐内商品
+        Package aPackage = packageRepo.findById(order.getPackageId()).orElseThrow(new BusinessException("无套餐"));
+        List<PackageGoods> packageGoodsList = packageGoodsRepo.findAllByPackageId(order.getPackageId());
+        if (order.isRepeatedly()) {
+            // 多次使用加入套餐余额
+            userPackageService.joinUserPackage1(userId, packageGoodsList, order.getNum());
+        }
+        // 记录套餐流水 (没有*数量)
+        List<GoodsDTO> goodsDTOS = JSONObject.parseArray(JSONObject.toJSONString(packageGoodsList), GoodsDTO.class);
+        userPackageFlowRepo.save(UserPackageFlow.builder()
+                .userId(userId)
+                .type(FlowType.BUY)
+                .orderInfoId(orderInfoId)
+                .content(goodsDTOS)
+                .build());
+
+        // 用户
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+
+        // 用户id和上级id相同
+        if (user.getParent() != null && !userId.equals(user.getParent())) {
+            // 上级分销
+            this.distribution1(userId, user.getParent(), orderInfoId.toString(), order.getPrice(), aPackage);
+        }
+    }
+
     /*
     取消订单
      */
@@ -153,7 +193,7 @@ public class OrderInfoService {
         //分销级别
         int distributor = sysConfigService.getInt("DISTRIBUTOR");
         for (int i = 0; i < distributor; i++) {
-            String name = "PERSONAL_AMOUNT_" + i;
+            String name = "PERSONAL_RATIO_" + i;
             // 百分比
             BigDecimal percentage = sysConfigService.getBigDecimal(name);
             BigDecimal personalAmount = amount.multiply(percentage);
@@ -182,23 +222,36 @@ public class OrderInfoService {
         }
     }
 
-    public void distribution1(Long userId, Long parent, String transactionId, BigDecimal amount) {
+    public void distribution1(Long userId, Long parent, String transactionId, BigDecimal amount, Package aPackage) {
         User parentUser = userRepo.findById(parent).orElseThrow(new BusinessException("无用户"));
         Member member = parentUser.getMember();
+        if (Member.NORMAL.equals(member)) {
+            return;
+        }
 
         //直推
         // 达人分销
-        BigDecimal directPush = sysConfigService.getBigDecimal("PERSONAL_AMOUNT_0");
+        BigDecimal directPush = aPackage.getPersonalRatio0();
+        // 套餐有额外分销
+        if (ObjectUtil.isNull(directPush)) {
+            directPush = sysConfigService.getBigDecimal("PERSONAL_RATIO_0");
+        }
         BigDecimal directPushAmount = amount.multiply(directPush);
+
         // 大达人分销
-        BigDecimal bigExpertPush = sysConfigService.getBigDecimal("BIG_EXPERT_AMOUNT");
+        BigDecimal bigExpertPush = aPackage.getBigExpertRatio();
+        // 套餐有额外分销
+        if (ObjectUtil.isNotNull(bigExpertPush)) {
+            bigExpertPush = sysConfigService.getBigDecimal("BIG_EXPERT_RATIO");
+        }
         BigDecimal bigExpertAmount = amount.multiply(bigExpertPush);
+
         // 暂存 保存大达人
         parentUser.setCacheAmount(bigExpertAmount);
         userRepo.save(parentUser);
 
         // 保存流水
-        switch (member){
+        switch (member) {
             case EXPERT:
                 CommissionRecord commissionRecord1 = CommissionRecord.builder()
                         .userId(parent)
@@ -218,9 +271,11 @@ public class OrderInfoService {
                         .transactionId(transactionId)
                         .build();
                 commissionRecordRepo.save(commissionRecord2);
+                break;
             case BIG_EXPERT:
+            case MAKER:
                 CommissionRecord commissionRecord = CommissionRecord.builder()
-                        .userId(parentUser.getId())
+                        .userId(parent)
                         .amount(bigExpertAmount)
                         .payMethod(PayMethod.YUE)
                         .fromUserId(userId)
@@ -242,12 +297,16 @@ public class OrderInfoService {
             if (parentUser == null) {
                 return;
             }
-            if (Member.NORMAL.equals(member)) {
+            if (Member.NORMAL.equals(parentUser.getMember())) {
                 continue;
             }
-            String name = "PERSONAL_AMOUNT_" + i;
-            // 百分比
-            BigDecimal percentage = sysConfigService.getBigDecimal(name);
+            BigDecimal percentage = aPackage.getPersonalRatio1();
+            if (ObjectUtil.isNull(percentage)) {
+                String name = "PERSONAL_RATIO_" + i;
+                // 百分比
+                percentage = sysConfigService.getBigDecimal(name);
+            }
+
             BigDecimal personalAmount = amount.multiply(percentage);
             parentUser.setAmount(parentUser.getCacheAmount().add(personalAmount));
             userRepo.save(parentUser);
@@ -258,7 +317,7 @@ public class OrderInfoService {
                     .amount(personalAmount)
                     .payMethod(PayMethod.YUE)
                     .fromUserId(userId)
-                    .transactionType(TransactionType.CHILDREN_PROMOTE)
+                    .transactionType(TransactionType.CHILD_PROMOTE)
                     .transactionId(transactionId)
                     .build();
             commissionRecordRepo.save(commissionRecord);
@@ -274,7 +333,7 @@ public class OrderInfoService {
         // 用户余额
         User user = userRepo.findById(company.getUserId()).orElseThrow(new BusinessException("无用户"));
         // 百分比
-        BigDecimal percentage = sysConfigService.getBigDecimal("COMPANY_AMOUNT");
+        BigDecimal percentage = sysConfigService.getBigDecimal("COMPANY_RATIO");
         BigDecimal companyAmount = amount.multiply(percentage);
         user.setAmount(user.getAmount().add(companyAmount));
         userRepo.save(user);

+ 86 - 8
src/main/java/com/izouma/jiashanxia/service/OrderRefundService.java

@@ -1,25 +1,22 @@
 package com.izouma.jiashanxia.service;
 
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.core.util.ObjectUtil;
 import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
 import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
-import com.izouma.jiashanxia.domain.OrderInfo;
-import com.izouma.jiashanxia.domain.OrderRefund;
-import com.izouma.jiashanxia.domain.WxFee;
+import com.izouma.jiashanxia.domain.*;
+import com.izouma.jiashanxia.dto.GoodsDTO;
 import com.izouma.jiashanxia.dto.PageQuery;
+import com.izouma.jiashanxia.enums.FlowType;
 import com.izouma.jiashanxia.enums.OrderInfoStatus;
 import com.izouma.jiashanxia.enums.RefundStatus;
 import com.izouma.jiashanxia.exception.BusinessException;
-import com.izouma.jiashanxia.repo.OrderInfoRepo;
-import com.izouma.jiashanxia.repo.OrderRefundRepo;
-import com.izouma.jiashanxia.repo.WxFeeRepo;
+import com.izouma.jiashanxia.repo.*;
 import com.izouma.jiashanxia.utils.JpaUtils;
 import com.izouma.jiashanxia.utils.SnowflakeIdWorker;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.core.env.Environment;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
@@ -27,7 +24,9 @@ import org.springframework.stereotype.Service;
 import javax.transaction.Transactional;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -40,6 +39,8 @@ public class OrderRefundService {
     private final WxPayService            wxPayService;
     private final Environment             env;
     private final CommissionRecordService commissionRecordService;
+    private final UserPackageRepo         userPackageRepo;
+    private final UserPackageFlowRepo     userPackageFlowRepo;
 
     public Page<OrderRefund> all(PageQuery pageQuery) {
         return orderRefundRepo.findAll(JpaUtils.toSpecification(pageQuery, OrderRefund.class), JpaUtils.toPageRequest(pageQuery));
@@ -60,6 +61,33 @@ public class OrderRefundService {
             case REQUEST_REFUND:
                 throw new BusinessException("申请中");
         }
+        if (orderInfo.isUse()) {
+            throw new BusinessException("已使用无法退款");
+        }
+
+
+        // 可多次使用
+        if (orderInfo.isRepeatedly()) {
+
+            UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderId);
+            List<GoodsDTO> content = flow.getContent();
+            Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(orderInfo.getUserId())
+                    .stream()
+                    .collect(Collectors.toMap(UserPackage::getGoodsInfoId, aPackage -> aPackage));
+            for (GoodsDTO goods : content) {
+                UserPackage userPackage = userPackageMap.get(goods.getGoodsInfoId());
+                if (ObjectUtil.isNull(userPackage)) {
+                    throw new BusinessException("已使用无法退款");
+                }
+                if (userPackage.getNum() < goods.getNum()) {
+                    throw new BusinessException("已使用无法退款");
+                }
+                // 先扣款
+                userPackage.setNum(userPackage.getNum() - goods.getNum());
+                userPackageRepo.save(userPackage);
+            }
+        }
+
         orderInfo.setStatus(OrderInfoStatus.REQUEST_REFUND);
 
         OrderRefund refund = OrderRefund.builder()
@@ -87,6 +115,9 @@ public class OrderRefundService {
                 .orElseThrow(new BusinessException("未申请退款"));
         OrderRefund.setStatus(RefundStatus.CANCEL);
         orderRefundRepo.save(OrderRefund);
+        if (orderInfo.isRepeatedly()) {
+            this.restore(orderInfo.getUserId(), orderId);
+        }
     }
 
     /**
@@ -123,6 +154,9 @@ public class OrderRefundService {
         orderInfo.setStatus(OrderInfoStatus.PAID);
         orderInfoRepo.save(orderInfo);
         orderRefundRepo.save(refund);
+        if (orderInfo.isRepeatedly()) {
+            this.restore(orderInfo.getUserId(), refund.getOrderInfoId());
+        }
     }
 
     /*
@@ -170,5 +204,49 @@ public class OrderRefundService {
         orderRefundRepo.save(refund);
         // 收回分销
         commissionRecordService.refund(orderInfo.getId().toString());
+
+        if (orderInfo.isRepeatedly()) {
+            this.saveFlow(orderInfo.getId(), refund.getId());
+        }
+    }
+
+    /*
+    保存套餐流水
+     */
+    public void saveFlow(Long orderId, Long refundId) {
+        // 套餐使用流水
+        UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderId);
+        List<GoodsDTO> content = flow.getContent();
+        content.forEach(goods -> goods.setNum(-goods.getNum()));
+        userPackageFlowRepo.save(UserPackageFlow.builder()
+                .type(FlowType.REFUND)
+                .userId(orderId)
+                .content(content)
+                .orderInfoId(refundId)
+                .build());
+    }
+
+    /*
+    恢复
+     */
+    public void restore(Long userId, Long orderId) {
+        UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderId);
+        List<GoodsDTO> content = flow.getContent();
+        Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(userId)
+                .stream()
+                .collect(Collectors.toMap(UserPackage::getGoodsInfoId, aPackage -> aPackage));
+        content.forEach(goods -> {
+            UserPackage userPackage = userPackageMap.get(goods.getGoodsInfoId());
+            if (ObjectUtil.isNotEmpty(userPackage)) {
+                userPackage.setNum(userPackage.getNum() + goods.getNum());
+            } else {
+                userPackage = UserPackage.builder()
+                        .userId(userId)
+                        .goodsInfoId(goods.getGoodsInfoId())
+                        .num(goods.getNum())
+                        .build();
+            }
+            userPackageRepo.save(userPackage);
+        });
     }
 }

+ 66 - 29
src/main/java/com/izouma/jiashanxia/service/UserPackageFlowService.java

@@ -5,23 +5,19 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.izouma.jiashanxia.domain.GoodsInfo;
+import com.izouma.jiashanxia.domain.OrderInfo;
 import com.izouma.jiashanxia.domain.UserPackage;
 import com.izouma.jiashanxia.domain.UserPackageFlow;
-import com.izouma.jiashanxia.domain.UserPackagePeriod;
 import com.izouma.jiashanxia.dto.*;
 import com.izouma.jiashanxia.enums.FlowType;
 import com.izouma.jiashanxia.exception.BusinessException;
-import com.izouma.jiashanxia.repo.GoodsInfoRepo;
-import com.izouma.jiashanxia.repo.UserPackageFlowRepo;
-import com.izouma.jiashanxia.repo.UserPackagePeriodRepo;
-import com.izouma.jiashanxia.repo.UserPackageRepo;
+import com.izouma.jiashanxia.repo.*;
 import com.izouma.jiashanxia.utils.JpaUtils;
 import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
 import javax.persistence.criteria.Predicate;
-import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -29,10 +25,10 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class UserPackageFlowService {
 
-    private final UserPackageFlowRepo   userPackageFlowRepo;
-    private final GoodsInfoRepo         goodsInfoRepo;
-    private final UserPackageRepo       userPackageRepo;
-    private final UserPackagePeriodRepo userPackagePeriodRepo;
+    private final UserPackageFlowRepo userPackageFlowRepo;
+    private final GoodsInfoRepo       goodsInfoRepo;
+    private final UserPackageRepo     userPackageRepo;
+    private final OrderInfoRepo       orderInfoRepo;
 
     public Page<UserPackageFlow> all(PageQuery pageQuery) {
         pageQuery.setSort("createdAt,desc");
@@ -132,8 +128,7 @@ public class UserPackageFlowService {
         }
 
         // 用户已有套餐
-        Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserIdAndType(writeOffSaveVO.getUserId(), writeOffSaveVO
-                .getType())
+        Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(writeOffSaveVO.getUserId())
                 .stream()
                 .collect(Collectors.toMap(UserPackage::getGoodsInfoId, userPackage -> userPackage));
 
@@ -177,14 +172,71 @@ public class UserPackageFlowService {
 //        }
 
         // 保存套餐流水
-//        String content = JSONObject.toJSONString(goodsDTOS);
         return userPackageFlowRepo.save(
                 UserPackageFlow.builder()
                         .userId(writeOffSaveVO.getUserId())
                         .content(goodsDTOS)
                         .type(FlowType.WRITE_OFF)
 //                        .userPackagePeriodId(writeOffSaveVO.getUserPackagePeriodId())
-                        .packageType(writeOffSaveVO.getType())
+//                        .packageType(writeOffSaveVO.getType())
+                        .writeOffUserId(writeOffSaveVO.getWriteOffUserId())
+                        .build());
+    }
+
+    /*
+    核销
+    */
+    public UserPackageFlow writeOff1(WriteOffSaveVO writeOffSaveVO) {
+        if (writeOffSaveVO.getUserId().equals(writeOffSaveVO.getWriteOffUserId())) {
+            throw new BusinessException("不可自己核销自己");
+        }
+        Long orderInfoId = writeOffSaveVO.getOrderInfoId();
+        if (ObjectUtil.isNotEmpty(orderInfoId)) {
+            OrderInfo orderInfo = orderInfoRepo.findById(orderInfoId)
+                    .orElseThrow(new BusinessException("无订单"));
+            if (orderInfo.isUse()) {
+                throw new BusinessException("已核销");
+            }
+            orderInfo.setUse(true);
+            orderInfoRepo.save(orderInfo);
+            UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderInfoId);
+            flow.getContent().forEach(goods -> goods.setNum(-goods.getNum()));
+            return userPackageFlowRepo.save(
+                    UserPackageFlow.builder()
+                            .userId(writeOffSaveVO.getUserId())
+                            .content(flow.getContent())
+                            .type(FlowType.WRITE_OFF)
+                            .writeOffUserId(writeOffSaveVO.getWriteOffUserId())
+                            .build());
+        }
+        // 用户已有套餐
+        Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(writeOffSaveVO.getUserId())
+                .stream()
+                .collect(Collectors.toMap(UserPackage::getGoodsInfoId, userPackage -> userPackage));
+
+        List<GoodsDTO> goodsDTOS = JSONObject.parseArray(writeOffSaveVO.getContent(), GoodsDTO.class);
+        goodsDTOS.forEach(goodsDTO -> {
+            UserPackage userPackage = userPackageMap.get(goodsDTO.getGoodsInfoId());
+            if (ObjectUtil.isEmpty(userPackage)) {
+                throw new BusinessException("无此项目");
+            }
+            if (userPackage.getNum() <= 0) {
+                throw new BusinessException("无余额");
+            }
+            if (goodsDTO.getNum() > userPackage.getNum()) {
+                throw new BusinessException("核销数量大于套餐数量");
+            }
+            userPackage.setNum(userPackage.getNum() - goodsDTO.getNum());
+
+            userPackageRepo.save(userPackage);
+            goodsDTO.setNum(-goodsDTO.getNum());
+        });
+
+        return userPackageFlowRepo.save(
+                UserPackageFlow.builder()
+                        .userId(writeOffSaveVO.getUserId())
+                        .content(goodsDTOS)
+                        .type(FlowType.WRITE_OFF)
                         .writeOffUserId(writeOffSaveVO.getWriteOffUserId())
                         .build());
     }
@@ -215,19 +267,4 @@ public class UserPackageFlowService {
         }
         return build;
     }
-
-    public void getAmount() {
-
-    }
-
-    /*
-    退款收回
-     */
-    public void refund(Long orderId) {
-        UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderId);
-        if (ObjectUtil.isNull(flow)) {
-            return;
-        }
-        flow.getContent();
-    }
 }

+ 23 - 11
src/main/java/com/izouma/jiashanxia/service/UserPackageService.java

@@ -79,7 +79,7 @@ public class UserPackageService {
                 .build());
     }
 
-    public void joinUserPackage1(Long userId, List<PackageGoods> packageGoodsList, Integer num, Long orderId) {
+    public void joinUserPackage1(Long userId, List<PackageGoods> packageGoodsList, Integer num) {
         // 用户已有套餐
         Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(userId)
                 .stream()
@@ -102,16 +102,28 @@ public class UserPackageService {
             }
             userPackageRepo.save(goods);
         });
+    }
 
-        // 记录套餐流水
-        List<GoodsDTO> goodsDTOS = JSONObject.parseArray(JSONObject.toJSONString(packageGoodsList), GoodsDTO.class);
-        userPackageFlowRepo.save(UserPackageFlow.builder()
-                .userId(userId)
-                .type(FlowType.BUY)
-//                .packageType(type)
-                .orderInfoId(orderId)
-//                .content(JSONObject.toJSONString(goodsDTOS))
-                .content(goodsDTOS)
-                .build());
+    /*
+    多次套餐退款
+     */
+    public boolean canRefund(Long userId, Long orderId) {
+        UserPackageFlow flow = userPackageFlowRepo.findByOrderInfoId(orderId);
+        List<GoodsDTO> content = flow.getContent();
+        Map<Long, UserPackage> userPackageMap = userPackageRepo.findAllByUserId(userId)
+                .stream()
+                .collect(Collectors.toMap(UserPackage::getGoodsInfoId, aPackage -> aPackage));
+        for (GoodsDTO goods : content) {
+            UserPackage userPackage = userPackageMap.get(goods.getGoodsInfoId());
+            if (ObjectUtil.isNull(userPackage)) {
+                return false;
+            }
+            if (userPackage.getNum() < goods.getNum()) {
+                return false;
+            }
+        }
+        return true;
     }
+
+
 }

+ 1 - 1
src/test/java/com/izouma/jiashanxia/service/UserPackageFlowServiceTest.java

@@ -33,7 +33,7 @@ public class UserPackageFlowServiceTest {
                 .userId(125L)
                 .writeOffUserId(1L)
                 .content("[{\"goodsInfoId\":27,\"num\":1}]")
-                .type(PackageType.TEAM)
+//                .type(PackageType.TEAM)
                 .build());
     }