Parcourir la source

返利钱包返利使用比例(新增、编辑、删除、批量删除、导出)
收款单(导入模板、批量导入、批量审批、导出)
返利单(导入模板、批量导入、批量审批、导出)
台账管理(列表、导出)

FengChaoYu il y a 1 mois
Parent
commit
40e108c09c
27 fichiers modifiés avec 1809 ajouts et 36 suppressions
  1. 70 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/AdminCompanyRebateAccVO.java
  2. 70 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/AdminCompanyWalletAccVO.java
  3. 118 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/CompanyWalletBalanceDTO.java
  4. 67 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/RebateVO.java
  5. 70 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/ReceiptVO.java
  6. 62 0
      mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/sales/config/RebateTypeRateVO.java
  7. 45 4
      mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/CommonMapper.java
  8. 4 0
      mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/LockQueryMapper.java
  9. 2 0
      mall-server-api/src/main/java/com/gree/mall/manager/constant/Constant.java
  10. 114 0
      mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/RebateController.java
  11. 114 0
      mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/ReceiptController.java
  12. 72 0
      mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/WalletBalanceUseAccController.java
  13. 53 10
      mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/sales/config/SupplyPayConfigController.java
  14. 23 0
      mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/BalanceBillTypeEnum.java
  15. 22 0
      mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/BalanceTypeEnum.java
  16. 22 0
      mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/RebateBillTypeEnum.java
  17. 22 0
      mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/ReceiptBillTypeEnum.java
  18. 153 0
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/CompanyWalletBalanceLogic.java
  19. 155 0
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/CompanyWalletLogic.java
  20. 176 0
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/RebateLogic.java
  21. 202 0
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/ReceiptLogic.java
  22. 37 0
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/WalletBalanceUseAccLogic.java
  23. 61 21
      mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/sales/config/SupplyPayConfigLogic.java
  24. 64 1
      mall-server-api/src/main/resources/mapper/CommonMapper.xml
  25. 11 0
      mall-server-api/src/main/resources/mapper/LockQueryMapper.xml
  26. BIN
      mall-server-api/src/main/resources/template/收款单模板.xlsx
  27. BIN
      mall-server-api/src/main/resources/template/返利单模板.xlsx

+ 70 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/AdminCompanyRebateAccVO.java

@@ -0,0 +1,70 @@
+package com.gree.mall.manager.bean.supply.funds;
+
+import com.gree.mall.manager.annotation.ZfireField;
+import com.gree.mall.manager.enums.material.DirectFlagEnum;
+import com.gree.mall.manager.enums.supply.BalanceBillTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@ApiModel
+@ZfireField(tbName = "a")
+public class AdminCompanyRebateAccVO {
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "商户id")
+    private String companyWechatId;
+
+    @ApiModelProperty(value = "商户名称")
+    private String companyName;
+
+    @ApiModelProperty(value = "单据号")
+    private String billId;
+
+    @ApiModelProperty(value = "单据日期")
+    private Date theTime;
+
+    @ApiModelProperty(value = "单据类型")
+    private BalanceBillTypeEnum billType;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "返利类型id")
+    private String walletId;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利类型编码")
+    private String code;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利类型名称")
+    private String name;
+
+    @ApiModelProperty(value = "发生方向")
+    private DirectFlagEnum directFlag;
+
+    @ApiModelProperty(value = "发生金额")
+    private BigDecimal changeAmount;
+
+//    @ApiModelProperty(value = "当前余额")
+//    private BigDecimal historyBalance;
+
+    @ApiModelProperty(value = "余额")
+    private BigDecimal balance;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+}

+ 70 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/AdminCompanyWalletAccVO.java

@@ -0,0 +1,70 @@
+package com.gree.mall.manager.bean.supply.funds;
+
+import com.gree.mall.manager.annotation.ZfireField;
+import com.gree.mall.manager.enums.material.DirectFlagEnum;
+import com.gree.mall.manager.enums.supply.BalanceBillTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@ApiModel
+@ZfireField(tbName = "a")
+public class AdminCompanyWalletAccVO {
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "商户id")
+    private String companyWechatId;
+
+    @ApiModelProperty(value = "商户名称")
+    private String companyName;
+
+    @ApiModelProperty(value = "单据号")
+    private String billId;
+
+    @ApiModelProperty(value = "单据日期")
+    private Date theTime;
+
+    @ApiModelProperty(value = "单据类型")
+    private BalanceBillTypeEnum billType;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "钱包id")
+    private String walletId;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "钱包编码")
+    private String code;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "钱包名称")
+    private String name;
+
+    @ApiModelProperty(value = "发生方向")
+    private DirectFlagEnum directFlag;
+
+    @ApiModelProperty(value = "发生金额")
+    private BigDecimal changeAmount;
+
+//    @ApiModelProperty(value = "当前余额")
+//    private BigDecimal historyBalance;
+
+    @ApiModelProperty(value = "余额")
+    private BigDecimal balance;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+}

+ 118 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/CompanyWalletBalanceDTO.java

@@ -0,0 +1,118 @@
+package com.gree.mall.manager.bean.supply.funds;
+
+import com.gree.mall.manager.enums.material.DirectFlagEnum;
+import com.gree.mall.manager.enums.supply.BalanceTypeEnum;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.plus.entity.AdminCompanyRebateAcc;
+import com.gree.mall.manager.plus.entity.AdminCompanyWalletAcc;
+import com.gree.mall.manager.plus.entity.AdminCompanyWalletBalance;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.springframework.beans.BeanUtils;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+public class CompanyWalletBalanceDTO {
+
+    @NotBlank(message = "发生方向不能空")
+    @ApiModelProperty(value = "发生方向 ADD=增加 SUB=减少")
+    private String directFlag;
+
+    @ApiModelProperty(value = "商户编号")
+    @NotBlank(message = "商户编号不能空")
+    private String companyWechatId;
+
+    @ApiModelProperty(value = "商户名称")
+    @NotBlank(message = "商户名称不能空")
+    private String companyName;
+
+    @NotNull(message = "单据日期不能空")
+    @ApiModelProperty(value = "单据日期")
+    private Date theTime;
+
+    @NotNull(message = "发生金额不能空")
+    @ApiModelProperty(value = "发生金额")
+    private BigDecimal changeAmount;
+
+    @NotBlank(message = "单据号不能空")
+    @ApiModelProperty(value = "单据号")
+    private String billId;
+
+    @ApiModelProperty(value = "单据类型")
+    @NotBlank(message = "单据类型不能空")
+    private String billType;
+
+    @NotNull(message = "钱包不能空")
+    @ApiModelProperty(value = "钱包id")
+    private String walletId;
+
+    @NotNull(message = "钱包类型不能空")
+    @ApiModelProperty(value = "钱包类型 W=现金钱包  R=返利钱包")
+    private String walletType;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    public AdminCompanyWalletBalance createWalletBalance() {
+        AdminCompanyWalletBalance walletBalance = new AdminCompanyWalletBalance();
+        BeanUtils.copyProperties(this, walletBalance);
+        walletBalance.setId(null)
+                .setBalance(BigDecimal.ZERO)
+                .setType(this.walletType);
+        return walletBalance;
+    }
+
+    public void computeCompanyWalletBalance(AdminCompanyWalletBalance walletBalance, List<AdminCompanyWalletAcc> walletAccList,
+                                            List<AdminCompanyRebateAcc> rebateAccList) {
+        BigDecimal balance = walletBalance.getBalance();
+
+        BigDecimal direct = this.directFlag.equals(DirectFlagEnum.ADD.getKey()) ? BigDecimal.ONE : new BigDecimal("-1");
+        BigDecimal closeBalance = balance.add(this.changeAmount.multiply(direct));
+        if (closeBalance.compareTo(BigDecimal.ZERO) < 0 && direct.compareTo(BigDecimal.ZERO) < 0) {
+            String walletName = this.walletType.equals(BalanceTypeEnum.W.getKey()) ? BalanceTypeEnum.W.getRemark() : BalanceTypeEnum.R.getRemark();
+            throw new RemoteServiceException("\""+ companyName + walletName + "\"不允许为负" + this.walletId);
+        }
+
+        if (this.walletType.equals(BalanceTypeEnum.W.getKey())) {
+            // 注入现金钱包三级帐
+            walletAccList.add(new AdminCompanyWalletAcc()
+                    .setCompanyWechatId(this.companyWechatId)
+                    .setCompanyName(this.companyName)
+                    .setBillId(this.billId)
+                    .setBillType(this.billType)
+                    .setTheTime(this.theTime)
+                    .setWalletId(this.walletId)
+                    .setDirectFlag(this.directFlag)
+                    .setChangeAmount(this.changeAmount)
+                    .setBalance(balance)
+                    .setHistoryBalance(balance)
+                    .setBalance(closeBalance)
+                    .setRemark(this.remark));
+        } else {
+            // 注入返利钱包三级帐
+            rebateAccList.add(new AdminCompanyRebateAcc()
+                    .setCompanyWechatId(this.companyWechatId)
+                    .setCompanyName(this.companyName)
+                    .setBillId(this.billId)
+                    .setBillType(this.billType)
+                    .setTheTime(this.theTime)
+                    .setWalletId(this.walletId)
+                    .setDirectFlag(this.directFlag)
+                    .setChangeAmount(this.changeAmount)
+                    .setBalance(balance)
+                    .setHistoryBalance(balance)
+                    .setBalance(closeBalance)
+                    .setRemark(this.remark));
+        }
+
+        // 注入余额
+        walletBalance.setBalance(closeBalance);
+    }
+}

