商户支付能力配置页面
diff --git a/src/main/java/com/supwisdom/dlpay/api/dao/PaytypeDao.java b/src/main/java/com/supwisdom/dlpay/api/dao/PaytypeDao.java
index 0b0b998..bd2c959 100644
--- a/src/main/java/com/supwisdom/dlpay/api/dao/PaytypeDao.java
+++ b/src/main/java/com/supwisdom/dlpay/api/dao/PaytypeDao.java
@@ -4,8 +4,11 @@
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * Created by shuwei on 2019/4/9.
  */
@@ -14,4 +17,7 @@
   TPaytype getByPaytype(String paytype);
 
   Page<TPaytype> findByPaytypeContaining(String paytype, Pageable pageable);
+
+  @Query("select t from TPaytype t")
+  List<TPaytype> getConsumePaytypes();
 }
diff --git a/src/main/java/com/supwisdom/dlpay/api/dao/ShopPaytypeDao.java b/src/main/java/com/supwisdom/dlpay/api/dao/ShopPaytypeDao.java
index 750f8ac..03196e1 100644
--- a/src/main/java/com/supwisdom/dlpay/api/dao/ShopPaytypeDao.java
+++ b/src/main/java/com/supwisdom/dlpay/api/dao/ShopPaytypeDao.java
@@ -3,11 +3,13 @@
 import com.supwisdom.dlpay.api.domain.TShopPaytype;
 import com.supwisdom.dlpay.api.domain.TShopPaytypePK;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface ShopPaytypeDao extends JpaRepository<TShopPaytype,TShopPaytypePK> {
+public interface ShopPaytypeDao extends JpaRepository<TShopPaytype, TShopPaytypePK>, JpaSpecificationExecutor<TShopPaytype> {
   @Query("select a from TShopPaytype a where a.paytype=?1 and a.shopaccno=?2 ")
   TShopPaytype getById(String paytype, String shopaccno);
+
 }
diff --git a/src/main/java/com/supwisdom/dlpay/system/bean/ShopConfigBean.java b/src/main/java/com/supwisdom/dlpay/system/bean/ShopConfigBean.java
new file mode 100644
index 0000000..0bd5256
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/system/bean/ShopConfigBean.java
@@ -0,0 +1,80 @@
+package com.supwisdom.dlpay.system.bean;
+
+public class ShopConfigBean {
+  private String shopaccno;
+  private String shopname;
+  private String paytype;
+  private String paydesc;
+  private String consumeEnable;
+  private String anonymousEnable;
+  private String reverseEnable;
+
+  public ShopConfigBean() {
+  }
+
+  public ShopConfigBean(String shopaccno, String shopname, String paytype, String paydesc, String consumeEnable, String anonymousEnable, String reverseEnable) {
+    this.shopaccno = shopaccno;
+    this.shopname = shopname;
+    this.paytype = paytype;
+    this.paydesc = paydesc;
+    this.consumeEnable = consumeEnable;
+    this.anonymousEnable = anonymousEnable;
+    this.reverseEnable = reverseEnable;
+  }
+
+  public String getShopaccno() {
+    return shopaccno;
+  }
+
+  public void setShopaccno(String shopaccno) {
+    this.shopaccno = shopaccno;
+  }
+
+  public String getShopname() {
+    return shopname;
+  }
+
+  public void setShopname(String shopname) {
+    this.shopname = shopname;
+  }
+
+  public String getPaytype() {
+    return paytype;
+  }
+
+  public void setPaytype(String paytype) {
+    this.paytype = paytype;
+  }
+
+  public String getPaydesc() {
+    return paydesc;
+  }
+
+  public void setPaydesc(String paydesc) {
+    this.paydesc = paydesc;
+  }
+
+  public String getConsumeEnable() {
+    return consumeEnable;
+  }
+
+  public void setConsumeEnable(String consumeEnable) {
+    this.consumeEnable = consumeEnable;
+  }
+
+  public String getAnonymousEnable() {
+    return anonymousEnable;
+  }
+
+  public void setAnonymousEnable(String anonymousEnable) {
+    this.anonymousEnable = anonymousEnable;
+  }
+
+  public String getReverseEnable() {
+    return reverseEnable;
+  }
+
+  public void setReverseEnable(String reverseEnable) {
+    this.reverseEnable = reverseEnable;
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/system/controller/ShopController.java b/src/main/java/com/supwisdom/dlpay/system/controller/ShopController.java
index a94f906..5f09c4e 100644
--- a/src/main/java/com/supwisdom/dlpay/system/controller/ShopController.java
+++ b/src/main/java/com/supwisdom/dlpay/system/controller/ShopController.java
@@ -1,14 +1,20 @@
 package com.supwisdom.dlpay.system.controller;
 
 import com.supwisdom.dlpay.api.bean.JsonResult;
+import com.supwisdom.dlpay.api.domain.TPaytype;
+import com.supwisdom.dlpay.api.domain.TShopPaytype;
 import com.supwisdom.dlpay.framework.domain.TShop;
+import com.supwisdom.dlpay.framework.util.PageResult;
 import com.supwisdom.dlpay.framework.util.StringUtil;
 import com.supwisdom.dlpay.framework.util.TradeDict;
+import com.supwisdom.dlpay.framework.util.WebConstant;
+import com.supwisdom.dlpay.system.bean.ShopConfigBean;
 import com.supwisdom.dlpay.system.service.ShopDataService;
 import com.supwisdom.dlpay.util.WebCheckException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
 
 @Controller
@@ -131,5 +137,40 @@
     }
   }
 
+  /**
+   * ====================================================
+   *              商户支付能力配置
+   * ====================================================
+   */
+  @GetMapping("/shop/config")
+  public String shopConfigView(Model model) {
+    model.addAttribute("paytypelist", shopDataService.getConsumePaytypes());
+    return "system/shop/config";
+  }
+
+  @GetMapping("/shop/shopacctree")
+  @PreAuthorize("hasPermission('/shop/config','')")
+  @ResponseBody
+  public JsonResult shopaccTreeData(){
+    return JsonResult.ok("OK").put("data", shopDataService.getAllShopNodes());
+  }
+
+  @GetMapping("/shop/shoppaytypelist")
+  @PreAuthorize("hasPermission('/shop/shoppaytypelist','')")
+  @ResponseBody
+  public PageResult<ShopConfigBean> getShopPaytypeList(@RequestParam("page") Integer pageNo,
+                                                       @RequestParam("limit") Integer pageSize,
+                                                       @RequestParam(value = "shopid", required = false) Integer shopid,
+                                                       @RequestParam(value = "paytype", required = false) String paytype,
+                                                       @RequestParam(value = "shopaccno", required = false) String shopaccno) {
+    try {
+      if (null == pageNo || pageNo < 1) pageNo = WebConstant.PAGENO_DEFAULT;
+      if (null == pageSize || pageSize < 1) pageSize = WebConstant.PAGESIZE_DEFAULT;
+      return shopDataService.getShopPaytypeInfos(shopaccno, paytype, shopid, pageNo, pageSize);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return new PageResult<>(99, "系统查询错误");
+    }
+  }
 
 }
