Merge branch 'hotfix/1.0.9'
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/controller/SettleReportController.java b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/SettleReportController.java
index c7cb46b..749fae7 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/controller/SettleReportController.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/SettleReportController.java
@@ -156,4 +156,42 @@
   }
 
 
+  /**
+   * ====================================================
+   * 商户当天统计表
+   * ====================================================
+   */
+  @GetMapping("/report/shoptodaybusiness")
+  public String shopTodayBusinessReport(ModelMap map) {
+    String settledate = settleReportService.getSystemSettledate();
+    map.addAttribute("mindate", DateUtil.parseToDateFormat(settledate));
+    return "system/report/shoptodaybusiness";
+  }
+
+  @GetMapping("/report/selectshoptodaytree")
+  @PreAuthorize("hasPermission('/report/shoptodaybusiness','')")
+  @ResponseBody
+  public List<TreeSelectNode> searchShopTodayTree() {
+    return settleReportService.getSystemNormalShopTree();
+  }
+
+  @GetMapping("/report/shoptodaybusinesslist")
+  @PreAuthorize("hasPermission('/report/shoptodaybusiness','')")
+  @ResponseBody
+  public PageResult<ShopBusinessShowBean> getShopTodayBusinessData(@RequestParam(value = "startdate", required = false) String startdate,
+                                                                   @RequestParam(value = "enddate", required = false) String enddate,
+                                                                   @RequestParam(value = "shopid", required = false) String shopid,
+                                                                   @RequestParam(value = "nodealshow", required = false, defaultValue = "false") Boolean noDealShow) {
+    try {
+      BaseResp resp = new BaseResp();
+      if (!checkReportDate(startdate, enddate, resp)) {
+        return new PageResult<>(99, resp.getRetmsg());
+      }
+      return settleReportService.getShopTodayBusinessShowInfos(DateUtil.unParseToDateFormat(startdate), DateUtil.unParseToDateFormat(enddate), shopid, noDealShow);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return new PageResult<>(99, "系统查询异常");
+    }
+  }
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/SettleReportService.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/SettleReportService.java
index 6b60bca..2b704eb 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/SettleReportService.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/SettleReportService.java
@@ -28,4 +28,8 @@
 
   @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
   PageResult<ShopBusinessShowBean> getShopBusinessShowInfos(String startdate, String enddate, String shopid, boolean nodealshow);
+
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+  PageResult<ShopBusinessShowBean> getShopTodayBusinessShowInfos(String startdate, String enddate, String shopid, boolean nodealshow);
+
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/SettleReportServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/SettleReportServiceImpl.java
index 7aaac69..4d3a830 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/SettleReportServiceImpl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/SettleReportServiceImpl.java
@@ -5,20 +5,26 @@
 import com.supwisdom.dlpay.framework.domain.TSettlectl;
 import com.supwisdom.dlpay.framework.domain.TShop;
 import com.supwisdom.dlpay.framework.domain.TSubject;
-import com.supwisdom.dlpay.framework.util.DateUtil;
-import com.supwisdom.dlpay.framework.util.MoneyUtil;
-import com.supwisdom.dlpay.framework.util.PageResult;
-import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.framework.util.*;
 import com.supwisdom.dlpay.system.bean.*;
 import com.supwisdom.dlpay.system.service.SettleReportService;
 import com.supwisdom.dlpay.util.EnumCheck;
+import org.hibernate.query.internal.NativeQueryImpl;
+import org.hibernate.transform.Transformers;
+import org.hibernate.type.DoubleType;
+import org.hibernate.type.LongType;
+import org.hibernate.type.StringType;
 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.stereotype.Service;
 
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 @Service
@@ -34,6 +40,9 @@
   @Autowired
   private ShopDao shopDao;
 
+  @PersistenceContext
+  private EntityManager entityManager;
+
   private EnumCheck<ShopTypes, String> shoptypeCheck = new EnumCheck<>();
 
   @Override