+ 67 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/RebateVO.java

@@ -0,0 +1,67 @@
+package com.gree.mall.manager.bean.supply.funds;
+
+import com.gree.mall.manager.annotation.ZfireField;
+import com.gree.mall.manager.enums.ExamineStatusEnum;
+import com.gree.mall.manager.enums.supply.RebateBillTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@ApiModel
+@ZfireField(tbName = "a")
+public class RebateVO {
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ApiModelProperty(value = "单据编号")
+    private String billNo;
+
+    @ApiModelProperty(value = "单据类型")
+    private RebateBillTypeEnum billType;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "商户id")
+    private String companyWechatId;
+
+    @ApiModelProperty(value = "商户名称")
+    private String companyName;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "返利类型id")
+    private String rebateTypeId;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利类型编码")
+    private String code;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利类型名称")
+    private String name;
+
+    @ApiModelProperty(value = "返利金额")
+    private BigDecimal realAmount;
+
+    @ApiModelProperty(value = "状态")
+    private ExamineStatusEnum status;
+
+    @ApiModelProperty(value = "业务日期")
+    private Date theTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+}

+ 70 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/funds/ReceiptVO.java

@@ -0,0 +1,70 @@
+package com.gree.mall.manager.bean.supply.funds;
+
+import com.gree.mall.manager.annotation.ZfireField;
+import com.gree.mall.manager.enums.ExamineStatusEnum;
+import com.gree.mall.manager.enums.supply.ReceiptBillTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@ApiModel
+@ZfireField(tbName = "a")
+public class ReceiptVO {
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ApiModelProperty(value = "单据编号")
+    private String billNo;
+
+    @ApiModelProperty(value = "单据类型")
+    private ReceiptBillTypeEnum billType;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "商户id")
+    private String companyWechatId;
+
+    @ApiModelProperty(value = "商户名称")
+    private String companyName;
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "钱包id")
+    private String walletId;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "钱包编码")
+    private String code;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "钱包名称")
+    private String name;
+
+    @ApiModelProperty(value = "应收金额")
+    private BigDecimal amount;
+
+    @ApiModelProperty(value = "实收金额")
+    private BigDecimal realAmount;
+
+    @ApiModelProperty(value = "状态")
+    private ExamineStatusEnum status;
+
+    @ApiModelProperty(value = "业务日期")
+    private Date theTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+}

+ 62 - 0
mall-server-api/src/main/java/com/gree/mall/manager/bean/supply/sales/config/RebateTypeRateVO.java

@@ -0,0 +1,62 @@
+package com.gree.mall.manager.bean.supply.sales.config;
+
+import com.gree.mall.manager.annotation.ZfireField;
+import com.gree.mall.manager.enums.StatusEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@ApiModel
+@ZfireField(tbName = "a")
+public class RebateTypeRateVO {
+
+    @ZfireField(hide = true)
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ZfireField(hide = true, tbName = "b", colName = "id", ignoreSelect = true)
+    @ApiModelProperty(value = "返利类型id")
+    private String rebateTypeId;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利编码")
+    private String code;
+
+    @ZfireField(tbName = "b")
+    @ApiModelProperty(value = "返利类型")
+    private String name;
+
+    @ZfireField(hide = true, tbName = "c", colName = "id", ignoreSelect = true)
+    @ApiModelProperty(value = "销售类型id")
+    private String salesTypeId;
+
+    @ZfireField(tbName = "c", colName = "code", ignoreSelect = true)
+    @ApiModelProperty(value = "销售类型编码")
+    private String salesTypeCode;
+
+    @ZfireField(tbName = "c", colName = "name", ignoreSelect = true)
+    @ApiModelProperty(value = "销售类型名称")
+    private String salesTypeName;
+
+    @ApiModelProperty(value = "返利比例")
+    private BigDecimal rebateRate;
+
+    @ApiModelProperty(value = "状态")
+    private StatusEnum status;
+
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+
+    @ApiModelProperty(value = "修改时间")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "修改人")
+    private String updateBy;
+}

+ 45 - 4
mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/CommonMapper.java

@@ -26,10 +26,11 @@ import com.gree.mall.manager.bean.settle.SettleExpenseVO;
 import com.gree.mall.manager.bean.settle.SettleMonthWagesVO;
 import com.gree.mall.manager.bean.settle.SettleMonthWagesWorkerVO;
 import com.gree.mall.manager.bean.settle.repair.*;
-import com.gree.mall.manager.bean.supply.sales.config.CompanyWalletVO;
-import com.gree.mall.manager.bean.supply.sales.config.RebateTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.SalesTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.WalletVO;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyRebateAccVO;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyWalletAccVO;
+import com.gree.mall.manager.bean.supply.funds.RebateVO;
+import com.gree.mall.manager.bean.supply.funds.ReceiptVO;
+import com.gree.mall.manager.bean.supply.sales.config.*;
 import com.gree.mall.manager.bean.supply.sales.price.ProductPriceUpdateVO;
 import com.gree.mall.manager.bean.supply.sales.price.ProductPriceVO;
 import com.gree.mall.manager.bean.user.*;
@@ -743,4 +744,44 @@ public interface CommonMapper {
      * @return
      */
     IPage<CompanyWalletVO> companyWalletList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
+
+    /**
+     * 返利使用比例列表
+     * @param page
+     * @param zfireParamBean
+     * @return
+     */
+    IPage<RebateTypeRateVO> rebateTypeRetaList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
+
+    /**
+     * 收款单列表
+     * @param page
+     * @param zfireParamBean
+     * @return
+     */
+    IPage<ReceiptVO> receiptList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
+
+    /**
+     * 返利单列表
+     * @param page
+     * @param zfireParamBean
+     * @return
+     */
+    IPage<RebateVO> rebateList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
+
+    /**
+     * 钱包余额使用台账列表
+     * @param page
+     * @param zfireParamBean
+     * @return
+     */
+    IPage<AdminCompanyWalletAccVO> walletBalanceUseAccList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
+
+    /**
+     * 返利余额使用台账列表
+     * @param page
+     * @param zfireParamBean
+     * @return
+     */
+    IPage<AdminCompanyRebateAccVO> rebateBalanceUseAccList(Page page, @Param("ex") ZfireParamBean zfireParamBean);
 }

+ 4 - 0
mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/LockQueryMapper.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.manager.bean.goods.GoodsMaterialStockDTO;
 import com.gree.mall.manager.bean.material.vender.WebsitVenderVO;
+import com.gree.mall.manager.bean.supply.funds.CompanyWalletBalanceDTO;
+import com.gree.mall.manager.plus.entity.AdminCompanyWalletBalance;
 import com.gree.mall.manager.plus.entity.GoodsMaterialStorage;
 import com.gree.mall.manager.plus.entity.UserCompanyCredit;
 import com.gree.mall.manager.zfire.bean.ZfireParamBean;
@@ -34,4 +36,6 @@ public interface LockQueryMapper {
                                                   @Param("userId") String userId);
 
     List<UserCompanyCredit> findByBillingDay(@Param("billingDay") Integer billingDay);
+
+    List<AdminCompanyWalletBalance> queryExistCompanyWalletBalanceList(@Param("dto") CompanyWalletBalanceDTO dto);
 }

+ 2 - 0
mall-server-api/src/main/java/com/gree/mall/manager/constant/Constant.java

@@ -65,6 +65,8 @@ public class Constant {
 
         public final static String LOCK_USER_COMPANY_CREDIT = "zfire:overseas:lock:user:company:credit:";
 
+        public final static String LOCK_COMPANY_WALLET = "zfire:overseas:company:wallet:";
+
     }
 
 

+ 114 - 0
mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/RebateController.java

