From efb2457e0f7b6e5a76999c239d8b079b21c88eb0 Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期三, 19 二月 2025 14:03:43 +0800
Subject: [PATCH] Merge branch 'master' of https://gitee.com/xiaochen991015/xizang

---
 ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java                        |   17 +
 ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java                    |   36 +++
 ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java                             |   34 +++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java |    6 
 ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml                            |   17 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java                    |    5 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java              |   28 ++
 ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java                        |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java                |    6 
 ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml                  |   42 +++
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java                |   24 ++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java                    |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java          |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java                        |   38 +++
 ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java                     |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java    |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java                  |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java          |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java           |   73 ++++++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java           |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java  |   12 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java            |    5 
 ruoyi-common/pom.xml                                                                     |   12 +
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java          |   27 ++
 ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java                            |    2 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java             |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java          |  100 ++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java                          |    4 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java                           |   53 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java       |   16 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java       |   20 +
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java                      |    2 
 ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml                        |   36 +++
 33 files changed, 622 insertions(+), 38 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java
index 46bf97f..9c5cdd4 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java
@@ -4,11 +4,9 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.system.model.TBankFlow;
-import com.ruoyi.system.model.TFlowManagement;
 import com.ruoyi.system.query.TBankFlowQuery;
-import com.ruoyi.system.query.TFlowManagementQuery;
 import com.ruoyi.system.service.TBankFlowService;
-import com.ruoyi.system.service.TFlowManagementService;
+import com.ruoyi.system.vo.TBankFlowStatisticsVo;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -39,5 +37,11 @@
     public R<PageInfo<TBankFlow>> list(@RequestBody TBankFlowQuery query) {
         return R.ok(flowService.pageList(query));
     }
+
+    @ApiOperation(value = "根据支付方式统计流水金额")
+    @PostMapping("/getPaymentStats")
+    public R<TBankFlowStatisticsVo> getPaymentStats(@RequestBody TBankFlowQuery query){
+        return R.ok(flowService.getPaymentStats(query));
+    }
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
index 5816bc3..7ecc704 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -4,9 +4,7 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.system.dto.OfflinePayCheckDto;
-import com.ruoyi.system.dto.TBillDto;
-import com.ruoyi.system.dto.TbillSaveDto;
+import com.ruoyi.system.dto.*;
 import com.ruoyi.system.model.TBill;
 import com.ruoyi.system.query.TBillQuery;
 import com.ruoyi.system.service.TBillService;
@@ -62,6 +60,30 @@
         return R.ok();
     }
 