@@ -190,10 +199,14 @@
 
   @Override
   public PageResult<ShopBusinessShowBean> getShopBusinessShowInfos(String startdate, String enddate, String shopid, boolean nodealshow) {
-    List<ShopBusinessInfo> businessInfos = voucherDao.getShopBusinessInfos(Integer.valueOf(startdate), Integer.valueOf(enddate));
+    List<ShopBusinessInfo> businessInfos = voucherDao.getShopBusinessInfos(Integer.valueOf(startdate), Integer.valueOf(enddate)); //根据凭证统计历史的数据
     if (StringUtil.isEmpty(businessInfos) && !nodealshow) {
       return new PageResult<>(99, "无数据"); //无交易记录
     }
+    return new PageResult<>(getShopBusinessShowBean(businessInfos, shopid, nodealshow));
+  }
+
+  private List<ShopBusinessShowBean> getShopBusinessShowBean(List<ShopBusinessInfo> businessInfos, String shopid, boolean nodealshow) {
     List<TShop> shopAllList = shopDao.getNormalShops();
     List<ShopBusinessShowBean> result = new ArrayList<>(0);
     List<TShop> shopList = getShopBusinessSelectShops(shopAllList, shopid);
@@ -252,6 +265,42 @@
         result.add(bean);
       }
     }
-    return new PageResult<>(result);
+    return result;
+  }
+
+
+  @Override
+  public PageResult<ShopBusinessShowBean> getShopTodayBusinessShowInfos(String startdate, String enddate, String shopid, boolean nodealshow){
+    List<ShopBusinessInfo> businessInfos = getTodayShopbusiness(startdate, enddate); //根据流水统计当天的数据
+    if (StringUtil.isEmpty(businessInfos) && !nodealshow) {
+      return new PageResult<>(99, "无数据"); //无交易记录
+    }
+    return new PageResult<>(getShopBusinessShowBean(businessInfos, shopid, nodealshow));
+  }
+
+  private List<ShopBusinessInfo> getTodayShopbusiness(String startdate, String enddate) {
+    StringBuffer sql = new StringBuffer("select tt.shopaccno,tt.summary,count(distinct tt.refno) as transcnt,sum(tt.dramt) as dramt,sum(tt.cramt) as cramt \n" +
+        "from ( \n" +
+        "  select t.draccno as shopaccno,t.summary,t.refno,t.amount as dramt,0.0 as cramt \n" +
+        "  from tb_userdtl_debitcredit t left join tb_transactionmain a on t.refno=a.refno \n" +
+        "  where a. status='success' and t.drsubjno=:subjno and a.accdate>=:startdate and a.accdate<=:enddate \n" +
+        "  union all \n" +
+        "  select t.craccno as shopaccno,t.summary,t.refno,0.0 as dramt,t.amount as cramt \n" +
+        "  from tb_userdtl_debitcredit t left join tb_transactionmain a on t.refno=a.refno \n" +
+        "  where a. status='success' and t.crsubjno=:subjno and a.accdate>=:startdate and a.accdate<=:enddate \n" +
+        ") tt group by tt.shopaccno,tt.summary ");
+    Query query = entityManager.createNativeQuery(sql.toString());
+    query.setParameter("subjno", Subject.SUBJNO_MACHANT_INCOME); //商户收入科目
+    query.setParameter("startdate", DateUtil.unParseToDateFormat(startdate));
+    query.setParameter("enddate", DateUtil.unParseToDateFormat(enddate));
+    query.unwrap(NativeQueryImpl.class)
+        .addScalar("shopaccno", StringType.INSTANCE)
+        .addScalar("summary", StringType.INSTANCE)
+        .addScalar("transcnt", LongType.INSTANCE)
+        .addScalar("dramt", DoubleType.INSTANCE)
+        .addScalar("cramt", DoubleType.INSTANCE)
+        .setResultTransformer(Transformers.aliasToBean(ShopBusinessInfo.class));
+    List<ShopBusinessInfo> list = query.getResultList();
+    return list;
   }
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
index 6e2de3c..da66271 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/MobileApi.kt
@@ -93,8 +93,8 @@
                 return JsonResult.error("类型错误")
             }
         }