@@ -0,0 +1,114 @@
+package com.gree.mall.manager.controller.supply.funds;
+
+import cn.hutool.core.lang.TypeReference;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.manager.annotation.ZfireList;
+import com.gree.mall.manager.bean.supply.funds.RebateVO;
+import com.gree.mall.manager.constant.Constant;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.helper.ResponseHelper;
+import com.gree.mall.manager.logic.supply.funds.RebateLogic;
+import com.gree.mall.manager.utils.excel.ExcelUtils;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+
+@Slf4j
+@RestController
+@Api(value = "返利单API", tags = {"返利单API"})
+@RequestMapping(value = "/supply/funds/rebate", produces = "application/json; charset=utf-8")
+public class RebateController {
+
+    @Resource
+    RebateLogic rebateLogic;
+    @Resource
+    RedisLockRegistry redisLockRegistry;
+
+    @ZfireList
+    @PostMapping("/list")
+    @ApiOperation(value = "列表")
+    public ResponseHelper<IPage<RebateVO>> list(
+            @RequestBody ZfireParamBean zfireParamBean
+    ) {
+        IPage<RebateVO> page = rebateLogic.list(zfireParamBean);
+        return ResponseHelper.success(page, new TypeReference<RebateVO>() {
+        });
+    }
+
+    @PostMapping("/list/export")
+    @ApiOperation(value = "导出")
+    public void listExport(@RequestBody ZfireParamBean zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //2.查询要导出的内容
+        IPage<RebateVO> page = rebateLogic.list(zfireParamBean);
+        //3.导出
+        FieldUtils.exportData(page.getRecords(), zfireParamBean.getExportFields(), request, response);
+    }
+
+    @PostMapping("/import")
+    @ApiOperation("导入(下载模板:返利单模板.xlsx)")
+    public ResponseHelper<Integer> importData(
+            @ApiParam(value = "附件", required = true) @RequestPart("file") MultipartFile file,
+            HttpServletRequest request
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":rebate");
+        int num = 0;
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            List<Object> objects = ExcelUtils.importExcel(file);
+            num = rebateLogic.importData(objects);
+        } finally {
+            obtain.unlock();
+        }
+
+        return ResponseHelper.success(num);
+    }
+
+    @PostMapping("/batch/examine")
+    @ApiOperation(value = "批量审核")
+    public ResponseHelper batchExamine(
+            @RequestBody List<String> ids
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":batchRebate");
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            rebateLogic.batchExamine(ids);
+        } finally {
+            obtain.unlock();
+        }
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/batch/fail")
+    @ApiOperation(value = "批量驳回")
+    public ResponseHelper batchFail(
+            @RequestBody List<String> ids
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":batchRebate");
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            rebateLogic.batchFail(ids);
+        } finally {
+            obtain.unlock();
+        }
+        return ResponseHelper.success();
+    }
+}

+ 114 - 0
mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/ReceiptController.java

@@ -0,0 +1,114 @@
+package com.gree.mall.manager.controller.supply.funds;
+
+import cn.hutool.core.lang.TypeReference;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.manager.annotation.ZfireList;
+import com.gree.mall.manager.bean.supply.funds.ReceiptVO;
+import com.gree.mall.manager.constant.Constant;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.helper.ResponseHelper;
+import com.gree.mall.manager.logic.supply.funds.ReceiptLogic;
+import com.gree.mall.manager.utils.excel.ExcelUtils;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+
+@Slf4j
+@RestController
+@Api(value = "收款单API", tags = {"收款单API"})
+@RequestMapping(value = "/supply/funds/receipt", produces = "application/json; charset=utf-8")
+public class ReceiptController {
+
+    @Resource
+    ReceiptLogic receiptLogic;
+    @Resource
+    RedisLockRegistry redisLockRegistry;
+
+    @ZfireList
+    @PostMapping("/list")
+    @ApiOperation(value = "列表")
+    public ResponseHelper<IPage<ReceiptVO>> list(
+            @RequestBody ZfireParamBean zfireParamBean
+    ) {
+        IPage<ReceiptVO> page = receiptLogic.list(zfireParamBean);
+        return ResponseHelper.success(page, new TypeReference<ReceiptVO>() {
+        });
+    }
+
+    @PostMapping("/list/export")
+    @ApiOperation(value = "导出")
+    public void listExport(@RequestBody ZfireParamBean zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //2.查询要导出的内容
+        IPage<ReceiptVO> page = receiptLogic.list(zfireParamBean);
+        //3.导出
+        FieldUtils.exportData(page.getRecords(), zfireParamBean.getExportFields(), request, response);
+    }
+
+    @PostMapping("/import")
+    @ApiOperation("导入(下载模板:收款单模板.xlsx)")
+    public ResponseHelper<Integer> importData(
+            @ApiParam(value = "附件", required = true) @RequestPart("file") MultipartFile file,
+            HttpServletRequest request
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":receipt");
+        int num = 0;
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            List<Object> objects = ExcelUtils.importExcel(file);
+            num = receiptLogic.importData(objects);
+        } finally {
+            obtain.unlock();
+        }
+
+        return ResponseHelper.success(num);
+    }
+
+    @PostMapping("/batch/examine")
+    @ApiOperation(value = "批量审核")
+    public ResponseHelper batchExamine(
+            @RequestBody List<String> ids
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":batchReceipt");
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            receiptLogic.batchExamine(ids);
+        } finally {
+            obtain.unlock();
+        }
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/batch/fail")
+    @ApiOperation(value = "批量驳回")
+    public ResponseHelper batchFail(
+            @RequestBody List<String> ids
+    ) throws Exception {
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":batchReceipt");
+        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
+            throw new RemoteServiceException("系统繁忙,请稍后再尝试");
+        }
+        try {
+            receiptLogic.batchFail(ids);
+        } finally {
+            obtain.unlock();
+        }
+        return ResponseHelper.success();
+    }
+}

+ 72 - 0
mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/funds/WalletBalanceUseAccController.java

@@ -0,0 +1,72 @@
+package com.gree.mall.manager.controller.supply.funds;
+
+import cn.hutool.core.lang.TypeReference;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.manager.annotation.ZfireList;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyRebateAccVO;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyWalletAccVO;
+import com.gree.mall.manager.helper.ResponseHelper;
+import com.gree.mall.manager.logic.supply.funds.WalletBalanceUseAccLogic;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+@RestController
+@Api(value = "台账管理API", tags = {"台账管理API"})
+@RequestMapping(value = "/supply/funds/acc", produces = "application/json; charset=utf-8")
+public class WalletBalanceUseAccController {
+
+    @Resource
+    WalletBalanceUseAccLogic walletBalanceAccLogic;
+
+    @ZfireList
+    @PostMapping("/wallet/list")
+    @ApiOperation(value = "列表")
+    public ResponseHelper<IPage<AdminCompanyWalletAccVO>> walletList(
+            @RequestBody ZfireParamBean zfireParamBean
+    ) {
+        IPage<AdminCompanyWalletAccVO> page = walletBalanceAccLogic.walletList(zfireParamBean);
+        return ResponseHelper.success(page, new TypeReference<AdminCompanyWalletAccVO>() {
+        });
+    }
+
+    @PostMapping("/wallet/list/export")
+    @ApiOperation(value = "导出")
+    public void walletListExport(@RequestBody ZfireParamBean zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //2.查询要导出的内容
+        IPage<AdminCompanyWalletAccVO> page = walletBalanceAccLogic.walletList(zfireParamBean);
+        //3.导出
+        FieldUtils.exportData(page.getRecords(), zfireParamBean.getExportFields(), request, response);
+    }
+
+    @ZfireList
+    @PostMapping("/rebate/list")
+    @ApiOperation(value = "列表")
+    public ResponseHelper<IPage<AdminCompanyRebateAccVO>> rebateList(
+            @RequestBody ZfireParamBean zfireParamBean
+    ) {
+        IPage<AdminCompanyRebateAccVO> page = walletBalanceAccLogic.rebateList(zfireParamBean);
+        return ResponseHelper.success(page, new TypeReference<AdminCompanyRebateAccVO>() {
+        });
+    }
+
+    @PostMapping("/rebate/list/export")
+    @ApiOperation(value = "导出")
+    public void rebateListExport(@RequestBody ZfireParamBean zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //2.查询要导出的内容
+        IPage<AdminCompanyRebateAccVO> page = walletBalanceAccLogic.rebateList(zfireParamBean);
+        //3.导出
+        FieldUtils.exportData(page.getRecords(), zfireParamBean.getExportFields(), request, response);
+    }
+}

+ 53 - 10
mall-server-api/src/main/java/com/gree/mall/manager/controller/supply/sales/config/SupplyPayConfigController.java

@@ -3,18 +3,12 @@ package com.gree.mall.manager.controller.supply.sales.config;
 import cn.hutool.core.lang.TypeReference;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.gree.mall.manager.annotation.ZfireList;
-import com.gree.mall.manager.bean.supply.sales.config.CompanyWalletVO;
-import com.gree.mall.manager.bean.supply.sales.config.RebateTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.SalesTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.WalletVO;
+import com.gree.mall.manager.bean.supply.sales.config.*;
 import com.gree.mall.manager.constant.Constant;
 import com.gree.mall.manager.exception.RemoteServiceException;
 import com.gree.mall.manager.helper.ResponseHelper;
 import com.gree.mall.manager.logic.supply.sales.config.SupplyPayConfigLogic;
-import com.gree.mall.manager.plus.entity.AdminCompanyWechatWallet;
-import com.gree.mall.manager.plus.entity.RebateType;
-import com.gree.mall.manager.plus.entity.SalesType;
-import com.gree.mall.manager.plus.entity.Wallet;
+import com.gree.mall.manager.plus.entity.*;
 import com.gree.mall.manager.utils.excel.ExcelUtils;
 import com.gree.mall.manager.zfire.bean.ZfireParamBean;
 import com.gree.mall.manager.zfire.util.FieldUtils;