+    @PreAuthorize("@ss.hasPermi('system:bill:sendSmsByBillIds')")
+    @ApiOperation("账单批量发送短信通知")
+    @PostMapping("sendSmsByBillIds")
+    public R sendSmsByBillIds(@Validated @RequestBody SmsByBillDto dto){
+        Integer failNum = tBillService.sendSmsByBillIds(dto);
+        return R.ok(failNum);
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('system:bill:sendMailBatchByBillIds')")
+    @ApiOperation("账单批量发送短信通知")
+    @PostMapping("sendMailBatchByBillIds")
+    public R sendMailBatchByBillIds(@Validated @RequestBody SmsByBillDto dto){
+        Integer failNum = tBillService.sendMailBatchByBillIds(dto);
+        return R.ok(failNum);
+    }
+
+    @PreAuthorize("@ss.hasPermi('system:bill:cashPay')")
+    @ApiOperation("收款")
+    @PostMapping("cashPay")
+    public R cashPay(@RequestBody OfflinePayDto offlinePayDto){
+        return null;
+    }
+
 
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
index 3053ff9..391f5dc 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -75,9 +75,103 @@
     @ApiOperation(value = "测试生成账单")
     @PostMapping(value = "/testBill")
     public R testBill(String id) {
-        SignContractDTO signContractDTO = new SignContractDTO();
-        signContractDTO.setId(id);
-        contractService.signContract(signContractDTO);
+        TContract contract = contractService.getById(id);
+        // 查询所有已签订的合同并且未生成第一笔账单的
+
+        List<TBill> bills = new ArrayList<>();
+        List<TContractRentType> contractRentTypes = contractRentTypeService.list();
+            contract.setFirstPayTime(contract.getStartTime().plusDays(10));
+            // 第一次应缴费日期
+            LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
+            TBill rentBill = new TBill();
+            rentBill.setContractId(contract.getId());
+            rentBill.setContractNumber(contract.getContractNumber());
+            rentBill.setPayableFeesTime(firstPayTime.toLocalDate());
+            rentBill.setPayFeesStatus("1");
+            rentBill.setBillType("1");
+            rentBill.setStartTime(contract.getStartPayTime());
+            TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
+
+            if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){
+                // 计算租金变动的天数
+                long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L;
+                contract.setChangeTime(LocalDateTime.now());
+                // 递增递减的租金
+                BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                // 不递增递减的租金
+                BigDecimal originalMoney = new BigDecimal("0");
+                // 原租金
+                switch (tContractRentType.getIncreasingDecreasingType()){
+                    case 1:
+                        switch (tContractRentType.getIncreasingDecreasing()){
+                            case 1:
+                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                            case 2:
+                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                        }
+                        break;
+                    case 2:
+                        switch (tContractRentType.getIncreasingDecreasing()){
+                            case 1:
+                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                            case 2:
+                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                contract.setChangeRent(contractRentTypeMoney);
+
+                                break;
+                        }
+                        break;
+                }
+                // 不需要涨租金的时间段
+                if (contract.getFirstPayTime().isBefore(tContractRentType.getChangeTime())){
+                    long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime());
+                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                            .multiply(new BigDecimal(originalDays));
+                    rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+                }else{
+                    rentBill.setPayableFeesMoney(contractRentTypeMoney);
+                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+                }
+
+                if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                    rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+                }else{
+                    rentBill.setEndTime(contract.getEndTime());
+                }
+            }else{
+                if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                    rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+                }else{
+                    rentBill.setEndTime(contract.getEndTime());
+                }
+                // 不走递增递减
+                long allDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), rentBill.getEndTime());
+                rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
+                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+
+            }
+            // 租金账单
+            bills.add(rentBill);
+            // 押金账单
+            TBill depositBill = new TBill();
+            depositBill.setContractId(contract.getId());
+            depositBill.setContractNumber(contract.getContractNumber());
+            depositBill.setPayableFeesMoney(contract.getDeposit());
+            depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney());
+
+            depositBill.setPayableFeesTime(firstPayTime.toLocalDate());
+            depositBill.setPayFeesStatus("1");
+            depositBill.setBillType("2");
+        contractService.updateById(contract);
+        billService.save(rentBill);
+        billService.save(depositBill);
         return R.ok();
     }
     @ApiOperation(value = "获取合同分页列表")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java
index 652d417..d32a1a8 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.system.model.TFlowManagement;
 import com.ruoyi.system.query.TFlowManagementQuery;
 import com.ruoyi.system.service.TFlowManagementService;
+import com.ruoyi.system.vo.TFlowManagementStatisticsVo;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -38,6 +39,12 @@
         return R.ok(flowService.pageList(query));
     }
 
+    @ApiOperation(value = "根据支付方式统计流水金额")
+    @PostMapping("/getPaymentStats")
+    public R<TFlowManagementStatisticsVo> getPaymentStats(@RequestBody TFlowManagementQuery query){
+        return R.ok(flowService.getPaymentStats(query));
+    }
+
 
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java
index 10cd917..5a781f8 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java
@@ -47,8 +47,8 @@
     }
 
     @ApiOperation(value = "关联账单信息")
-    @GetMapping(value = "/getBillByInvoiceId")
-    public R<PageInfo<TBill>> getBillByInvoiceId(String invoiceId){
+    @GetMapping(value = "/getBillByInvoiceId/{invoiceId}")
+    public R<PageInfo<TBill>> getBillByInvoiceId(@PathVariable String invoiceId){
         return R.ok(tBillService.getBillByInvoiceId(invoiceId));
     }
 
@@ -58,10 +58,10 @@
         TInvoice tInvoice = new TInvoice();
         tInvoice.setId(query.getId());
         tInvoice.setInvoiceVoucher(query.getInvoiceVoucher());
+        tInvoice.setInvoiceVoucherName(query.getInvoiceVoucherName());
         tInvoice.setInvoiceTime(query.getInvoiceTime());
         tInvoice.setStatus(2);
         return R.ok(invoiceService.updateById(tInvoice));
     }