-        // 如果未设置密码
-        val temp = redisTemplate.opsForValue().get(phone)
+        //如果已经发送了
+        val temp = redisTemplate.opsForValue().get(phone.plus("_after"))
         if (temp.isNullOrEmpty()) {
             val code = RandomUtils.randomNumber(6)
             logger.error { code }
@@ -105,6 +105,7 @@
                 return JsonResult.error(rs.retmsg)
             }
             redisTemplate.opsForValue().set(phone, code, Duration.ofMinutes(5))
+            redisTemplate.opsForValue().set(phone.plus("_after"), code, Duration.ofMinutes(2))
         }
         return JsonResult.ok("验证码已发送")
     }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
index 292b73c..f9c2b1e 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/mobile/service/impl/MobileApiServiceImpl.kt
@@ -30,7 +30,9 @@
 
     @Autowired
     lateinit var systemUtilService: SystemUtilService
-
+    companion object {
+        var isMsgLogined: Boolean = false
+    }
     val logger = KotlinLogging.logger { }
 
     override fun saveUser(user: TBMobileUser): TBMobileUser {
@@ -123,12 +125,15 @@
         }
         var client = Client.getInstance()
         // 正式环境IP,登录验证URL,用户名,密码,集团客户名称
-        var ret = client.login(url, account, pwd, ecname)
-        if (!ret) {
-            logger.error { "无法登陆短信平台,身份验证失" }
-            resp.retcode = "1"
-            resp.retmsg = "无法登陆短信平台"
-            return resp
+        if(!isMsgLogined){
+            var ret = client.login(url, account, pwd, ecname)
+            if (!ret) {
+                logger.error { "无法登陆短信平台,身份验证失" }
+                resp.retcode = "1"
+                resp.retmsg = "无法登陆短信平台"
+                return resp
+            }
+            isMsgLogined = true
         }
         var sendResult = client.sendTSMS(arrayOf(phone),
                 tempid, arrayOf(code), addserial, priority.toInt(), sign, UUID.randomUUID().toString())
@@ -141,6 +146,23 @@
             resp.retcode = "1"
             resp.retmsg = "手机号错误"
             resp
+        } else if (sendResult == 105) {
+            //105 需要重新登录
+            var ret = client.login(url, account, pwd, ecname)
+            if (!ret) {
+                logger.error { "无法登陆短信平台,身份验证失" }
+                resp.retcode = "1"
+                resp.retmsg = "无法登陆短信平台"
+                return resp
+            }
+            resp.retcode = "1"
+            resp.retmsg = "短信发送失败,请稍后再试"
+            resp
+        } else if (sendResult == 106 || sendResult == 108 || sendResult == 111) {
+            logger.error { "106:网关签名为空, 用户需要填写网关签名编号;108:JMS异常,用户侧网络问题。需要检查防火墙配置和网络连通性,看是否能够与云MAS平台正常连接;111:扩展码错误,扩展码只能是15位以内数字或空字符串" }
+            resp.retcode = "1"
+            resp.retmsg = "短信发送失败,请稍后再试"
+            resp
         } else {
             resp.retcode = "1"
             resp.retmsg = "短信发送失败,请稍后再试"
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index 446650b..cefb007 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -75,6 +75,8 @@
 VALUES (36, NULL, 1, NULL, '', '/shop/shopcheck', '商户审批', 2, 7, '{tenantid}');
 INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", tenantid)
 VALUES (37, NULL, 1, NULL, '', '/user/card', '市民卡查询', 1, 19, '{tenantid}');
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", tenantid)
+VALUES (38, NULL, 1, NULL, '', '/report/shoptodaybusiness', '商户当天统计表', 4, 20, '{tenantid}');
 
 
 INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
@@ -141,6 +143,8 @@
 VALUES ('ff8080816db87e27016db88be41a0014', 36, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
 INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
 VALUES ('ff8080816db87e27016db88be41f0015', 37, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
+VALUES ('4028ee9f6e5d95d8016e5d99e8d50012', 38, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
 
 
 INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
@@ -297,6 +301,8 @@
 VALUES (89, '', 36, '审核', '/shop/docheckshop', '{tenantid}');
 INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
 VALUES (90, '', 37, '查询', '/user/card', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (91, '', 38, '查询', '/report/shoptodaybusiness', '{tenantid}');
 
 
 INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", tenantid)
@@ -453,6 +459,8 @@
 VALUES ('ff8080816db87e27016db94468da008a', 89, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
 INSERT INTO  "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
 VALUES ('ff8080816db87e27016db9446fda008b', 90, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO  "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('4028ee9f6e5d95d8016e5d99e8dd0013', 91, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
 
 
 INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
diff --git a/payapi/src/main/resources/templates/system/report/shoptodaybusiness.html b/payapi/src/main/resources/templates/system/report/shoptodaybusiness.html
new file mode 100644
index 0000000..c01ddbf
--- /dev/null
+++ b/payapi/src/main/resources/templates/system/report/shoptodaybusiness.html
@@ -0,0 +1,190 @@
+<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-form" lay-filter="today-shopbusiness-search-form">
+            <input type="hidden" id="today-shopbusiness-hidden-mindate" th:value="${mindate}"/>
+            <input type="hidden" id="today-shopbusiness-hidden-parentId" value="0"/>
+            <div class="layui-form-item" style="margin-bottom: 0;">
+                <div class="layui-inline">
+                    <label class="layui-form-label">记账日期</label>
+                    <div class="layui-input-inline">
+                        <input type="text" name="startdate" id="today-shopbusiness-search-startdate" placeholder="起始日期"
+                               th:value="${mindate}"
+                               autocomplete="off" class="layui-input"/>
+                    </div>
+                    <div class="layui-form-mid">-</div>
+                    <div class="layui-input-inline">
+                        <input type="text" name="enddate" id="today-shopbusiness-search-enddate" placeholder="截止日期"
+                               th:value="${mindate}"
+                               autocomplete="off" class="layui-input"/>
+                    </div>
+                </div>
+
+                <div class="layui-inline">
+                    <label class="layui-form-label">选择商户</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="shopid" id="today-shopbusiness-search-shopid" placeholder="选择商户"
+                               lay-filter="today-shopbusiness-search-shopid-filter"
+                               autocomplete="off" class="layui-input"/>
+                    </div>
+                </div>
+
+                <div class="layui-inline">
+                    <div class="layui-input-block" style="margin-left: 0;">
+                        <input type="checkbox" name="nodealshow" id="today-shopbusiness-search-nodealshow" lay-skin="primary"
+                               title="显示未交易商户"/>
+                    </div>
+                </div>
+
+                <div class="layui-inline">
+                    <button id="today-shopbusiness-search-btn" class="layui-btn icon-btn" data-type="search"><i
+                            class="layui-icon">&#xe615;</i>搜索
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="layui-card-body">
+        <table class="layui-table" id="todayShopbusinessTable" lay-filter="todayShopbusinessTable-filter"></table>
+    </div>
+</div>
+
+<script type="text/html" id="today-shopbusiness-toolbar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-sm" id="btn-fold-today-shopbusiness" lay-event="todayShopbusinessShowFold">全部折叠</button>
+        <button class="layui-btn layui-btn-sm" id="btn-expand-today-shopbusiness" lay-event="todayShopbusinessExpandAll">全部展开
+        </button>
+    </div>
+</script>
+
+
+<script>
+    layui.use(['form', 'table', 'layer', 'admin', 'element', 'laydate', 'treeSelect', 'treetable'], function () {
+        var form = layui.form;
+        var table = layui.table;
+        var admin = layui.admin;
+        var laydate = layui.laydate;
+        var treetable = layui.treetable;
+        var treeSelect = layui.treeSelect;
+
+        form.render("checkbox");
+        laydate.render({
+            elem: '#today-shopbusiness-search-startdate',
+            min: $("#today-shopbusiness-hidden-mindate").val(),
+            trigger: 'click'
+        });
+        laydate.render({
+            elem: '#today-shopbusiness-search-enddate',
+            min: $("#today-shopbusiness-hidden-mindate").val(),
+            trigger: 'click'
+        });
+
+        treeSelect.render({
+            elem: '#today-shopbusiness-search-shopid',
+            data: '[[@{/report/selectshoptodaytree}]]',
+            type: 'get',
+            placeholder: '选择商户',
+            search: false,
+            style: {
+                folder: {
+                    enable: false
+                },
+                line: {
+                    enable: true
+                }
+            },
+            // 点击回调
+            click: function (d) {
+                var treeNode = d.current;
+                console.log(treeNode);
+                $("#today-shopbusiness-hidden-parentId").val(treeNode.pId);
+                return true;
+            },
+            success: function (d) {
+                console.log(d); // 加载完成后的回调函数
+            }
+        });
+
+        var renderTable = function (obj) {
+            layer.load(2);
+            var parentId = $("#today-shopbusiness-hidden-parentId").val();
+            console.log(parentId);
+            treetable.render({
+                id: 'todayShopBusinessReport',
+                title: '商户营业情况表',
+                treeColIndex: 0,
+                treeSpid: parentId,
+                treeIdName: 'shopid',
+                treePidName: 'fshopid',
+                treeDefaultClose: false,
+                treeLinkage: false,
+                elem: '#todayShopbusinessTable',
+                url: '[[@{/report/shoptodaybusinesslist}]]',
+                page: false,
+                where: obj,
+                showicon: false,
+                toolbar: '#today-shopbusiness-toolbar',
+                cols: [
+                    [
+                        {field: 'shopname', title: '商户名称', align: 'left'},
+                        {field: 'summary', title: '交易摘要', align: 'center'},
+                        {field: 'transcnt', title: '交易次数', align: 'center'},
+                        {
+                            field: 'transamt', title: '交易金额', align: 'center', templet: function (e) {
+                                return parseFloat(e.transamt).toFixed(2);
+                            }
+                        }
+                    ]
+                ],
+                done: function (res, curr, count) {
+                    console.log(res);
+                    layer.closeAll('loading');
+                }
+            });
+        }
+        renderTable({
+            startdate: $("#today-shopbusiness-search-startdate").val(),
+            enddate: $("#today-shopbusiness-search-enddate").val(),
+            shopid: "",
+            nodealshow: false
+        });
+
+        $('#today-shopbusiness-search-btn').click(function () {
+            var startdate = $("#today-shopbusiness-search-startdate").val();
+            var enddate = $("#today-shopbusiness-search-enddate").val();
+            var shopid = $("#today-shopbusiness-search-shopid").val();
+            var nodealshow = $("#today-shopbusiness-search-nodealshow").is(':checked');
+            if (null == startdate || "" == $.trim(startdate)) {
+                layer.msg('请选择起始日期', {icon: 2, time: 1500});
+                return;
+            }
+            if (null == enddate || "" == $.trim(enddate)) {
+                layer.msg('请选择截止日期', {icon: 2, time: 1500});
+                return;
+            }
+            renderTable({
+                startdate: startdate,
+                enddate: enddate,
+                shopid: shopid,
+                nodealshow: nodealshow
+            });
+        });
+
+        table.on('toolbar(todayShopbusinessTable-filter)', function (obj) {
+            switch (obj.event) {
+                case 'todayShopbusinessShowFold':
+                    treetable.foldAll('#todayShopbusinessTable');
+                    break;
+                case 'todayShopbusinessExpandAll':
+                    treetable.expandAll('#todayShopbusinessTable');
+                    break;
+            }
+        });
+    });
+</script>
\ No newline at end of file