@@ -139,9 +133,9 @@ public class SupplyPayConfigController {
     @PostMapping("/company/wallet/add")
     @ApiOperation(value = "商户供应链钱包新增")
     public ResponseHelper companyWalletAdd(
-            @RequestBody AdminCompanyWechatWallet adminCompanyWechatWallet
+            @RequestBody AdminCompanyWallet adminCompanyWallet
     ) throws Exception {
-        supplyPayConfigLogic.companyWalletAdd(adminCompanyWechatWallet);
+        supplyPayConfigLogic.companyWalletAdd(adminCompanyWallet);
 
         return ResponseHelper.success();
     }
@@ -176,4 +170,53 @@ public class SupplyPayConfigController {
 
         return ResponseHelper.success(num);
     }
+
+    @ZfireList
+    @PostMapping("/rebate/type/rate/list")
+    @ApiOperation(value = "返利类型使用比例列表")
+    public ResponseHelper<IPage<RebateTypeRateVO>> rebateTypeRateList(
+            @RequestBody ZfireParamBean zfireParamBean
+    ) {
+        IPage<RebateTypeRateVO> page = supplyPayConfigLogic.rebateTypeRateList(zfireParamBean);
+        return ResponseHelper.success(page, new TypeReference<RebateTypeRateVO>() {
+        });
+    }
+
+    @PostMapping("/rebate/type/rate/list/export")
+    @ApiOperation(value = "返利类型使用比例导出")
+    public void rebateTypeRateListExport(@RequestBody ZfireParamBean zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //2.查询要导出的内容
+        IPage<RebateTypeRateVO> page = supplyPayConfigLogic.rebateTypeRateList(zfireParamBean);
+        //3.导出
+        FieldUtils.exportData(page.getRecords(), zfireParamBean.getExportFields(), request, response);
+    }
+
+    @PostMapping("/rebate/type/rate/detail")
+    @ApiOperation(value = "销售类型详情")
+    public ResponseHelper<RebateTypeUseRate> rebateTypeRateDetail(
+            @ApiParam(value = "id", required = true) @RequestParam String id
+    ) throws Exception {
+        RebateTypeUseRate detail = supplyPayConfigLogic.rebateTypeRateDetail(id);
+        return ResponseHelper.success(detail);
+    }
+
+    @PostMapping("/rebate/type/rate/save")
+    @ApiOperation(value = "返利类型使用比例新增")
+    public ResponseHelper rebateTypeRateSave(
+            @RequestBody RebateTypeUseRate rebateTypeUseRate
+    ) throws Exception {
+        supplyPayConfigLogic.rebateTypeRateSave(rebateTypeUseRate);
+
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/rebate/type/rate/batch/del")
+    @ApiOperation(value = "返利类型使用比例批量删除")
+    public ResponseHelper rebateTypeRateBatchDel(
+            @RequestBody List<String> ids
+    ) throws Exception {
+        supplyPayConfigLogic.rebateTypeRateBatchDel(ids);
+
+        return ResponseHelper.success();
+    }
 }

+ 23 - 0
mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/BalanceBillTypeEnum.java

@@ -0,0 +1,23 @@
+package com.gree.mall.manager.enums.supply;
+
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+public enum BalanceBillTypeEnum implements BaseEnum {
+
+    RECEIPT_BILL("RECEIPT_BILL","收款单"),
+    REBATE_BILL("REBATE_BILL","返利单"),
+            ;
+
+    @EnumValue
+    @JsonValue
+    private final String key;
+    private final String remark;
+}

+ 22 - 0
mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/BalanceTypeEnum.java

@@ -0,0 +1,22 @@
+package com.gree.mall.manager.enums.supply;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+public enum BalanceTypeEnum implements BaseEnum {
+
+    W("W","现金钱包"),
+    R("R","返利钱包"),
+    ;
+
+    @EnumValue
+    @JsonValue
+    private final String key;
+    private final String remark;
+}

+ 22 - 0
mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/RebateBillTypeEnum.java

@@ -0,0 +1,22 @@
+package com.gree.mall.manager.enums.supply;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+public enum RebateBillTypeEnum implements BaseEnum {
+
+    A("A","增加"),
+    S("S","减少"),
+    ;
+
+    @EnumValue
+    @JsonValue
+    private final String key;
+    private final String remark;
+}

+ 22 - 0
mall-server-api/src/main/java/com/gree/mall/manager/enums/supply/ReceiptBillTypeEnum.java

@@ -0,0 +1,22 @@
+package com.gree.mall.manager.enums.supply;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+public enum ReceiptBillTypeEnum implements BaseEnum {
+
+    C("C","收款单"),
+    R("R","退款单"),
+    ;
+
+    @EnumValue
+    @JsonValue
+    private final String key;
+    private final String remark;
+}

+ 153 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/CompanyWalletBalanceLogic.java

@@ -0,0 +1,153 @@
+package com.gree.mall.manager.logic.supply.funds;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.gree.mall.manager.bean.supply.funds.CompanyWalletBalanceDTO;
+import com.gree.mall.manager.commonmapper.LockQueryMapper;
+import com.gree.mall.manager.constant.Constant;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.plus.entity.AdminCompanyRebateAcc;
+import com.gree.mall.manager.plus.entity.AdminCompanyWalletAcc;
+import com.gree.mall.manager.plus.entity.AdminCompanyWalletBalance;
+import com.gree.mall.manager.plus.service.AdminCompanyRebateAccService;
+import com.gree.mall.manager.plus.service.AdminCompanyWalletAccService;
+import com.gree.mall.manager.plus.service.AdminCompanyWalletBalanceService;
+import com.gree.mall.manager.utils.ValidateUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.redis.util.RedisLockRegistry;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import javax.validation.ValidationException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class CompanyWalletBalanceLogic {
+
+    private final RedisLockRegistry redisLockRegistry;
+    private final LockQueryMapper lockQueryMapper;
+    private final AdminCompanyWalletBalanceService adminCompanyWalletBalanceService;
+    private final AdminCompanyWalletAccService adminCompanyWalletAccService;
+    private final AdminCompanyRebateAccService adminCompanyRebateAccService;
+
+    /**
+     * 单个商户钱包处理
+     * @param walletList
+     * @throws Exception
+     */
+    public void handleCompanyWalletBalance(List<CompanyWalletBalanceDTO> walletList) throws Exception {
+        if(!TransactionSynchronizationManager.isSynchronizationActive()) {
+            throw new RemoteServiceException("请先开启事务");
+        }
+        if (CollectionUtil.isEmpty(walletList)) {
+            return;
+        }
+        // 检查传入的参数
+        for (int i = 0; i < walletList.size(); i++) {
+            CompanyWalletBalanceDTO dto = walletList.get(i);
+            try {
+                ValidateUtil.validate(dto);
+                if (dto.getChangeAmount().compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new RemoteServiceException("变动金额不能少于等于0");
+                }
+            } catch (ValidationException ve) {
+                throw new RemoteServiceException("执行数据第" + (i+1) + "行, " + dto.getCompanyName() + ve.getMessage());
+            }
+        }
+        // 锁定商户钱包
+        CompanyWalletBalanceDTO dto = walletList.get(0);
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_COMPANY_WALLET +
+                dto.getCompanyWechatId());
+        if(!obtain.tryLock(10, TimeUnit.SECONDS)){
+            throw new RemoteServiceException("商户所有钱包已冻结:" + dto.getCompanyName());
+        }
+        // 处理商户钱包
+        try{
+            this.saveCompanyWalletBalance(dto, walletList);
+
+        } finally {
+            this.txCallUnlock(obtain);
+        }
+    }
+
+    private void saveCompanyWalletBalance(CompanyWalletBalanceDTO dto, List<CompanyWalletBalanceDTO> walletList) {
+        // 查询存在的钱包
+        List<AdminCompanyWalletBalance> existWalletList = lockQueryMapper.queryExistCompanyWalletBalanceList(dto);
+        // 全部钱包
+        Map<String, AdminCompanyWalletBalance> existStockMap = this.createNotExistWallet(walletList, existWalletList);
+        // 计算钱包余额
+        List<AdminCompanyWalletAcc> walletAccList = new ArrayList<>();
+        List<AdminCompanyRebateAcc> rebateAccList = new ArrayList<>();
+        this.computeCompanyWalletBalance(walletList, existStockMap, walletAccList, rebateAccList);
+
+        if (CollectionUtil.isEmpty(walletAccList) && CollectionUtil.isEmpty(rebateAccList) ) {
+            throw new RemoteServiceException("商户钱包余额处理失败");
+        }
+
+        adminCompanyWalletBalanceService.saveOrUpdateBatch(existStockMap.values());
+        if (CollectionUtil.isNotEmpty(walletAccList)) {
+            adminCompanyWalletAccService.saveBatch(walletAccList);
+        }
+        if (CollectionUtil.isNotEmpty(rebateAccList)) {
+            adminCompanyRebateAccService.saveBatch(rebateAccList);
+        }
+    }
+
+    private void computeCompanyWalletBalance(List<CompanyWalletBalanceDTO> walletList, Map<String, AdminCompanyWalletBalance> walletBalanceMap,
+                                             List<AdminCompanyWalletAcc> walletAccList, List<AdminCompanyRebateAcc> rebateAccList) {
+        for (CompanyWalletBalanceDTO walletBalanceDTO : walletList) {
+            AdminCompanyWalletBalance walletBalance = walletBalanceMap.get(walletBalanceDTO.getWalletId());
+            walletBalanceDTO.computeCompanyWalletBalance(walletBalance, walletAccList, rebateAccList);
+        }
+    }
+
+    private Map<String, AdminCompanyWalletBalance> createNotExistWallet(List<CompanyWalletBalanceDTO> walletList, List<AdminCompanyWalletBalance> existWalletList) {
+        // 已存在的钱包转成Map
+        Map<String, AdminCompanyWalletBalance> existStockMap = existWalletList.stream()
+                .collect(Collectors.toMap(AdminCompanyWalletBalance::getWalletId, Function.identity()));
+
+        // 找出不存在的钱包并存入新钱包List
+        for (CompanyWalletBalanceDTO balanceDTO : walletList) {
+            AdminCompanyWalletBalance walletBalance = existStockMap.get(balanceDTO.getWalletId());
+            if (Objects.isNull(walletBalance)) {
+                walletBalance = balanceDTO.createWalletBalance();
+                existStockMap.put(balanceDTO.getWalletId(), walletBalance);
+            }
+        }
+        return existStockMap;
+    }
+
+
+    private void txCallUnlock(Lock obtain) {
+        //事务提交完成后才释放锁,此方法禁止执行mysql相关操作,否则将导致重大问题。
+        if (TransactionSynchronizationManager.isActualTransactionActive()) {
+            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                @Override
+                public void afterCompletion(int status) {
+
+                    if(TransactionSynchronization.STATUS_COMMITTED == status){
+                        log.info("=========【商户钱包】======事务提交==============");
+                    }else if(TransactionSynchronization.STATUS_ROLLED_BACK == status){
+                        log.info("========【商户钱包】=========事务回滚============");
+                    }
+
+                    obtain.unlock();
+                }
+            });
+        } else {
+            log.info("【商户钱包】====没有事务===释放锁");
+            obtain.unlock();
+        }
+    }
+}