-
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
index a878cdb..6db2c4f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
@@ -45,7 +45,7 @@
             List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, 1).list();
             for (TBill tBill : list) {
                 TContract contract = contractService.getById(tBill.getContractId());
-                LocalDateTime payableFeesTime = tBill.getPayableFeesTime();
+                LocalDate payableFeesTime = tBill.getPayableFeesTime();
                 LocalDateTime now = LocalDateTime.now();
                 // 计算两个时间相差多少个小时
                 long hours = ChronoUnit.HOURS.between(payableFeesTime, now);
@@ -75,7 +75,7 @@
         try {
             List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, "2").list();
             for (TBill tBill : list) {
-                if (tBill.getPayableFeesTime().toLocalDate().equals(LocalDate.now())){
+                if (tBill.getPayableFeesTime().equals(LocalDate.now())){
                     tBill.setPayFeesStatus("1");
                 }
             }
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
index 1cbc2f2..92a149a 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
@@ -181,6 +181,9 @@
                 List<TBill> billList = bills.stream().filter(e -> e.getContractId().equals(contract.getId())).collect(Collectors.toList());
                 List<PayListVO> payList = new ArrayList<>();
                 for (TBill tBill : billList) {
+                    if (tBill.getPayFeesTime()==null){
+                        continue;
+                    }
                     PayListVO payListVO = new PayListVO();
                     payListVO.setPayFeesTime(DateUtils.localDateTimeToStringYear(tBill.getPayFeesTime()));
                     payListVO.setPayFeesMoney("-" + tBill.getPayFeesMoney() + "元");
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 3be18aa..48aaf48 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -181,6 +181,18 @@
             <artifactId>jave-all-deps</artifactId>
             <version>2.5.1</version>
         </dependency>
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+            <version>4.0.11</version>
+        </dependency>
+
+        <!-- 工作流-->
+        <dependency>
+            <groupId>com.aizuda</groupId>
+            <artifactId>flowlong-spring-boot-starter</artifactId>
+            <version>1.0.4</version>
+        </dependency>
 
     </dependencies>
 
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java
new file mode 100644
index 0000000..f689f45
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.config;
+
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import com.tencentcloudapi.sms.v20190711.SmsClient;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties(SmsProperties.class)
+@ConditionalOnProperty(value = SmsProperties.ENABLE_KEY,matchIfMissing = true)
+public class SmsConfig {
+
+    @Bean
+    public SmsClient smsClient(SmsProperties properties) {
+        // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId,SecretKey。
+        // 为了保护密钥安全,建议将密钥设置在环境变量中或者配置文件中,请参考凭证管理 https://github.com/TencentCloud/tencentcloud-sdk-java?tab=readme-ov-file#%E5%87%AD%E8%AF%81%E7%AE%A1%E7%90%86。
+        // 硬编码密钥到代码中有可能随代码泄露而暴露,有安全隐患,并不推荐。
+        // SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi
+        // Credential cred = new Credential("SecretId", "SecretKey");
+
+        Credential cred = new Credential(properties.getSecretid(), properties.getSecretkey());
+        // 实例化一个http选项,可选的,没有特殊需求可以跳过
+        HttpProfile httpProfile = new HttpProfile();
+        // 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com
+        httpProfile.setEndpoint("sms.tencentcloudapi.com");
+        // 实例化一个客户端配置对象
+        ClientProfile clientProfile = new ClientProfile();
+        clientProfile.setHttpProfile(httpProfile);
+        // 实例化要请求产品(sms)的client对象,第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
+        return new SmsClient(cred, "ap-guangzhou", clientProfile);
+    }
+
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java
new file mode 100644
index 0000000..af6476c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java
@@ -0,0 +1,36 @@
+package com.ruoyi.common.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "sms")
+public class SmsProperties {
+
+    public static final String ENABLE_KEY = "sms.enable";
+
+    private Boolean enable;
+
+    private String appId;
+
+    private String secretid;
+
+    private String secretkey;
+    /**
+     * 短信签名
+     */
+    private String sign;
+
+    /**
+     * 账单提醒 ,同一个用户离上次发送短信的最小间隔
+     * 单位分钟
+     */
+    private Integer billSmsDelayPeriod = 60;
+    /**
+     * 账单提醒 ,同一个用户离上次发送邮件的最小间隔
+     * 单位分钟
+     */
+    private Integer billMailDelayPeriod = 60;
+
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java
new file mode 100644
index 0000000..7129612
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java
@@ -0,0 +1,53 @@
+package com.ruoyi.common.utils;
+
+import com.ruoyi.common.config.SmsProperties;
+import com.ruoyi.common.exception.ServiceException;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import com.tencentcloudapi.sms.v20190711.SmsClient;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+
+@Component
+@Slf4j
+public class SmsUtil {
+
+    @Resource
+    SmsProperties smsProperties;
+    @Resource
+    SmsClient smsClient;
+
+
+    public SmsProperties getPro(){
+        return smsProperties;
+    }
+
+    public boolean sendSms(String phone,String templateId,String[] param){
+        SendSmsRequest req = new SendSmsRequest();
+        req.setSmsSdkAppid(smsProperties.getAppId());
+        req.setPhoneNumberSet(new String[]{phone});
+        req.setTemplateID(templateId);
+        req.setSign(smsProperties.getSign());
+        req.setTemplateParamSet(param);
+        req.setSenderId("");
+        req.setSessionContext("");
+        req.setExtendCode("");
+        try {
+            smsClient.SendSms(req);
+            return true;
+        } catch (TencentCloudSDKException e) {
+            log.error("发送短信失败,{},{}",phone,param,e);
+            throw new ServiceException("发送短信失败");
+        } catch (Exception e){
+            log.error("发送短信失败1,{},{}",phone,param,e);
+            throw new ServiceException("发送短信失败1");
+        }
+    }
+
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java
new file mode 100644
index 0000000..a986a89
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class SmsByBillDto implements Serializable {
+
+    @NotEmpty(message = "账单ID不能为空")
+    private List<String> billIds;
+
+    private String sendUserId;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java
index 6a76c57..45c2e41 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java
@@ -12,6 +12,8 @@
 
     private String phone;
 
+    private String email;
+
     private String account;
 
     private String houseName;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java
index f40a77b..c7869f5 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java
@@ -11,7 +11,10 @@
 @Data
 public class TbillSaveDto extends TBill implements Serializable {
 
-    @ApiModelProperty(value = "水单费列表")
+    @ApiModelProperty(value = "水电费列表")
     private List<TBillDetail> details;
 
+
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java
index 0bf605c..20398af 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java
@@ -2,6 +2,9 @@
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.system.model.TBankFlow;
+import com.ruoyi.system.query.TBankFlowQuery;
+import com.ruoyi.system.vo.TBankFlowStatisticsVo;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -12,5 +15,6 @@
  * @since 2025-02-07
  */
 public interface TBankFlowMapper extends BaseMapper<TBankFlow> {
+    TBankFlowStatisticsVo getPaymentStats(@Param("req") TBankFlowQuery query);
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
index 49292e8..6a447fb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
@@ -33,4 +33,6 @@
      * @return
      */
     List<TBillDto> invoiceList(@Param("query")TBillQuery query, @Param("pageInfo")PageInfo<TBillDto> pageInfo);
+
+    TBillDto selectTenentByBillId(@Param("billId") String billId);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java
index f963542..deca07e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java
@@ -2,6 +2,9 @@
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.system.model.TFlowManagement;
+import com.ruoyi.system.query.TFlowManagementQuery;
+import com.ruoyi.system.vo.TFlowManagementStatisticsVo;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -12,5 +15,5 @@
  * @since 2025-01-17
  */
 public interface TFlowManagementMapper extends BaseMapper<TFlowManagement> {
-
+    TFlowManagementStatisticsVo getPaymentStats(@Param("req") TFlowManagementQuery query);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
index 38f218b..8baef49 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
@@ -5,9 +5,11 @@
 import com.baomidou.mybatisplus.annotation.TableId;
 
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+import java.util.Date;
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -54,7 +56,7 @@
     @ApiModelProperty(value = "应缴费日期")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @TableField("payable_fees_time")
-    private LocalDateTime payableFeesTime;
+    private LocalDate payableFeesTime;
 
     @ApiModelProperty(value = "缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 5= 已失效")
     @TableField("pay_fees_status")
@@ -111,6 +113,31 @@
     @TableField("confirm_id")
     private String confirmId;
 
+    @ApiModelProperty(value = "短信发送状态:0.未发送  1.已发送  2.发送失败")
+    @TableField("sms_status")
+    private Integer smsStatus;
+
+    @ApiModelProperty(value = "短信最后发送时间")
+    @TableField("sms_last_time")
+    private Date smsLastTime;
+
+    @ApiModelProperty(value = "最后短信发送人")
+    @TableField("sms_send_userid")
+    private String smsSendUserid;
+
+
+    @ApiModelProperty(value = "邮件发送状态:0.未发送  1.已发送  2.发送失败")
+    @TableField("mail_status")
+    private Integer mailStatus;
+
+    @ApiModelProperty(value = "邮件最后发送时间")
+    @TableField("mail_last_time")
+    private Date mailLastTime;
+
+    @ApiModelProperty(value = "最后邮件发送人")
+    @TableField("mail_send_userid")
+    private String mailSendUserid;
+
     /**
      * 抵扣金额
      */
@@ -122,4 +149,9 @@
     @TableField(exist = false)
     private BigDecimal preOutstand;
 
+
+
+
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java
index 287b231..cf29a4f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java
@@ -80,5 +80,9 @@
     @TableField("contract_number")
     private String contractNumber;
 
+    @ApiModelProperty(value = "开票文件名称")
+    @TableField("invoice_voucher_name")
+    private String invoiceVoucherName;
+
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java
index e40dd4e..7a7cf34 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.query;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.common.core.domain.BasePage;
 import io.swagger.annotations.ApiModel;
@@ -54,4 +55,7 @@
     @ApiModelProperty(value = "开票结束日期")
     private String invoiceEndTime;
 
+    @ApiModelProperty(value = "开票文件名称")
+    private String invoiceVoucherName;
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java
index 6e945d3..46234e1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java
@@ -3,9 +3,8 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TBankFlow;
-import com.ruoyi.system.model.TFlowManagement;
 import com.ruoyi.system.query.TBankFlowQuery;
-import com.ruoyi.system.query.TFlowManagementQuery;
+import com.ruoyi.system.vo.TBankFlowStatisticsVo;
 
 import java.util.List;
 
@@ -21,6 +20,9 @@
 
     PageInfo<TBankFlow> pageList(TBankFlowQuery query);
     List<TBankFlow> makeQuery(TBankFlowQuery query);
+    TBankFlowStatisticsVo getPaymentStats( TBankFlowQuery query);
+
+    List<TBankFlow> searchByBankSerialNumber(String bankSerialNumber);
 
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
index 7721283..b561ecd 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.dto.OfflinePayCheckDto;
+import com.ruoyi.system.dto.SmsByBillDto;
 import com.ruoyi.system.dto.TBillDto;
 import com.ruoyi.system.dto.TbillSaveDto;
 import com.ruoyi.system.model.TBill;
@@ -76,4 +77,8 @@
      * @return
      */
     PageInfo<TBill> getBillByInvoiceId(String invoiceId);
+
+    Integer sendSmsByBillIds(SmsByBillDto dto);
+
+    Integer sendMailBatchByBillIds(SmsByBillDto dto);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java
index 5560db0..0d95c6e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TFlowManagement;
 import com.ruoyi.system.query.TFlowManagementQuery;
+import com.ruoyi.system.vo.TFlowManagementStatisticsVo;
 
 import java.util.List;
 
@@ -18,6 +19,7 @@
 public interface TFlowManagementService extends IService<TFlowManagement> {
     PageInfo<TFlowManagement> pageList(TFlowManagementQuery query);
     List<TFlowManagement> makeQuery(TFlowManagementQuery query);
+    TFlowManagementStatisticsVo getPaymentStats(TFlowManagementQuery req);
 
 
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java
index 723c203..89e5fec 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java
@@ -6,9 +6,9 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.mapper.TBankFlowMapper;
 import com.ruoyi.system.model.TBankFlow;
-import com.ruoyi.system.model.TFlowManagement;
 import com.ruoyi.system.query.TBankFlowQuery;
 import com.ruoyi.system.service.TBankFlowService;
+import com.ruoyi.system.vo.TBankFlowStatisticsVo;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -31,6 +31,7 @@
         pageInfo.setTotal(list.size());
         return pageInfo;
     }
+
     @Override
     public List<TBankFlow> makeQuery(TBankFlowQuery query) {
         LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>();
@@ -43,4 +44,21 @@
         ;
         return this.baseMapper.selectList(queryWrapper);
     }
+
+    @Override
+    public TBankFlowStatisticsVo getPaymentStats(TBankFlowQuery query) {
+        return this.baseMapper.getPaymentStats(query);
+    }
+
+    /**
+     * 根据银行流水号模糊查询
+     * @param bankSerialNumber
+     * @return
+     */
+    @Override
+    public List<TBankFlow> searchByBankSerialNumber(String bankSerialNumber) {
+        LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.like(StringUtils.isNotEmpty(bankSerialNumber),TBankFlow::getBankSerialNumber,bankSerialNumber);
+        return this.baseMapper.selectList(queryWrapper);
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
index 2c1bc20..88b06ed 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -7,9 +7,11 @@
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SmsUtil;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.UUID;
 import com.ruoyi.system.dto.OfflinePayCheckDto;
+import com.ruoyi.system.dto.SmsByBillDto;
 import com.ruoyi.system.dto.TBillDto;
 import com.ruoyi.system.dto.TbillSaveDto;
 import com.ruoyi.system.mapper.TBillMapper;
@@ -18,6 +20,8 @@
 import com.ruoyi.system.query.TInvoiceToBillQuery;
 import com.ruoyi.system.service.*;
 import com.taxi591.bankapi.dto.ChargeBillRequest;
+import com.tencentcloudapi.sms.v20190711.SmsClient;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.beans.BeanUtils;
@@ -25,6 +29,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.math.BigDecimal;
@@ -70,6 +75,10 @@
 
     @Autowired
     TInvoiceToBillService tInvoiceToBillService;
+
+
+    @Resource
+    SmsUtil smsUtil;
 
     public PageInfo<TBillDto> queryPage(TBillQuery query){
         PageInfo<TBill> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
@@ -345,4 +354,68 @@
     }
 
 
+
+    @Override
+    public Integer sendSmsByBillIds(SmsByBillDto dto) {
+        int failNum = 0;
+        for (String billId : dto.getBillIds()) {
+            TBillDto bill = getTenentByBillId(billId);
+            if (bill.getSmsLastTime()!=null
+                    && (System.currentTimeMillis()-bill.getSmsLastTime().getTime()<smsUtil.getPro().getBillSmsDelayPeriod()*60*1000L)){
+                throw new ServiceException("有账单最近一次发送的时间是:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,bill.getSmsLastTime()));
+            }
+            if (StringUtils.isEmpty(bill.getPhone())){
+                failNum++;
+                continue;
+            }
+            TBill save = new TBill();
+            save.setId(bill.getId());
+            try {
+                smsUtil.sendSms(bill.getPhone(), "", new String[]{""});
+                save.setSmsStatus(1);
+            }catch (ServiceException e){
+                failNum++;
+                save.setSmsStatus(2);
+            }
+            save.setSmsLastTime(new Date());
+            save.setSmsSendUserid(dto.getSendUserId());
+            lockAndUpdateInfo(save,1);
+        }
+        return failNum;
+    }
+
+    @Override
+    public Integer sendMailBatchByBillIds(SmsByBillDto dto) {
+        int failNum = 0;
+        for (String billId : dto.getBillIds()) {
+            TBillDto bill = getTenentByBillId(billId);
+            if (bill.getSmsLastTime()!=null
+                    && (System.currentTimeMillis()-bill.getSmsLastTime().getTime()<smsUtil.getPro().getBillMailDelayPeriod()*60*1000L)){
+                throw new ServiceException("有账单最近一次发送的时间是:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,bill.getSmsLastTime()));
+            }
+            if (StringUtils.isEmpty(bill.getEmail())){
+                failNum++;
+                continue;
+            }
+            TBill save = new TBill();
+            save.setId(bill.getId());
+            try {
+                //todo  发送邮件
+                save.setMailStatus(1);
+            }catch (ServiceException e){
+                failNum++;
+                save.setMailStatus(2);
+            }
+            save.setMailLastTime(new Date());
+            save.setMailSendUserid(dto.getSendUserId());
+            lockAndUpdateInfo(save,1);
+        }
+        return failNum;
+    }
+
+    private TBillDto getTenentByBillId(String billId) {
+        return getBaseMapper().selectTenentByBillId(billId);
+    }
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
index 8b6eae1..f227579 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
@@ -164,7 +164,7 @@
         TBill rentBill = new TBill();
         rentBill.setContractId(contract.getId());
         rentBill.setContractNumber(contract.getContractNumber());
-        rentBill.setPayableFeesTime(firstPayTime);
+        rentBill.setPayableFeesTime(firstPayTime.toLocalDate());
         if (firstPayTime.toLocalDate().equals(LocalDate.now())){
             rentBill.setPayFeesStatus("1");
         }else {
@@ -240,7 +240,7 @@
         depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney());
         depositBill.setStartTime(contract.getStartPayTime());
         depositBill.setEndTime(contract.getEndTime());
-        depositBill.setPayableFeesTime(firstPayTime);
+        depositBill.setPayableFeesTime(firstPayTime.toLocalDate());
         if (firstPayTime.toLocalDate().equals(LocalDate.now())){
             depositBill.setPayFeesStatus("1");
 
@@ -424,11 +424,11 @@
                         }
                         tBill.setContractNumber(contract.getContractNumber());
                         if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
-                            tBill.setPayableFeesTime(contract.getEndTime());
+                            tBill.setPayableFeesTime(contract.getEndTime().toLocalDate());
                         }else{
                             tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12)));
+                                    beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")?
+                                    beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).toLocalDate()));
                         }
                         tBill.setPayFeesStatus("2");
                         tBill.setBillType("1");
@@ -611,11 +611,11 @@
             }
             tBill.setContractNumber(contract.getContractNumber());
             if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
-                tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0));
+                tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0).toLocalDate());
             }else{
                 tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                        beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
-                        beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0)));
+                        beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")?
+                        beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0).toLocalDate()));
             }
             tBill.setPayFeesStatus("1");
             tBill.setBillType("1");
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java
index f793220..f5fe8b4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java
@@ -8,6 +8,7 @@
 import com.ruoyi.system.query.TFlowManagementQuery;
 import com.ruoyi.system.service.TFlowManagementService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.vo.TFlowManagementStatisticsVo;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -44,4 +45,9 @@
         ;
         return this.baseMapper.selectList(queryWrapper);
     }
