无关风月
2025-02-19 efb2457e0f7b6e5a76999c239d8b079b21c88eb0
Merge branch 'master' of https://gitee.com/xiaochen991015/xizang
27个文件已修改
6个文件已添加
660 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBankFlowService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TFlowManagementService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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));
    }
}
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;
    }
}
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 = "获取合同分页列表")
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));
    }
}
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));
    }
}
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");
                }
            }
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() + "元");
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>
ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java
New file
@@ -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);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/config/SmsProperties.java
New file
@@ -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;
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtil.java
New file
@@ -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");
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/SmsByBillDto.java
New file
@@ -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;
}
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;
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;
}
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);
}
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);
}
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);
}
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;
}
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;
}
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;
}
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);
}
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);
}
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);
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);
    }
}
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);
    }
}
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");
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);
    }
}
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>
ruoyi-system/src/main/java/com/ruoyi/system/vo/TBankFlowStatisticsVo.java
New file
@@ -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;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/TFlowManagementStatisticsVo.java
New file
@@ -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;
}
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>
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>
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>