+ 155 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/CompanyWalletLogic.java

@@ -0,0 +1,155 @@
+package com.gree.mall.manager.logic.supply.funds;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.gree.mall.manager.bean.admin.AdminUserCom;
+import com.gree.mall.manager.bean.supply.funds.CompanyWalletBalanceDTO;
+import com.gree.mall.manager.enums.ExamineStatusEnum;
+import com.gree.mall.manager.enums.material.DirectFlagEnum;
+import com.gree.mall.manager.enums.supply.BalanceBillTypeEnum;
+import com.gree.mall.manager.enums.supply.BalanceTypeEnum;
+import com.gree.mall.manager.enums.supply.RebateBillTypeEnum;
+import com.gree.mall.manager.enums.supply.ReceiptBillTypeEnum;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.plus.entity.Rebate;
+import com.gree.mall.manager.plus.entity.Receipt;
+import com.gree.mall.manager.plus.service.RebateService;
+import com.gree.mall.manager.plus.service.ReceiptService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class CompanyWalletLogic {
+
+    public final ReceiptService receiptService;
+    public final RebateService rebateService;
+    public final CompanyWalletBalanceLogic companyWalletBalanceLogic;
+
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public void handleReceiptCompanyWallet(List<Receipt> receiptList, AdminUserCom adminUser) {
+        try {
+            final List<Receipt> cList = receiptList.stream().filter(v -> v.getBillType().equals(ReceiptBillTypeEnum.C.getKey())).collect(Collectors.toList());
+            final List<Receipt> rList = receiptList.stream().filter(v -> v.getBillType().equals(ReceiptBillTypeEnum.R.getKey())).collect(Collectors.toList());
+
+            List<CompanyWalletBalanceDTO> dtoList = new ArrayList<>();
+            if (CollectionUtil.isNotEmpty(cList)) {
+                for (Receipt receipt : cList) {
+                    dtoList.add(new CompanyWalletBalanceDTO()
+                            .setDirectFlag(DirectFlagEnum.ADD.getKey())
+                            .setCompanyWechatId(receipt.getCompanyWechatId())
+                            .setCompanyName(receipt.getCompanyName())
+                            .setTheTime(receipt.getCreateTime())
+                            .setChangeAmount(receipt.getRealAmount())
+                            .setBillId(receipt.getId())
+                            .setBillType(BalanceBillTypeEnum.RECEIPT_BILL.getKey())
+                            .setWalletId(receipt.getWalletId())
+                            .setWalletType(BalanceTypeEnum.W.getKey())
+                            .setRemark(Objects.nonNull(receipt.getTheTime()) ? "业务日期:" + DateUtil.formatDate(receipt.getTheTime()) : "")
+                    );
+                }
+            }
+
+            if (CollectionUtil.isNotEmpty(rList)) {
+                for (Receipt receipt : rList) {
+                    dtoList.add(new CompanyWalletBalanceDTO()
+                            .setDirectFlag(DirectFlagEnum.SUB.getKey())
+                            .setCompanyWechatId(receipt.getCompanyWechatId())
+                            .setCompanyName(receipt.getCompanyName())
+                            .setTheTime(receipt.getCreateTime())
+                            .setChangeAmount(receipt.getRealAmount())
+                            .setBillId(receipt.getId())
+                            .setBillType(BalanceBillTypeEnum.RECEIPT_BILL.getKey())
+                            .setWalletId(receipt.getWalletId())
+                            .setWalletType(BalanceTypeEnum.W.getKey())
+                            .setRemark(Objects.nonNull(receipt.getTheTime()) ? "业务日期:" + DateUtil.formatDate(receipt.getTheTime()) : "")
+                    );
+                }
+            }
+
+            if (CollectionUtil.isNotEmpty(dtoList)) {
+                companyWalletBalanceLogic.handleCompanyWalletBalance(dtoList);
+            }
+
+        } catch (Exception e) {
+            throw new RemoteServiceException(e.getMessage());
+        }
+
+        // 更改为审核通过
+        receiptService.lambdaUpdate()
+                .set(Receipt::getUpdateBy, adminUser.getNickName())
+                .set(Receipt::getUpdateTime, DateUtil.date())
+                .set(Receipt::getStatus, ExamineStatusEnum.OK.getKey())
+                .eq(Receipt::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Receipt::getId, receiptList.stream().map(Receipt::getId).collect(Collectors.toSet()))
+                .update();
+    }
+
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public void handleRebateCompanyWallet(List<Rebate> rebateList, AdminUserCom adminUser) {
+        try {
+            final List<Rebate> cList = rebateList.stream().filter(v -> v.getBillType().equals(RebateBillTypeEnum.A.getKey())).collect(Collectors.toList());
+            final List<Rebate> rList = rebateList.stream().filter(v -> v.getBillType().equals(RebateBillTypeEnum.S.getKey())).collect(Collectors.toList());
+
+            List<CompanyWalletBalanceDTO> dtoList = new ArrayList<>();
+            if (CollectionUtil.isNotEmpty(cList)) {
+                for (Rebate receipt : cList) {
+                    dtoList.add(new CompanyWalletBalanceDTO()
+                            .setDirectFlag(DirectFlagEnum.ADD.getKey())
+                            .setCompanyWechatId(receipt.getCompanyWechatId())
+                            .setCompanyName(receipt.getCompanyName())
+                            .setTheTime(receipt.getCreateTime())
+                            .setChangeAmount(receipt.getRealAmount())
+                            .setBillId(receipt.getId())
+                            .setBillType(BalanceBillTypeEnum.REBATE_BILL.getKey())
+                            .setWalletId(receipt.getRebateTypeId())
+                            .setWalletType(BalanceTypeEnum.R.getKey())
+                            .setRemark(Objects.nonNull(receipt.getTheTime()) ? "业务日期:" + DateUtil.formatDate(receipt.getTheTime()) : "")
+                    );
+                }
+            }
+
+            if (CollectionUtil.isNotEmpty(rList)) {
+                for (Rebate receipt : rList) {
+                    dtoList.add(new CompanyWalletBalanceDTO()
+                            .setDirectFlag(DirectFlagEnum.SUB.getKey())
+                            .setCompanyWechatId(receipt.getCompanyWechatId())
+                            .setCompanyName(receipt.getCompanyName())
+                            .setTheTime(receipt.getCreateTime())
+                            .setChangeAmount(receipt.getRealAmount())
+                            .setBillId(receipt.getId())
+                            .setBillType(BalanceBillTypeEnum.REBATE_BILL.getKey())
+                            .setWalletId(receipt.getRebateTypeId())
+                            .setWalletType(BalanceTypeEnum.R.getKey())
+                            .setRemark(Objects.nonNull(receipt.getTheTime()) ? "业务日期:" + DateUtil.formatDate(receipt.getTheTime()) : "")
+                    );
+                }
+            }
+
+            if (CollectionUtil.isNotEmpty(dtoList)) {
+                companyWalletBalanceLogic.handleCompanyWalletBalance(dtoList);
+            }
+
+        } catch (Exception e) {
+            throw new RemoteServiceException(e.getMessage());
+        }
+
+        // 更改为审核通过
+        rebateService.lambdaUpdate()
+                .set(Rebate::getUpdateBy, adminUser.getNickName())
+                .set(Rebate::getUpdateTime, DateUtil.date())
+                .set(Rebate::getStatus, ExamineStatusEnum.OK.getKey())
+                .eq(Rebate::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Rebate::getId, rebateList.stream().map(Rebate::getId).collect(Collectors.toSet()))
+                .update();
+    }
+}

+ 176 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/RebateLogic.java