diff --git a/src/main/java/com/supwisdom/dlpay/system/service/ShopDataService.java b/src/main/java/com/supwisdom/dlpay/system/service/ShopDataService.java
index 9a5dd9a..fe9ce27 100644
--- a/src/main/java/com/supwisdom/dlpay/system/service/ShopDataService.java
+++ b/src/main/java/com/supwisdom/dlpay/system/service/ShopDataService.java
@@ -1,6 +1,9 @@
 package com.supwisdom.dlpay.system.service;
 
+import com.supwisdom.dlpay.api.domain.TPaytype;
 import com.supwisdom.dlpay.framework.domain.TShop;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.system.bean.ShopConfigBean;
 import com.supwisdom.dlpay.system.bean.ZTreeNode;
 import com.supwisdom.dlpay.util.WebCheckException;
 import org.springframework.transaction.annotation.Propagation;
@@ -20,4 +23,10 @@
 
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
   boolean saveOrUpdateShop(TShop shop) throws WebCheckException;
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class,readOnly = true)
+  List<TPaytype> getConsumePaytypes();
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class,readOnly = true)
+  PageResult<ShopConfigBean> getShopPaytypeInfos(String shopaccno, String paytype, Integer shopid, int pageNo, int pageSize);
 }
diff --git a/src/main/java/com/supwisdom/dlpay/system/service/impl/ShopDataServiceImpl.java b/src/main/java/com/supwisdom/dlpay/system/service/impl/ShopDataServiceImpl.java
index c8d3fe2..75722c7 100644
--- a/src/main/java/com/supwisdom/dlpay/system/service/impl/ShopDataServiceImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/system/service/impl/ShopDataServiceImpl.java
@@ -1,6 +1,8 @@
 package com.supwisdom.dlpay.system.service.impl;
 