+
+    @Override
+    public TFlowManagementStatisticsVo getPaymentStats(TFlowManagementQuery query) {
+        return this.baseMapper.getPaymentStats(query);
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java
index aacd7b8..af3ecde 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java
@@ -1,22 +1,14 @@
 package com.ruoyi.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.model.TInvoice;
-import com.ruoyi.system.model.TInvoiceToBill;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.system.mapper.TInvoiceToBillMapper;
+import com.ruoyi.system.model.TInvoiceToBill;
 import com.ruoyi.system.query.TInvoiceToBillQuery;
 import com.ruoyi.system.service.TInvoiceToBillService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.system.mapper.TInvoiceToBillMapper;
-import com.ruoyi.system.model.TInvoiceToBill;
-import com.ruoyi.system.service.TInvoiceToBillService;
-import org.springframework.stereotype.Service;
 
 /**
  * <p>
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java
new file mode 100644
index 0000000..62336be
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author 64502
+ */
+@Data
+@ApiModel(value = "系统流水统计VO")
+public class TBankFlowStatisticsVo {
+    @ApiModelProperty(value = "流水总额")
+    private BigDecimal totalFlowMoney;
+
+    @ApiModelProperty(value = "已抵扣金额")
+    private BigDecimal totalDeductionMoney;
+
+    @ApiModelProperty(value = "剩余未抵扣")
+    private BigDecimal totalRemainingMoney;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java
new file mode 100644
index 0000000..5dc10b2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java
@@ -0,0 +1,27 @@
+package com.ruoyi.system.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author 64502
+ */
+@Data
+@ApiModel(value = "系统流水统计VO")
+public class TFlowManagementStatisticsVo {
+    @ApiModelProperty(value = "系统流水总额")
+    private BigDecimal totalAmount;
+
+    @ApiModelProperty(value = "微信")
+    private BigDecimal wechatAmount;
+
+    @ApiModelProperty(value = "支付宝")
+    private BigDecimal alipayAmount;
+
+    @ApiModelProperty(value = "线下支付")
+    private BigDecimal offlineAmount;
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml
index 61d5859..c72c8f5 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml
@@ -26,4 +26,40 @@
         id, bank_serial_number, flow_money, deduction_money, remaining_money, pay_time, payer, flow_status, pay_type, payment_bill_id, create_time, update_time, create_by, update_by, disabled
     </sql>
 
+
+    <!-- 定义结果映射 -->
+    <resultMap id="PaymentStatsResultMap" type="com.ruoyi.system.vo.TBankFlowStatisticsVo">
+        <result property="totalFlowMoney" column="totalFlowMoney" />
+        <result property="totalDeductionMoney" column="totalDeductionMoney" />
+        <result property="totalRemainingMoney" column="totalRemainingMoney" />
+    </resultMap>
+
+    <!-- 统计总额和微信支付金额 -->
+    <select id="getPaymentStats" resultMap="PaymentStatsResultMap">
+        SELECT
+        SUM(flow_money) AS totalFlowMoney,
+        SUM(deduction_money) AS totalDeductionMoney,
+        SUM(remaining_money) AS totalRemainingMoney
+        FROM
+        t_bank_flow
+        <where>
+            <if test="req.bankSerialNumber != null and req.bankSerialNumber != ''">
+                and bank_serial_number = #{req.bankSerialNumber}
+            </if>
+            <if test="req.payer != null and req.payer != ''">
+                and payer like concat('%', #{req.payer}, '%')
+            </if>
+            <if test="req.flowStatus != null and req.flowStatus != ''">
+                and flow_status = #{req.flowStatus}
+            </if>
+            <if test="req.payStartTime != null and req.payStartTime != ''">
+                and pay_time &gt;= #{req.payStartTime}
+            </if>
+            <if test="req.payEndTime != null and req.payEndTime != ''">
+                and pay_time &lt;= #{req.payEndTime}
+            </if>
+            AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        </where>
+    </select>
+
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
index c52d5ba..76763fd 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
@@ -63,6 +63,7 @@
                 and t.id = #{query.userId}
             </if>
         </where>
+        order by b.payable_fees_time desc
     </select>
     <select id="getBillList" resultType="com.ruoyi.system.dto.TBillDto">
         SELECT
@@ -128,4 +129,20 @@
         </where>
         order by b.pay_fees_time
     </select>
+
+    <select id="selectTenentByBillId" resultType="com.ruoyi.system.dto.TBillDto">
+        SELECT
+            b.*,
+            t.resident_name as residentName,
+            t.email,
+            t.phone,
+            t.account,
+            h.house_name as houseName
+        FROM
+            t_bill b
+        LEFT JOIN t_contract c ON c.contract_number = b.contract_number and c.disabled=0
+        LEFT JOIN t_house h ON h.id = c.house_id and h.disabled=0
+        LEFT JOIN t_tenant t ON t.id = c.tenant_id and t.disabled=0
+        where b.id = #{billId}
+    </select>
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml
index c864d32..f11b0fd 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml
@@ -28,4 +28,46 @@
         id, sys_serial_number, bank_serial_number, flow_money, deduction_money, remaining_money, pay_time, payer, flow_status, flow_type, pay_type, payment_bill_id, create_time, update_time, create_by, update_by, disabled
     </sql>
 
+
+    <!-- 定义结果映射 -->
+    <resultMap id="PaymentStatsResultMap" type="com.ruoyi.system.vo.TFlowManagementStatisticsVo">
+        <result property="totalAmount" column="total_amount" />
+        <result property="wechatAmount" column="wechat_amount" />
+        <result property="alipayAmount" column="alipay_amount" />
+        <result property="offlineAmount" column="offline_amount" />
+    </resultMap>
+
+    <!-- 统计总额和微信支付金额 -->
+    <select id="getPaymentStats" resultMap="PaymentStatsResultMap">
+        SELECT SUM(flow_money) AS total_amount,
+               SUM(CASE WHEN pay_type = 1 THEN flow_money ELSE 0 END ) AS wechat_amount,
+               SUM(CASE WHEN pay_type = 2 THEN flow_money ELSE 0 END ) AS alipay_amount,
+               SUM(CASE WHEN pay_type = 3 THEN flow_money ELSE 0 END ) AS offline_amount
+        FROM
+            t_flow_management
+        <where>
+            <if test="req.sysSerialNumber != null and req.sysSerialNumber != ''">
+                 and sys_serial_number = #{req.sysSerialNumber}
+            </if>
+            <if test="req.bankSerialNumber != null and req.bankSerialNumber != ''">
+                 and bank_serial_number = #{req.bankSerialNumber}
+            </if>
+            <if test="req.payer != null and req.payer != ''">
+                 and payer like concat('%', #{req.payer}, '%')
+            </if>
+            <if test="req.payType != null and req.payType != ''">
+                 and pay_type = #{req.payType}
+            </if>
+            <if test="req.payStartTime != null and req.payStartTime != ''">
+                 and pay_time &gt;= #{req.payStartTime}
+            </if>
+            <if test="req.payEndTime != null and req.payEndTime != ''">
+                 and pay_time &lt;= #{req.payEndTime}
+            </if>
+            AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        </where>
+    </select>
+
+
+
 </mapper>

--
Gitblit v1.7.1