@@ -0,0 +1,176 @@
+package com.gree.mall.manager.logic.supply.funds;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.manager.bean.admin.AdminUserCom;
+import com.gree.mall.manager.bean.supply.funds.RebateVO;
+import com.gree.mall.manager.commonmapper.CommonMapper;
+import com.gree.mall.manager.enums.ExamineStatusEnum;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import com.gree.mall.manager.enums.supply.RebateBillTypeEnum;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.logic.common.CommonLogic;
+import com.gree.mall.manager.plus.entity.AdminCompanyWechat;
+import com.gree.mall.manager.plus.entity.Rebate;
+import com.gree.mall.manager.plus.entity.RebateType;
+import com.gree.mall.manager.plus.service.AdminCompanyWechatService;
+import com.gree.mall.manager.plus.service.RebateService;
+import com.gree.mall.manager.plus.service.RebateTypeService;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class RebateLogic {
+
+
+    private final CommonLogic commonLogic;
+    private final CommonMapper commonMapper;
+    private final AdminCompanyWechatService adminCompanyWechatService;
+    private final RebateTypeService rebateTypeService;
+    private final RebateService rebateService;
+    private final CompanyWalletLogic companyWalletLogic;
+
+    public IPage<RebateVO> list(ZfireParamBean zfireParamBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        FieldUtils.supplyParam(zfireParamBean, RebateVO.class, adminUser);
+
+        return commonMapper.rebateList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+    }
+
+    @Transactional
+    public int importData(List<Object> objects) {
+        //所有商户
+        List<AdminCompanyWechat> adminCompanyWechatList = adminCompanyWechatService.list();
+        Map<String, AdminCompanyWechat> companyWechatMap = adminCompanyWechatList.stream().collect(Collectors.toMap(AdminCompanyWechat::getCorpId, v -> v));
+
+        //查询所有返利类型
+        List<RebateType> rebateTypeList = rebateTypeService.list();
+        Map<String, RebateType> rebateTypeMap = rebateTypeList.stream().collect(Collectors.toMap(RebateType::getCode, v -> v));
+
+        List<Rebate> rebateList = new ArrayList<>();
+
+        int index = 2;
+        for(Object o : objects) {
+            List<Object> row = (List<Object>) o;
+            String billNo = (String) row.get(0);
+            String billType = (String) row.get(1);
+            String companyCode = (String) row.get(2);
+            String rebateTypeCode = (String) row.get(3);
+            String realAmountStr = (String) row.get(4);
+            String theTimeStr = (String) row.get(5);
+
+            if (StringUtils.isEmpty(billNo) || StringUtils.isEmpty(billType)
+                    || StringUtils.isEmpty(companyCode) || StringUtils.isEmpty(rebateTypeCode)
+                    || StringUtils.isEmpty(realAmountStr)) {
+                throw new RemoteServiceException("第" + index + "行, 检测到单据编号/单据类型/商户编码/返利类型编码/返利金额 有为空的情况");
+            }
+
+            boolean exists = BaseEnum.keyToEnumOpt(RebateBillTypeEnum.class, billType).isPresent(); // false
+
+            if (!exists) {
+                throw new RemoteServiceException("第" + index + "行, 单据类型不存在");
+            }
+
+            if (!companyWechatMap.containsKey(companyCode)) {
+                throw new RemoteServiceException("第" + index + "行, 商户编码不存在");
+            }
+
+            if (!rebateTypeMap.containsKey(rebateTypeCode)) {
+                throw new RemoteServiceException("第" + index + "行, 返利类型编码不存在");
+            }
+
+            BigDecimal realAmount;
+            try {
+                realAmount = new BigDecimal(realAmountStr);
+                if (realAmount.compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new RemoteServiceException("第" + index + "行, 返利金额不能少于等于0");
+                }
+            } catch (Exception e) {
+                throw new RemoteServiceException("第" + index + "行, 返利金额异常");
+            }
+
+            Date theTime = null;
+            if (StringUtils.isNotBlank(theTimeStr)) {
+                try {
+                    theTime = DateUtil.parseDate(theTimeStr);
+                } catch (Exception e) {
+                    throw new RemoteServiceException("第" + index + "行, 业务日期格式不正确, 要求:yyyy-MM-dd");
+                }
+            }
+
+            final AdminCompanyWechat companyWechat = companyWechatMap.get(companyCode);
+            final RebateType rebateType = rebateTypeMap.get(rebateTypeCode);
+
+            Rebate rebate = new Rebate();
+            rebate.setBillNo(billNo);
+            rebate.setBillType(billType);
+            rebate.setCompanyWechatId(companyWechat.getCompanyWechatId());
+            rebate.setCompanyName(companyWechat.getCompanyName());
+            rebate.setRebateTypeId(rebateType.getId());
+            rebate.setRealAmount(realAmount);
+            rebate.setStatus(ExamineStatusEnum.WAIT.getKey());
+            rebate.setTheTime(theTime);
+
+            rebateList.add(rebate);
+        }
+
+        if (CollectionUtil.isNotEmpty(rebateList)) {
+            rebateService.saveBatch(rebateList);
+        }
+
+        return rebateList.size();
+    }
+
+    @Transactional
+    public void batchExamine(List<String> ids) {
+        final List<Rebate> rebateList = rebateService.lambdaQuery()
+                .eq(Rebate::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Rebate::getId, ids)
+                .list();
+
+        if (CollectionUtil.isEmpty(rebateList)) {
+            return;
+        }
+
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+
+        // 商户分组
+        Map<String, List<Rebate>> companyGroupMap = rebateList.stream()
+                .collect(Collectors.groupingBy(Rebate::getCompanyWechatId));
+
+        for (Map.Entry<String, List<Rebate>> entry : companyGroupMap.entrySet()) {
+            // 开始处理钱包逻辑
+            companyWalletLogic.handleRebateCompanyWallet(entry.getValue(), adminUser);
+        }
+
+    }
+
+    @Transactional
+    public void batchFail(List<String> ids) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        // 批量驳回
+        rebateService.lambdaUpdate()
+                .set(Rebate::getUpdateBy, adminUser.getNickName())
+                .set(Rebate::getUpdateTime, DateUtil.date())
+                .set(Rebate::getStatus, ExamineStatusEnum.FAIL.getKey())
+                .eq(Rebate::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Rebate::getId, ids)
+                .update();
+    }
+}

+ 202 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/ReceiptLogic.java