+import com.supwisdom.dlpay.api.dao.PaytypeDao;
 import com.supwisdom.dlpay.api.dao.ShopPaytypeDao;
+import com.supwisdom.dlpay.api.domain.TPaytype;
 import com.supwisdom.dlpay.api.domain.TShopPaytype;
 import com.supwisdom.dlpay.framework.dao.ShopDao;
 import com.supwisdom.dlpay.framework.dao.ShopaccDao;
@@ -8,16 +10,24 @@
 import com.supwisdom.dlpay.framework.domain.TShop;
 import com.supwisdom.dlpay.framework.domain.TShopacc;
 import com.supwisdom.dlpay.framework.service.SystemUtilService;
+import com.supwisdom.dlpay.framework.util.PageResult;
 import com.supwisdom.dlpay.framework.util.StringUtil;
 import com.supwisdom.dlpay.framework.util.Subject;
 import com.supwisdom.dlpay.framework.util.TradeDict;
+import com.supwisdom.dlpay.system.bean.ShopConfigBean;
 import com.supwisdom.dlpay.system.bean.ZTreeNode;
 import com.supwisdom.dlpay.system.service.ShopDataService;
 import com.supwisdom.dlpay.util.ConstantUtil;
 import com.supwisdom.dlpay.util.WebCheckException;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
+import org.springframework.data.jpa.domain.Specification;
 
+import javax.persistence.criteria.*;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -31,6 +41,8 @@
   private ShopPaytypeDao shopPaytypeDao;
   @Autowired
   private SystemUtilService systemUtilService;
+  @Autowired
+  private PaytypeDao paytypeDao;
 
   @Override
   public List<ZTreeNode> getAllShopNodes() {
@@ -131,5 +143,56 @@
     }
   }
 
+  @Override
+  public List<TPaytype> getConsumePaytypes() {
+    List<TPaytype> list = paytypeDao.getConsumePaytypes();
+    if (!StringUtil.isEmpty(list)) {
+      return list;
+    }
+    return new ArrayList<TPaytype>(0);
+  }
+
+  @Override
+  public PageResult<ShopConfigBean> getShopPaytypeInfos(String shopaccno, String paytype, Integer shopid, int pageNo, int pageSize) {
+    Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by("shopaccno", "paytype"));
+
+    Page<TShopPaytype> page = shopPaytypeDao.findAll(new Specification<TShopPaytype>() {
+      @Override
+      public Predicate toPredicate(Root<TShopPaytype> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+        List<Predicate> predicates = new ArrayList<>();
+        if (!StringUtil.isEmpty(shopaccno)) {
+          predicates.add(criteriaBuilder.equal(root.get("shopaccno").as(String.class), shopaccno.trim()));
+        }
+        if (!StringUtil.isEmpty(paytype)) {
+          predicates.add(criteriaBuilder.equal(root.get("paytype").as(String.class), paytype.trim()));
+        }
+        if (null != shopid) {
+          Join<TShopPaytype, TShopacc> joinShopacc = root.join("shopaccno", JoinType.LEFT);
+          predicates.add(criteriaBuilder.equal(joinShopacc.get("shopid").as(Integer.class), shopid));
+        }
+        return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+      }
+    }, pageable);
+
+    if (null == page || page.getTotalElements() == 0) {
+      return new PageResult<>(99, "无数据");
+    }
+    List<ShopConfigBean> list = new ArrayList<>(0);
+    for (TShopPaytype pt : page.getContent()) {
+      ShopConfigBean bean = new ShopConfigBean();
+      bean.setShopaccno(pt.getShopaccno());
+      TShopacc shopacc = shopaccDao.getByShopaccno(pt.getShopaccno());
+      bean.setShopname(shopacc == null ? "" : shopacc.getShopname());
+      bean.setPaytype(pt.getPaytype());
+      TPaytype tPaytype = paytypeDao.getByPaytype(pt.getPaytype());
+      bean.setPaydesc(tPaytype == null ? "" : tPaytype.getPaydesc());
+      bean.setConsumeEnable(pt.getConsumeEnable());
+      bean.setAnonymousEnable(pt.getAnonymousEnable());
+      bean.setReverseEnable(pt.getReverseEnable());
+      list.add(bean);
+    }
+    return new PageResult<>(page.getTotalElements(), list);
+  }
+
 
 }