@@ -0,0 +1,202 @@
+package com.gree.mall.manager.logic.supply.funds;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.manager.bean.admin.AdminUserCom;
+import com.gree.mall.manager.bean.supply.funds.ReceiptVO;
+import com.gree.mall.manager.commonmapper.CommonMapper;
+import com.gree.mall.manager.enums.ExamineStatusEnum;
+import com.gree.mall.manager.enums.base.BaseEnum;
+import com.gree.mall.manager.enums.supply.ReceiptBillTypeEnum;
+import com.gree.mall.manager.exception.RemoteServiceException;
+import com.gree.mall.manager.logic.common.CommonLogic;
+import com.gree.mall.manager.plus.entity.AdminCompanyWallet;
+import com.gree.mall.manager.plus.entity.AdminCompanyWechat;
+import com.gree.mall.manager.plus.entity.Receipt;
+import com.gree.mall.manager.plus.entity.Wallet;
+import com.gree.mall.manager.plus.service.AdminCompanyWalletService;
+import com.gree.mall.manager.plus.service.AdminCompanyWechatService;
+import com.gree.mall.manager.plus.service.ReceiptService;
+import com.gree.mall.manager.plus.service.WalletService;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ReceiptLogic {
+
+    private final CommonLogic commonLogic;
+    private final CommonMapper commonMapper;
+    private final AdminCompanyWechatService adminCompanyWechatService;
+    private final AdminCompanyWalletService adminCompanyWechatWalletService;
+    private final WalletService walletService;
+    private final ReceiptService receiptService;
+    private final CompanyWalletLogic companyWalletLogic;
+
+    public IPage<ReceiptVO> list(ZfireParamBean zfireParamBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        FieldUtils.supplyParam(zfireParamBean, ReceiptVO.class, adminUser);
+
+        return commonMapper.receiptList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+    }
+
+    @Transactional
+    public int importData(List<Object> objects) {
+        //所有商户
+        List<AdminCompanyWechat> adminCompanyWechatList = adminCompanyWechatService.list();
+        Map<String, AdminCompanyWechat> companyWechatMap = adminCompanyWechatList.stream().collect(Collectors.toMap(AdminCompanyWechat::getCorpId, v -> v));
+
+        //查询所有现金钱包
+        List<Wallet> wallets = walletService.list();
+        Map<String, Wallet> walletMap = wallets.stream().collect(Collectors.toMap(Wallet::getCode, v -> v));
+
+        //查询所有商户现金钱包
+        List<AdminCompanyWallet> companyWechatWalletList = adminCompanyWechatWalletService.list();
+        Map<String, AdminCompanyWallet> companyWechatWalletMap = companyWechatWalletList.stream().collect(Collectors.toMap(v -> v.getCompanyWechatId() + v.getWalletId(), v -> v));
+
+        List<Receipt> receiptList = new ArrayList<>();
+
+        int index = 2;
+        for(Object o : objects) {
+            List<Object> row = (List<Object>) o;
+            String billNo = (String) row.get(0);
+            String billType = (String) row.get(1);
+            String companyCode = (String) row.get(2);
+            String walletCode = (String) row.get(3);
+            String amountStr = (String) row.get(4);
+            String realAmountStr = (String) row.get(5);
+            String theTimeStr = (String) row.get(6);
+
+            if (StringUtils.isEmpty(billNo) || StringUtils.isEmpty(billType)
+                    || StringUtils.isEmpty(companyCode) || StringUtils.isEmpty(walletCode)
+                    || StringUtils.isEmpty(amountStr) || StringUtils.isEmpty(realAmountStr)) {
+                throw new RemoteServiceException("第" + index + "行, 检测到单据编号/单据类型/商户编码/钱包编码/应收金额/实收金额 有为空的情况");
+            }
+
+            boolean exists = BaseEnum.keyToEnumOpt(ReceiptBillTypeEnum.class, billType).isPresent(); // false
+
+            if (!exists) {
+                throw new RemoteServiceException("第" + index + "行, 单据类型不存在");
+            }
+
+            if (!companyWechatMap.containsKey(companyCode)) {
+                throw new RemoteServiceException("第" + index + "行, 商户编码不存在");
+            }
+
+            if (!walletMap.containsKey(walletCode)) {
+                throw new RemoteServiceException("第" + index + "行, 钱包编码不存在");
+            }
+
+            final AdminCompanyWechat companyWechat = companyWechatMap.get(companyCode);
+            final Wallet wallet = walletMap.get(walletCode);
+
+            if (!companyWechatWalletMap.containsKey(companyWechat.getCompanyWechatId() + wallet.getId())) {
+                throw new RemoteServiceException("第" + index + "行, 商户与钱包关系不存在");
+            }
+
+            BigDecimal amount;
+            try {
+                amount = new BigDecimal(amountStr);
+                if (amount.compareTo(BigDecimal.ZERO) < 0) {
+                    throw new RemoteServiceException("第" + index + "行, 应收金额不能少于0");
+                }
+            } catch (Exception e) {
+                throw new RemoteServiceException("第" + index + "行, 应收金额异常");
+            }
+
+            BigDecimal realAmount;
+            try {
+                realAmount = new BigDecimal(realAmountStr);
+                if (realAmount.compareTo(BigDecimal.ZERO) <= 0) {
+                    throw new RemoteServiceException("第" + index + "行, 实收金额不能少于等于0");
+                }
+            } catch (Exception e) {
+                throw new RemoteServiceException("第" + index + "行, 实收金额异常");
+            }
+
+            Date theTime = null;
+            if (StringUtils.isNotBlank(theTimeStr)) {
+                try {
+                    theTime = DateUtil.parseDate(theTimeStr);
+                } catch (Exception e) {
+                    throw new RemoteServiceException("第" + index + "行, 业务日期格式不正确, 要求:yyyy-MM-dd");
+                }
+            }
+
+
+            final AdminCompanyWallet companyWallet = companyWechatWalletMap.get(companyWechat.getCompanyWechatId() + wallet.getId());
+
+            Receipt receipt = new Receipt();
+            receipt.setBillNo(billNo);
+            receipt.setBillType(billType);
+            receipt.setCompanyWechatId(companyWallet.getCompanyWechatId());
+            receipt.setCompanyName(companyWechat.getCompanyName());
+            receipt.setWalletId(companyWallet.getWalletId());
+            receipt.setAmount(amount);
+            receipt.setRealAmount(realAmount);
+            receipt.setStatus(ExamineStatusEnum.WAIT.getKey());
+            receipt.setTheTime(theTime);
+
+            receiptList.add(receipt);
+        }
+
+        if (CollectionUtil.isNotEmpty(receiptList)) {
+            receiptService.saveBatch(receiptList);
+        }
+
+        return receiptList.size();
+    }
+
+    @Transactional
+    public void batchExamine(List<String> ids) {
+        final List<Receipt> receiptList = receiptService.lambdaQuery()
+                .eq(Receipt::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Receipt::getId, ids)
+                .list();
+
+        if (CollectionUtil.isEmpty(receiptList)) {
+            return;
+        }
+
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+
+        // 商户分组
+        Map<String, List<Receipt>> companyGroupMap = receiptList.stream()
+                .collect(Collectors.groupingBy(Receipt::getCompanyWechatId));
+
+        for (Map.Entry<String, List<Receipt>> entry : companyGroupMap.entrySet()) {
+            // 开始处理钱包逻辑
+            companyWalletLogic.handleReceiptCompanyWallet(entry.getValue(), adminUser);
+        }
+
+
+    }
+
+    @Transactional
+    public void batchFail(List<String> ids) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        // 批量驳回
+        receiptService.lambdaUpdate()
+                .set(Receipt::getUpdateBy, adminUser.getNickName())
+                .set(Receipt::getUpdateTime, DateUtil.date())
+                .set(Receipt::getStatus, ExamineStatusEnum.FAIL.getKey())
+                .eq(Receipt::getStatus, ExamineStatusEnum.WAIT.getKey())
+                .in(Receipt::getId, ids)
+                .update();
+    }
+}

+ 37 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/funds/WalletBalanceUseAccLogic.java

@@ -0,0 +1,37 @@
+package com.gree.mall.manager.logic.supply.funds;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.manager.bean.admin.AdminUserCom;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyRebateAccVO;
+import com.gree.mall.manager.bean.supply.funds.AdminCompanyWalletAccVO;
+import com.gree.mall.manager.commonmapper.CommonMapper;
+import com.gree.mall.manager.logic.common.CommonLogic;
+import com.gree.mall.manager.zfire.bean.ZfireParamBean;
+import com.gree.mall.manager.zfire.util.FieldUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WalletBalanceUseAccLogic {
+
+    private final CommonLogic commonLogic;
+    private final CommonMapper commonMapper;
+
+    public IPage<AdminCompanyWalletAccVO> walletList(ZfireParamBean zfireParamBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        FieldUtils.supplyParam(zfireParamBean, AdminCompanyWalletAccVO.class, adminUser);
+
+        return commonMapper.walletBalanceUseAccList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+    }
+
+    public IPage<AdminCompanyRebateAccVO> rebateList(ZfireParamBean zfireParamBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        FieldUtils.supplyParam(zfireParamBean, AdminCompanyRebateAccVO.class, adminUser);
+
+        return commonMapper.rebateBalanceUseAccList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+    }
+}

+ 61 - 21
mall-server-api/src/main/java/com/gree/mall/manager/logic/supply/sales/config/SupplyPayConfigLogic.java

@@ -5,10 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.manager.bean.admin.AdminUserCom;
-import com.gree.mall.manager.bean.supply.sales.config.CompanyWalletVO;
-import com.gree.mall.manager.bean.supply.sales.config.RebateTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.SalesTypeVO;
-import com.gree.mall.manager.bean.supply.sales.config.WalletVO;
+import com.gree.mall.manager.bean.supply.sales.config.*;
 import com.gree.mall.manager.commonmapper.CommonMapper;
 import com.gree.mall.manager.enums.StatusEnum;
 import com.gree.mall.manager.exception.RemoteServiceException;