diff --git a/src/main/resources/templates/system/shop/config.html b/src/main/resources/templates/system/shop/config.html
new file mode 100644
index 0000000..9765eb6
--- /dev/null
+++ b/src/main/resources/templates/system/shop/config.html
@@ -0,0 +1,175 @@
+<div class="layui-card">
+    <div class="layui-card-header">
+        <h2 class="header-title">商户支付能力管理</h2>
+        <span class="layui-breadcrumb pull-right">
+          <a href="#">商户中心</a>
+          <a><cite>商户支付能力管理</cite></a>
+        </span>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row">
+            <div class="layui-col-xs5 layui-col-md3">
+                <div class="layui-card">
+                    <div class="layui-card-header">
+                        商户树<span style="font-size: 12px;">(双击末级商户查询)</span>
+                    </div>
+                    <div class="layui-card-body layui-show"
+                         style="background-color: #D7F9F7;max-height: 560px;overflow:auto;">
+                        <ul id="shopacctree" class="ztree"></ul>
+                    </div>
+                </div>
+            </div>
+            <div class="layui-col-xs7 layui-col-md9">
+                <div class="layui-card" style="min-height: 600px;">
+                    <div class="layui-card-body">
+                        <div class="layui-form toolbar">
+                            搜索:
+                            <select id="search-paytype">
+                                <option value=""> 全部</option>
+                                <option th:each="pt:${paytypelist}" th:value="${pt.paytype}"
+                                        th:text="${pt.paydesc}"></option>
+                            </select>&emsp;
+                            <button id="btn-search" class="layui-btn icon-btn" data-type="search"><i class="layui-icon">&#xe615;</i>搜索
+                            </button>
+                            <button id="btn-add" class="layui-btn icon-btn" data-type="add"><i class="layui-icon">&#xe654;</i>新
+                                增
+                            </button>
+                            <button id="btn-reset" class="layui-btn layui-btn-primary" data-type="reset"><i
+                                    class="layui-icon"></i>清 空
+                            </button>
+                        </div>
+                        <table class="layui-table" id="shopPaytypeTable" lay-filter="shopPaytypeTable-filter"></table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 表格状态列 -->
+<script type="text/html" id="consumeenable-tpl-state">
+    <input type="checkbox" lay-filter="consumeenable-tpl-state" value="{{d.paytype}}" lay-skin="switch" lay-text="启用|关闭"
+           {{d.consumeEnable=='yes'?'checked':''}}/>
+</script>
+<script type="text/html" id="anonymousenable-tpl-state">
+    {{# if(d.consumeEnable =='yes' ){ }}
+    <input type="checkbox" lay-filter="anonymousenable-tpl-state" value="{{d.paytype}}" lay-skin="switch"
+           lay-text="启用|关闭"
+           {{(d.consumeEnable=='yes' && d.anonymousEnable=='yes')?'checked':''}}/>
+    {{# }else{ }}
+    <input type="checkbox" lay-filter="anonymousenable-tpl-state" value="{{d.paytype}}" lay-skin="switch"
+           lay-text="启用|关闭"
+           {{(d.consumeEnable=='yes' && d.anonymousEnable=='yes')?'checked':''}} disabled/>
+    {{# } }}
+</script>
+<script type="text/html" id="reverseenable-tpl-state">
+    <input type="checkbox" lay-filter="reverseenable-tpl-state" value="{{d.paytype}}" lay-skin="switch" lay-text="启用|关闭"
+           {{d.reverseEnable=='yes'?'checked':''}}/>
+</script>
+
+<script>
+    layui.use(['form', 'table', 'layer', 'admin', 'element'], function () {
+        var form = layui.form;
+        var table = layui.table;
+        var admin = layui.admin;
+        form.render('select');
+        var initTree = function (nodes) {
+            var menuSetting = {
+                view: {
+                    dblClickExpand: false,
+                    showLine: true,
+                    showIcon: true,
+                    selectedMulti: false
+                },
+                data: {
+                    simpleData: {
+                        enable: true
+                    }
+                },
+                callback: {
+                    onDblClick: ondblclick
+                }
+            };
+            $.fn.zTree.init($("#shopacctree"), menuSetting, nodes);
+        }
+        admin.dgo('/shop/shopacctree', {}, function (data) {
+            if (data.code == 200) {
+                initTree(data.data);
+            } else if (data.code == 401) {
+                layer.msg(data.msg, {icon: 2, time: 1500}, function () {
+                    location.replace('/login');
+                }, 1000);
+                return;
+            } else {
+                layer.msg(data.msg, {icon: 2, time: 2000});
+            }
+        }, function (ret) {
+            console.log(ret);
+            layer.msg('查询商户树失败了,请稍后再试', {icon: 2});
+        });
+
+        $('#btn-reset').click(function () {
+            $("#search-paytype").val("");
+            form.render('select');
+        });
+        $('#btn-search').click(function(){
+            var ptype = $("#search-paytype").val();
+            table.reload('shopPaytypeTable', {where: {paytype: ptype, shopid:""}, page: {curr: 1}});
+        });
+
+        function ondblclick(event, treeId, treeNode) {
+            if (treeNode.shoptype != 1) {
+                layer.msg("请选择末级商户", {icon: 2, time: 1000});
+                return;
+            }
+            var ptype = $("#search-paytype").val();
+            table.reload('shopPaytypeTable', {where: {paytype: ptype, shopid: treeNode.id}, page: {curr: 1}});
+        }
+
+        // 渲染表格
+        table.render({
+            elem: '#shopPaytypeTable',
+            url: '/shop/shoppaytypelist',
+            page: true,
+            width: 1010,
+            cols: [
+                [
+                    {field: 'shopaccno', title: '商户账号', width: 150, align: 'center', fixed: 'left', sort: true},
+                    {field: 'shopname', title: '商户名称',  align: 'center', fixed: 'left', sort: true},
+                    {field: 'paydesc', title: '支付方式', align: 'center', sort: true},
+                    {
+                        field: 'consumeEnable',
+                        title: '能否消费',
+                        align: 'center',
+                        width: 110,
+                        templet: '#consumeenable-tpl-state',
+                        sort: true
+                    },
+                    {
+                        field: 'anonymousEnable',
+                        title: '匿名消费',
+                        align: 'center',
+                        width: 110,
+                        templet: '#anonymousenable-tpl-state',
+                        sort: true
+                    },
+                    {
+                        field: 'reverseEnable',
+                        title: '能否冲正',
+                        align: 'center',
+                        width: 110,
+                        templet: '#reverseenable-tpl-state',
+                        sort: true
+                    },
+                    {align: 'center', title: '操作', width: 90, fixed: 'right', templet: function (item) {
+                            if (item.paytype != 'balance') {
+                                return '<a class="layui-btn layui-btn-xs" lay-event="config">配置</a>';
+                            }
+                            return '<span style="font-size: 12px;color: #D3D4D3;">无配置</span>';
+                        }
+                    }
+                ]
+            ]
+        });
+    });
+</script>
\ No newline at end of file