@@ -36,8 +33,9 @@ public class SupplyPayConfigLogic {
     private final SalesTypeService salesTypeService;
     private final WalletService walletService;
     private final RebateTypeService rebateTypeService;
-    private final AdminCompanyWechatWalletService adminCompanyWechatWalletService;
+    private final AdminCompanyWalletService adminCompanyWalletService;
     private final AdminCompanyWechatService adminCompanyWechatService;
+    private final RebateTypeUseRateService rebateTypeUseRateService;
 
     public IPage<SalesTypeVO> typeList(ZfireParamBean zfireParamBean) {
         AdminUserCom adminUser = commonLogic.getAdminUser();
@@ -136,34 +134,34 @@ public class SupplyPayConfigLogic {
 
     public IPage<CompanyWalletVO> companyWalletList(ZfireParamBean zfireParamBean) {
         AdminUserCom adminUser = commonLogic.getAdminUser();
-        FieldUtils.supplyParam(zfireParamBean, RebateTypeVO.class, adminUser);
+        FieldUtils.supplyParam(zfireParamBean, CompanyWalletVO.class, adminUser);
 
         return commonMapper.companyWalletList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
     }
 
     @Transactional
-    public void companyWalletAdd(AdminCompanyWechatWallet adminCompanyWechatWallet) {
-        if (StringUtils.isBlank(adminCompanyWechatWallet.getCompanyWechatId())) {
+    public void companyWalletAdd(AdminCompanyWallet adminCompanyWallet) {
+        if (StringUtils.isBlank(adminCompanyWallet.getCompanyWechatId())) {
             throw new RemoteServiceException("商户不能为空, 请检查!");
         }
-        if (StringUtils.isBlank(adminCompanyWechatWallet.getWalletId())) {
+        if (StringUtils.isBlank(adminCompanyWallet.getWalletId())) {
             throw new RemoteServiceException("钱包不能为空, 请检查!");
         }
 
-        final Integer count = adminCompanyWechatWalletService.lambdaQuery()
-                .eq(AdminCompanyWechatWallet::getCompanyWechatId, adminCompanyWechatWallet.getCompanyWechatId())
-                .eq(AdminCompanyWechatWallet::getWalletId, adminCompanyWechatWallet.getWalletId())
+        final Integer count = adminCompanyWalletService.lambdaQuery()
+                .eq(AdminCompanyWallet::getCompanyWechatId, adminCompanyWallet.getCompanyWechatId())
+                .eq(AdminCompanyWallet::getWalletId, adminCompanyWallet.getWalletId())
                 .count();
         if (count > 0) {
             throw new RemoteServiceException("商户与钱包关系已存在重复, 请检查!");
         }
-        adminCompanyWechatWallet.setId(IdWorker.getIdStr());
-        adminCompanyWechatWallet.insert();
+        adminCompanyWallet.setId(IdWorker.getIdStr());
+        adminCompanyWallet.insert();
     }
 
     @Transactional
     public void companyWalletBatchDel(List<String> ids) {
-        adminCompanyWechatWalletService.removeByIds(ids);
+        adminCompanyWalletService.removeByIds(ids);
     }
 
     @Transactional
@@ -176,7 +174,7 @@ public class SupplyPayConfigLogic {
         List<Wallet> wallets = walletService.list();
         Map<String, Wallet> walletMap = wallets.stream().collect(Collectors.toMap(Wallet::getCode, v -> v));
 
-        List<AdminCompanyWechatWallet> resultList = new ArrayList<>();
+        List<AdminCompanyWallet> resultList = new ArrayList<>();
         Set<String> set = new HashSet<>();
 
         int index = 2;
@@ -199,7 +197,7 @@ public class SupplyPayConfigLogic {
             }
 
 
-            AdminCompanyWechatWallet item = new AdminCompanyWechatWallet();
+            AdminCompanyWallet item = new AdminCompanyWallet();
             item.setCompanyWechatId(companyWechatMap.get(StrUtil.trim(companyCode)).getCompanyWechatId());
             item.setWalletId(walletMap.get(StrUtil.trim(walletCode)).getId());
 
@@ -207,9 +205,9 @@ public class SupplyPayConfigLogic {
                 throw new RemoteServiceException("第" + index + "行, 发现导入文件有重复的商户编码和钱包编码");
             }
 
-            final Integer count = adminCompanyWechatWalletService.lambdaQuery()
-                    .eq(AdminCompanyWechatWallet::getCompanyWechatId, item.getCompanyWechatId())
-                    .eq(AdminCompanyWechatWallet::getWalletId, item.getWalletId())
+            final Integer count = adminCompanyWalletService.lambdaQuery()
+                    .eq(AdminCompanyWallet::getCompanyWechatId, item.getCompanyWechatId())
+                    .eq(AdminCompanyWallet::getWalletId, item.getWalletId())
                     .count();
             if (count > 0) {
                 throw new RemoteServiceException("第" + index + "行, 商户与钱包关系已存在重复, 请检查!");
@@ -222,8 +220,50 @@ public class SupplyPayConfigLogic {
             index++;
         }
 
-        adminCompanyWechatWalletService.saveBatch(resultList);
+        adminCompanyWalletService.saveBatch(resultList);
 
         return resultList.size();
     }
+
+    public IPage<RebateTypeRateVO> rebateTypeRateList(ZfireParamBean zfireParamBean) {
+        AdminUserCom adminUser = commonLogic.getAdminUser();
+        FieldUtils.platformParam(zfireParamBean, RebateTypeRateVO.class, adminUser);
+
+        return commonMapper.rebateTypeRetaList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+    }
+
+    @Transactional
+    public void rebateTypeRateSave(RebateTypeUseRate rebateTypeUseRate) {
+
+        if (StringUtils.isBlank(rebateTypeUseRate.getRebateTypeId())) {
+            throw new RemoteServiceException("返利类型不能为空, 请检查!");
+        }
+        if (StringUtils.isBlank(rebateTypeUseRate.getSalesTypeId())) {
+            throw new RemoteServiceException("销售类型不能为空, 请检查!");
+        }
+
+        final Integer count = rebateTypeUseRateService.lambdaQuery()
+                .eq(RebateTypeUseRate::getRebateTypeId, rebateTypeUseRate.getRebateTypeId())
+                .eq(RebateTypeUseRate::getSalesTypeId, rebateTypeUseRate.getSalesTypeId())
+                .ne(StringUtils.isNotBlank(rebateTypeUseRate.getId()), RebateTypeUseRate::getId, rebateTypeUseRate.getId())
+                .count();
+        if (count > 0) {
+            throw new RemoteServiceException("返利类型与销售类型存在重复, 请检查!");
+        }
+        if (StringUtils.isBlank(rebateTypeUseRate.getId())) {
+            rebateTypeUseRate.setId(IdWorker.getIdStr());
+        }
+        rebateTypeUseRate.setCompanyWechatId("0");
+
+        rebateTypeUseRate.insertOrUpdate();
+    }
+
+    @Transactional
+    public void rebateTypeRateBatchDel(List<String> ids) {
+        rebateTypeUseRateService.removeByIds(ids);
+    }
+
+    public RebateTypeUseRate rebateTypeRateDetail(String id) {
+        return rebateTypeUseRateService.getById(id);
+    }
 }

+ 64 - 1
mall-server-api/src/main/resources/mapper/CommonMapper.xml

@@ -1392,7 +1392,7 @@
     <select id="companyWalletList" resultType="com.gree.mall.manager.bean.supply.sales.config.CompanyWalletVO">
         SELECT
         ${ex.selected}
-        FROM admin_company_wechat_wallet a LEFT JOIN wallet b ON a.wallet_id = b.id
+        FROM admin_company_wallet a LEFT JOIN wallet b ON a.wallet_id = b.id
         LEFT JOIN admin_company_wechat c on a.company_wechat_id = c.company_wechat_id
         ${ex.query}
         <if test="ex.orderBy == null or ex.orderBy ==''">
@@ -1401,4 +1401,67 @@
         ${ex.orderBy}
     </select>
 
+    <select id="rebateTypeRetaList"
+            resultType="com.gree.mall.manager.bean.supply.sales.config.RebateTypeRateVO">
+        SELECT
+            ${ex.selected},
+            b.id AS rebate_type_id,
+            c.id AS sales_type_id,
+            c.code AS sales_type_code,
+            c.name AS sales_type_name
+        FROM rebate_type_use_rate a LEFT JOIN rebate_type b ON a.rebate_type_id = b.id
+        LEFT JOIN sales_type c on a.sales_type_id = c.id
+        ${ex.query}
+        <if test="ex.orderBy == null or ex.orderBy ==''">
+            ORDER BY a.create_time DESC
+        </if>
+        ${ex.orderBy}
+    </select>
+
+    <select id="receiptList" resultType="com.gree.mall.manager.bean.supply.funds.ReceiptVO">
+        SELECT
+            ${ex.selected}
+        FROM receipt a LEFT JOIN wallet b ON a.wallet_id = b.id
+        ${ex.query}
+        <if test="ex.orderBy == null or ex.orderBy ==''">
+            ORDER BY a.create_time DESC
+        </if>
+        ${ex.orderBy}
+    </select>
+
+    <select id="rebateList" resultType="com.gree.mall.manager.bean.supply.funds.RebateVO">
+        SELECT
+        ${ex.selected}
+        FROM rebate a LEFT JOIN rebate_type b ON a.rebate_type_id = b.id
+        ${ex.query}
+        <if test="ex.orderBy == null or ex.orderBy ==''">
+            ORDER BY a.create_time DESC
+        </if>
+        ${ex.orderBy}
+    </select>
+
+    <select id="walletBalanceUseAccList"
+            resultType="com.gree.mall.manager.bean.supply.funds.AdminCompanyWalletAccVO">
+        SELECT
+        ${ex.selected}
+        FROM admin_company_wallet_acc a LEFT JOIN wallet b ON a.wallet_id = b.id
+        ${ex.query}
+        <if test="ex.orderBy == null or ex.orderBy ==''">
+            ORDER BY a.create_time DESC
+        </if>
+        ${ex.orderBy}
+    </select>
+
+    <select id="rebateBalanceUseAccList"
+            resultType="com.gree.mall.manager.bean.supply.funds.AdminCompanyRebateAccVO">
+        SELECT
+        ${ex.selected}
+        FROM admin_company_rebate_acc a LEFT JOIN rebate_type b ON a.wallet_id = b.id
+        ${ex.query}
+        <if test="ex.orderBy == null or ex.orderBy ==''">
+            ORDER BY a.create_time DESC
+        </if>
+        ${ex.orderBy}
+    </select>
+
 </mapper>

+ 11 - 0
mall-server-api/src/main/resources/mapper/LockQueryMapper.xml

@@ -52,4 +52,15 @@
         FOR UPDATE
     </select>
 
+    <select id="queryExistCompanyWalletBalanceList"
+            resultType="com.gree.mall.manager.plus.entity.AdminCompanyWalletBalance">
+        SELECT
+        *
+        FROM
+        admin_company_wallet_balance
+        WHERE
+        company_wechat_id = #{dto.companyWechatId}
+        FOR UPDATE
+    </select>
+
 </mapper>

BIN
mall-server-api/src/main/resources/template/收款单模板.xlsx


BIN
mall-server-api/src/main/resources/template/返利单模板.xlsx