无关风月
2025-04-10 099ea14bba367fd86f0dde37d908f07cc04c3d39
Merge branch 'dev' of http://120.76.84.145:10101/gitblit/r/java/xizang
32个文件已添加
89个文件已修改
4609 ■■■■ 已修改文件
pom.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ScreenController.java 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysFileController.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBannerController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBusinessDeptController.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java 638 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/THouseController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TRentalReturnRecordController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TStreetController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTenantController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-test.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TRentalReturnRecordController.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/OfflinePayCheckDto.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TContractDTO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TerminateContractDTO.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBusinessDeptMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TContractMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/THouseMapper.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TRentalReturnRecordMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TStreetMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTenantMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBankFlow.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBusinessDept.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TFlowManagement.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/THouse.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TRentalReturnRecord.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TStreet.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/RentalReturnAuditQuery.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/RentalReturnRecordQuery.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TBankFlowQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordAppletQuery.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TContractQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TFlowManagementQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/THouseQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TTenantQuery.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ITBusinessDeptService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ITRentalReturnRecordService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ITStreetService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/THouseService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TInvoiceService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java 150 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ScreenService.java 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateTaskCenterServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java 245 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBusinessDeptServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceServiceImpl.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TRentalReturnRecordServiceImpl.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TStreetServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseMapDistributionVO.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/MyHouseVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/RealTimeRentDataVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/RentalRetureApplyVO.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/RentalReturnRecordVO.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenRentIncomeTrendVO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenRentRankVO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenTopStaticsDataVO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TenantCountTrendVO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/YearQuarter.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBusinessDeptMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TRentalReturnRecordMapper.xml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TStreetMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TTenantMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -87,24 +87,18 @@
            </dependency>
            <!-- excel工具 -->
           <dependency>
               <groupId>org.apache.poi</groupId>
               <artifactId>poi-ooxml</artifactId>
               <version>${poi.version}</version>
           </dependency>
            <!-- Apache POI核心依赖 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.17</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.17</version>
            </dependency>
           <dependency>
               <groupId>org.apache.poi</groupId>
               <artifactId>poi</artifactId>
               <version>${poi.version}</version>
           </dependency>
           <dependency>
               <groupId>org.apache.poi</groupId>
               <artifactId>poi-ooxml-schemas</artifactId>
               <version>${poi.version}</version>
           </dependency>
            <!-- velocity代码生成使用模板 -->
            <dependency>
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java
@@ -6,6 +6,7 @@
import com.alibaba.fastjson.TypeReference;
import com.ruoyi.common.constant.AmountConstant;
import com.ruoyi.common.enums.BillTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.model.TOrderBill;
@@ -13,9 +14,7 @@
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TOrderBillService;
import com.ruoyi.system.service.TPayOrderService;
import com.taxi591.bankapi.dto.CovertPayBackResult;
import com.taxi591.bankapi.dto.QueryBillRequest;
import com.taxi591.bankapi.dto.QueryBillResponse;
import com.taxi591.bankapi.dto.*;
import com.taxi591.bankapi.service.BankService;
import com.taxi591.bankapi.service.SignatureAndVerification;
import lombok.extern.slf4j.Slf4j;
@@ -28,9 +27,14 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -54,13 +58,188 @@
    @Autowired
    TPayOrderService payOrderService;
    public static String getRequestBody(HttpServletRequest request)
            throws IOException {
        /** 读取httpbody内容 */
        StringBuilder httpBody = new StringBuilder();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(
                    request.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                httpBody.append(line);
            }
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return httpBody.toString();
    }
    @PostMapping(value = "payCallback")
    public @ResponseBody String payCallback(HttpServletRequest request){
        CovertPayBackResult result = bankService.covertPayCallBack(request, (billRequest) -> {
            tBillService.completePay(billRequest);
            return true;
        });
        return result.getBack();
    public void payCallback(HttpServletRequest servletRequest,HttpServletResponse servletResponse){
        String request = null;
        String responseJson = null;
        try {
            log.info("--------进入getRequest4Sale----------------------------------");
            // 接收报文
            String requestContent = getRequestBody(servletRequest).trim();
            String signatureString = requestContent.substring(0,
                    requestContent.indexOf("||"));
            log.info("-----ChargeBillController------------截取报文的signatureString:{}", signatureString);
            String requestBody = requestContent.substring(signatureString
                    .length() + 2);
            log.info("-----ChargeBillController------------截取报文的requestBody:{}", requestBody);
            //如果有双引号,则截取双引号内requestBody的内容
            Pattern p=Pattern.compile("\"");
            Matcher m=p.matcher(requestBody);
            while(m.find()){
                requestBody=requestBody.replace(m.group(), "");
                log.info("-----ChargeBillController------如果有双引号,则截取后的requestBody:{}", requestBody);
            }
            //requestBody是base64加密后的数据,需解析出来
            request = new String(
                    com.alibaba.fastjson.util.Base64.decodeFast(requestBody));
            log.info("-----ChargeBillController------------解析完成后的requestBody-------{}" + request);
            ChargeBillRequest chargeBillRequest = JSON.parseObject(request,
                    new TypeReference<ChargeBillRequest>() {
                    });
            boolean b = signatureAndVerification.read_cer_and_verify_sign(requestBody,
                    signatureString);
            if (!b){
                throw new ServiceException("验签失败");
            }
            /** 销账报文重发次数,通过resendTimes此字段识别销账报文是否为重发的,0表示首次、1表示重发一次,2表示重发2次,最多重发3次*/
            if(chargeBillRequest!=null && "0".equals(chargeBillRequest.getMessage().getInfo().getResendTimes())){
                ChargeBillResponse chargeBillResponse = new ChargeBillResponse(
                        chargeBillRequest);
                ChargeBillResponse.Message respMessage = chargeBillResponse
                        .getMessage();
                ChargeBillResponse.Message.Head respHead = chargeBillResponse
                        .getMessage().getHead();
                ChargeBillResponse.Message.Info respInfo = chargeBillResponse
                        .getMessage().getInfo();
                respHead.setTransFlag("02");
                respHead.setTimeStamp(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
                // respHead.setChannel("MBNK");
                respHead.setChannel(chargeBillRequest.getMessage().getHead()
                        .getChannel());
                // respHead.setTranCode("chargeBill");
                respHead.setTransCode(chargeBillRequest.getMessage().getHead()
                        .getTransCode());
                respHead.setTransSeqNum(chargeBillRequest.getMessage().getHead()
                        .getTransSeqNum());
                //测试销账返回报文中,本来是销账成功的报文,但是不要送0000成功码   (JF190510134746710555这个流水号是在Demo的returnCode设置成null的时候产生的,流水状态为6;)
                String epayCode = chargeBillRequest.getMessage().getInfo()
                        .getEpayCode();
                String traceNo = chargeBillRequest.getMessage().getInfo()
                        .getTraceNo();
                String numOpenMerchantOrder = chargeBillRequest.getMessage()
                        .getInfo().getNumOpenMerchantOrder();
                respInfo.setNumOpenMerchantOrder(numOpenMerchantOrder);
                respInfo.setEpayCode(epayCode);
                respInfo.setTraceNo(traceNo);
                try{
                    tBillService.completePay(chargeBillRequest);
                    respHead.setReturnCode("0000");
                    respHead.setReturnMessage("账单缴费成功");
                }catch (Exception e){
                    respHead.setReturnCode("1111");
                    respHead.setReturnMessage("账单处理失败");
                    log.error("支付第一次回调出现异常,{}",request,e);
                }
                //第一次处理失败,不退款
                respInfo.setRefundFlag("false");
                respMessage.setInfo(respInfo);
                respMessage.setHead(respHead);
                chargeBillResponse.setMessage(respMessage);
                responseJson = JSON.toJSONString(chargeBillResponse);
                //加签名
                String signatrue = signatureAndVerification
                        .signWhithsha1withrsa(responseJson);
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密前):" + responseJson);
                responseJson = signatrue + "||"
                        + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密后):" + responseJson);
                servletResponse.setCharacterEncoding("utf-8");
                servletResponse.setContentType("text/plain");
                servletResponse.getWriter().write(responseJson);
            }else{
                //销账报文重发次数,通过resendTimes此字段识别销账报文是否为重发的,0表示首次、1表示重发一次,2表示重发2次,最多重发3次
                //商户端要注意销账重复通知的情况,要进行订单唯一性处理
                ChargeBillResponse chargeBillResponse = new ChargeBillResponse(
                        chargeBillRequest);
                ChargeBillResponse.Message respMessage = chargeBillResponse
                        .getMessage();
                ChargeBillResponse.Message.Head respHead = chargeBillResponse
                        .getMessage().getHead();
                ChargeBillResponse.Message.Info respInfo = chargeBillResponse
                        .getMessage().getInfo();
                respHead.setTransFlag("02");
                respHead.setTimeStamp(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
                // respHead.setChannel("MBNK");
                respHead.setChannel(chargeBillRequest.getMessage().getHead()
                        .getChannel());
                // respHead.setTranCode("chargeBill");
                respHead.setTransCode(chargeBillRequest.getMessage().getHead()
                        .getTransCode());
                respHead.setTransSeqNum(chargeBillRequest.getMessage().getHead()
                        .getTransSeqNum());
                try{
                    tBillService.completePay(chargeBillRequest);
                    respHead.setReturnCode("0000");
                    respHead.setReturnMessage("账单缴费成功");
                }catch (Exception e){
                    respHead.setReturnCode("1111");
                    respHead.setReturnMessage("账单处理失败");
                    log.error("支付第一次回调出现异常,{}",request,e);
                }
                // 再次推送未处理成功,则返回退款标志
                if (!"0000".equals(respHead.getReturnCode())) {
                    respInfo.setRefundFlag("true");
                }
                String epayCode = chargeBillRequest.getMessage().getInfo()
                        .getEpayCode();
                String traceNo = chargeBillRequest.getMessage().getInfo()
                        .getTraceNo();
                String numOpenMerchantOrder = chargeBillRequest.getMessage()
                        .getInfo().getNumOpenMerchantOrder();
                respInfo.setNumOpenMerchantOrder(numOpenMerchantOrder);
                respInfo.setEpayCode(epayCode);
                respInfo.setTraceNo(traceNo);
                respMessage.setInfo(respInfo);
                respMessage.setHead(respHead);
                chargeBillResponse.setMessage(respMessage);
                responseJson = JSON.toJSONString(chargeBillResponse);
                //加签名
                String signatrue = signatureAndVerification
                        .signWhithsha1withrsa(responseJson);
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密前):" + responseJson);
                responseJson = signatrue + "||"
                        + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密后):" + responseJson);
                servletResponse.setCharacterEncoding("utf-8");
                servletResponse.setContentType("text/plain");
                servletResponse.getWriter().write(responseJson);
            }
        }catch (Exception e) {
            log.error("处理支付回调发生异常:返回内容:{}",request,e);
        }
    }
    @PostMapping(value = "queryBill")
@@ -99,8 +278,8 @@
                    .getInfo();
            //缴费账单子账单
            ArrayList<QueryBillResponse.Message.Info.Bill> respBills = new ArrayList<QueryBillResponse.Message.Info.Bill>();
            ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail> respDescDetail =
                    new ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail>();
//            ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail> respDescDetail =
//                    new ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail>();
            QueryBillResponse.Message.Info.Bill respBill = respInfo.new Bill();
            //缴费子商户账单
//            ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo> splitSubMerInfos = new ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo>();
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ScreenController.java
New file
@@ -0,0 +1,260 @@
package com.ruoyi.web.controller.api;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.TStreet;
import com.ruoyi.system.service.ITStreetService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.service.impl.ScreenService;
import com.ruoyi.system.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import static org.checkerframework.checker.units.qual.Prefix.one;
/**
 * @author mitao
 * @date 2025/3/19
 */
@Api(tags = {"大屏相关接口"})
@RestController
@RequestMapping("/screen")
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ScreenController {
    private final ScreenService screenService;
    private final TContractService contractService;
    private final THouseService houseService;
    private final ITStreetService streetService;
    private final TBillService billService;
    @GetMapping("/statics-data")
    @ApiOperation(value = "获取顶部统计数据")
    public R<ScreenTopStaticsDataVO> getTopStaticsData() {
        return R.ok(screenService.getTopStaticsData());
    }
    @GetMapping("/rent-rank")
    @ApiOperation("区域租金排名")
    public R<List<ScreenRentRankVO>> rentRank() {
        return R.ok(screenService.streetRentRank());
    }
    @GetMapping("/rent-income-trend")
    @ApiOperation("租金收入趋势")
    public R<ScreenRentIncomeTrendVO> rentIncomeTrend() {
        return R.ok(screenService.rentIncomeTrend());
    }
    @GetMapping("/getTenantCountTrend")
    @ApiOperation(value = "租户数量趋势统计")
    public R<List<TenantCountTrendVO>> getTenantCountTrend() {
        return screenService.getTenantCountTrend();
    }
    /**
     * 实时租赁数据
     */
    @GetMapping("/getRealTimeRentData")
    @ApiOperation("获取实时租赁数据")
    public R<List<RealTimeRentDataVO>> getRealTimeRentData() {
        // 随机获取十条房源
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        List<THouse> houses = houseService.list(new LambdaQueryWrapper<THouse>()
                .eq(!"0".equals(businessDeptId),THouse::getBusinessDeptId, businessDeptId)
                .last("ORDER BY RAND() LIMIT 10"));
        if (CollectionUtil.isEmpty(houses)){
            return R.ok(new ArrayList<>());
        }
        // 提取streetIds
        List<String> streetIds = houses.stream()
                .map(THouse::getStreetId)
                .collect(Collectors.toList());
        // 获取街道信息
        Map<String, String> streetMap = streetService.listByIds(streetIds).stream()
                .collect(Collectors.toMap(TStreet::getId, TStreet::getStreetName));
        // 转换为返回格式
        List<RealTimeRentDataVO> result = houses.stream().map(house -> {
            RealTimeRentDataVO vo = new RealTimeRentDataVO();
            vo.setStreetName(streetMap.getOrDefault(house.getStreetId(), "未知"));
            vo.setRoomName(house.getHouseName());
            vo.setLeaseStatus(house.getLeaseStatus());
            return vo;
        }).collect(Collectors.toList());
        return R.ok(result);
    }
    public static void main(String[] args) {
        // 获取当前季度的开始和结束时间
        // 获取当前季度的开始和结束时间的实现示例:
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate now = LocalDate.now();
        int month = now.getMonthValue();
        int year = now.getYear();
        // 计算季度起始月份(1,4,7,10)
        int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
        int quarterEndMonth = quarterStartMonth + 2;
        // 构建季度起止日期
        LocalDate quarterStart = YearMonth.of(year, quarterStartMonth).atDay(1);
        LocalDate quarterEnd = YearMonth.of(year, quarterEndMonth).atEndOfMonth();
        System.out.println("季度开始:" + quarterStart.format(formatter));
        System.out.println("季度结束:" + quarterEnd.format(formatter));
    }
    /**
     * 获取房屋地图分布
     */
    @GetMapping("/getHouseMapDistribution")
    @ApiOperation("获取房屋地图分布")
    public R<List<HouseMapDistributionVO>> getHouseMapDistribution() {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        List<TContract> tContracts = contractService.list(new LambdaQueryWrapper<TContract>()
                .eq(!"0".equals(businessDeptId), TContract::getBusinessDeptId, businessDeptId)
                .eq(TContract::getPayType, 2));
        List<String> houseIds = tContracts.stream().map(TContract::getHouseId).collect(Collectors.toList());
        // 获取所有房屋信息
        List<THouse> houses = houseService.list(new LambdaQueryWrapper<THouse>()
                        .and(wrapper -> wrapper.in(!houseIds.isEmpty(),THouse::getId, houseIds)
                                        .or(!houseIds.isEmpty())
                                        .eq(THouse::getLeaseStatus, "1")
                        )
                .eq(!"0".equals(businessDeptId),THouse::getBusinessDeptId, businessDeptId)
        );
        List<HouseMapDistributionVO> result = new ArrayList<>();
        for (THouse house : houses) {
            HouseMapDistributionVO houseMapDistributionVO = new HouseMapDistributionVO();
            houseMapDistributionVO.setHouseName(house.getHouseName());
            houseMapDistributionVO.setHouseAddress(house.getHouseAddress());
            houseMapDistributionVO.setHouseStatus(house.getLeaseStatus());
            houseMapDistributionVO.setLongitude(house.getLongitude());
            houseMapDistributionVO.setLatitude(house.getLatitude());
            TContract contract = contractService.getOne(new LambdaQueryWrapper<TContract>()
                    .eq(!"0".equals(businessDeptId),TContract::getBusinessDeptId, businessDeptId)
                    .eq(TContract::getPayType, 2)
                    .gt(TContract::getEndTime, LocalDate.now())
                    .eq(TContract::getHouseId, house.getId())
                    .eq(TContract::getStatus, 4)
                    .last("limit 1"));
            if (contract != null){
                List<TBill> tBills = billService.list(new LambdaQueryWrapper<TBill>()
                        .eq(!"0".equals(businessDeptId),TBill::getBusinessDeptId, businessDeptId)
                        .eq(TBill::getContractId, contract.getId())
                        .eq(TBill::getBillType, 1));
                houseMapDistributionVO.setTenant(contract.getPartyTwoName());
                BigDecimal payFeesMoney = tBills.stream()
                        .map(TBill::getPayFeesMoney)
                        .reduce(BigDecimal::add)
                        .orElse(BigDecimal.ZERO);
                BigDecimal payableFeesMoney = tBills.stream()
                        .map(TBill::getPayableFeesMoney)
                        .reduce(BigDecimal::add)
                        .orElse(BigDecimal.ZERO);
                String rentStatus = String.format("%.2f/%.2f", payFeesMoney, payableFeesMoney);
                houseMapDistributionVO.setRentStatus(rentStatus);
//                TBill one = billService.getOne(new LambdaQueryWrapper<TBill>()
//                        .le(TBill::getStartTime, LocalDate.now())
//                        .ge(TBill::getEndTime, LocalDate.now())
//                        .eq(TBill::getBillType, 1)
//                        .eq(TBill::getContractId, contract.getId()));
                // 获取当前季度的开始和结束时间
                // 获取当前季度的开始和结束时间的实现示例:
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate now = LocalDate.now();
                int month = now.getMonthValue();
                int year = now.getYear();
                // 计算季度起始月份(1,4,7,10)
                int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
                int quarterEndMonth = quarterStartMonth + 2;
                // 构建季度起止日期
                LocalDate quarterStart = YearMonth.of(year, quarterStartMonth).atDay(1);
                LocalDate quarterEnd = YearMonth.of(year, quarterEndMonth).atEndOfMonth();
                System.out.println("季度开始:" + quarterStart.format(formatter));
                System.out.println("季度结束:" + quarterEnd.format(formatter));
                List<TBill> ones = billService.list(new LambdaQueryWrapper<TBill>()
                        .eq(!"0".equals(businessDeptId),TBill::getBusinessDeptId, businessDeptId)
                        .between(TBill::getStartTime, quarterStart, quarterEnd)
                        .eq(TBill::getBillType, 1)
                        .eq(TBill::getContractId, contract.getId()));
                if (!ones.isEmpty()){
                    long count = ones.stream().filter(tBill -> "4".equals(tBill.getPayFeesStatus())).count();
                    if (count > 0){
                        houseMapDistributionVO.setHouseStatus("4");
                    }
                    BigDecimal payFeesMoney1 = ones.stream()
                            .map(TBill::getPayFeesMoney)
                            .reduce(BigDecimal::add)
                            .orElse(BigDecimal.ZERO);
                    BigDecimal payableFeesMoney1 = ones.stream()
                            .map(TBill::getPayableFeesMoney)
                            .reduce(BigDecimal::add)
                            .orElse(BigDecimal.ZERO);
                    String rent = String.format("%.2f/%.2f", payFeesMoney1, payableFeesMoney1);
                    houseMapDistributionVO.setRent(rent);
                }else {
                    houseMapDistributionVO.setRent("欠费");
                }
            }else {
                houseMapDistributionVO.setTenant("暂无");
                houseMapDistributionVO.setRentStatus("待出租");
                houseMapDistributionVO.setRent("暂无");
            }
            result.add(houseMapDistributionVO);
        }
        return R.ok(result);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysFileController.java
@@ -1,8 +1,18 @@
package com.ruoyi.web.controller.api;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
@@ -16,7 +26,22 @@
@RequestMapping("/sys-file")
public class SysFileController {
    public static void main(String[] args) throws IOException, InvalidFormatException {
        XWPFDocument document= new XWPFDocument();
        FileOutputStream out = new FileOutputStream(new File("D:\\a.docx"));
        //基本信息表格
        XWPFParagraph pic = document.createParagraph();
        XWPFRun picRun = pic.createRun();
            picRun.addPicture(
                    new FileInputStream("C:\\Users\\Admin\\Pictures\\Camera Roll\\1.jpg"),XWPFDocument.PICTURE_TYPE_JPEG,
                    "C:\\Users\\Admin\\Pictures\\Camera Roll\\1.jpg",
                    Units.toEMU(60),
                    Units.toEMU(30)
            );
        document.write(out);
        out.close();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBankFlowController.java
@@ -6,6 +6,7 @@
import com.alibaba.excel.event.AnalysisEventListener;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.WebUtils;
import com.ruoyi.system.importExcel.TBankFlowImportExcel;
@@ -48,6 +49,7 @@
    @ApiOperation(value = "获取银行流水列表")
    @PostMapping("/list")
    public R<PageInfo<TBankFlow>> list(@RequestBody TBankFlowQuery query) {
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        return R.ok(flowService.pageList(query));
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBannerController.java
@@ -39,7 +39,7 @@
    /**
     * 获取轮播图管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:banner:list')")
    @PreAuthorize("@ss.hasPermi('system:banner')")
    @ApiOperation(value = "获取轮播图分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TBanner>> pageList(@RequestBody TBannerQuery query) {
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -3,25 +3,39 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.*;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.dto.BillStatisticsDto;
import com.ruoyi.system.dto.CachPayDto;
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.TBillConfirm;
import com.ruoyi.system.model.TBillDetail;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.query.TContractQuery;
import com.ruoyi.system.service.TBillConfirmService;
import com.ruoyi.system.service.TBillDetailService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
 * <p>
@@ -45,19 +59,63 @@
    @Autowired
    TBillConfirmService tBillConfirmService;
    @Autowired
    TContractService contractService;
    @PreAuthorize("@ss.hasPermi('bill:list')")
    @PostMapping("list")
    @ApiOperation("分页查询账单列表")
    public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        PageInfo<TBillDto> pageInfo = tBillService.queryPage(query);
        return R.ok(pageInfo);
    }
    @ApiOperation("统计")
    @PostMapping("statistics")
    public R<BillStatisticsDto> statistics(@RequestBody TBillQuery query){
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        BillStatisticsDto dto = tBillService.statistics(query);
        return R.ok(dto);
    }
    @ApiOperation(value = "获取合同分页列表")
    @PostMapping(value = "/contractList")
    public R<PageInfo<TContract>> contractList(@RequestBody TContractQuery query) {
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        return R.ok(contractService.queryPage(query));
    }
    @PreAuthorize("@ss.hasPermi('bill:list:addRent')")
    @PostMapping("add")
    @ApiOperation("新增账单")
    public R<PageInfo<TBillDto>> add(@Validated @RequestBody TbillSaveDto bill){
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        if (SecurityUtils.getBusinessDeptId().equals("0")) {
            TContract contract = contractService.getById(bill.getContractId());
            if (Objects.nonNull(contract)) {
                businessDeptId = contract.getBusinessDeptId();
            }
        }
        bill.setBusinessDeptId(businessDeptId);
        tBillService.saveBill(bill);
        return R.ok();
    }
    @PreAuthorize("@ss.hasPermi('bill:list:editAmount')")
    @PostMapping("editAmount")
    @ApiOperation("修改账单金额")
    public R editAmount(@Validated @RequestBody TbillSaveDto bill){
        if (StringUtils.isEmpty(bill.getId())){
            return R.fail("参数错误");
        }
        if (bill.getEditAmount().compareTo(BigDecimal.ZERO)==0){
            return R.fail("调整金额不能为0");
        }
        tBillService.editAmount(bill);
        return R.ok();
    }
@@ -120,12 +178,7 @@
    }
    @ApiOperation("统计")
    @GetMapping("statistics")
    public R<BillStatisticsDto> statistics(){
        BillStatisticsDto dto = tBillService.statistics();
        return R.ok(dto);
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBusinessDeptController.java
New file
@@ -0,0 +1,46 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.model.TBusinessDept;
import com.ruoyi.system.service.ITBusinessDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * <p>
 * 营业部 前端控制器
 * </p>
 *
 * @author mitao
 * @since 2025-03-24
 */
@Api(tags = {"营业部相关接口"})
@Validated
@RestController
@RequestMapping("/t-business-dept")
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class TBusinessDeptController {
    private final ITBusinessDeptService businessDeptService;
    @ApiOperation(value = "获取营业部列表")
    @GetMapping("/list/type")
    public R<List<TBusinessDept>> list(@ApiParam(name = "type",value = "是否添加人员使用 1:是 0:否",required = true) Integer type ) {
        List<TBusinessDept> list = businessDeptService.list();
        if (type == 1){
            TBusinessDept tBusinessDept = new TBusinessDept();
            tBusinessDept.setId("0");
            tBusinessDept.setName("领导层");
            list.add(0,tBusinessDept);
        }
        return R.ok(list);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java
@@ -7,15 +7,9 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TCheckAcceptRecord;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.*;
import com.ruoyi.system.query.TCheckAcceptRecordQuery;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TCheckAcceptRecordService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.TCheckAcceptRecordVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -29,6 +23,7 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
 * <p>
@@ -49,6 +44,8 @@
    @Autowired
    private TBillService billService;
    @Autowired
    private TTenantService tenantService;
    @Autowired
    public TCheckAcceptRecordController(TCheckAcceptRecordService checkAcceptRecordService, TContractService contractService, THouseService houseService) {
        this.checkAcceptRecordService = checkAcceptRecordService;
        this.contractService = contractService;
@@ -58,7 +55,7 @@
    /**
     * 获取验收记录管理列表
     */
    @PreAuthorize("@ss.hasPermi('houseManage:check:list')")
    @PreAuthorize("@ss.hasPermi('houseManage:check')")
    @ApiOperation(value = "获取验收记录分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TCheckAcceptRecordVO>> pageList(@RequestBody TCheckAcceptRecordQuery query) {
@@ -73,6 +70,10 @@
    public R<THouse> getHouseByContractId(@RequestParam String contractId) {
        TContract contract = contractService.getById(contractId);
        THouse house = houseService.getById(contract.getHouseId());
        TTenant tenant = tenantService.getById(contract.getTenantId());
        if(Objects.nonNull(tenant)){
            house.setTenantType(tenant.getTenantType());
        }
        return R.ok(house);
    }
@@ -113,10 +114,12 @@
            tBill.setContractId(dto.getContractId());
            tBill.setContractNumber(contract.getContractNumber());
            tBill.setPayableFeesMoney(dto.getCheckMoney());
            tBill.setOutstandingMoney(dto.getCheckMoney());
            tBill.setPayableFeesTime(LocalDate.now());
            tBill.setPayFeesStatus("1");
            tBill.setBillType("4");
            tBill.setSmsStatus(0);
            tBill.setBusinessDeptId(contract.getBusinessDeptId());
            billService.save(tBill);
        }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -3,6 +3,7 @@
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.mybatisplus.mapper.FlwTaskMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -13,21 +14,31 @@
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.DisabledEnum;
import com.ruoyi.common.enums.ProcessCategoryEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.WebUtils;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.bo.ProcessStartBO;
import com.ruoyi.system.dto.RevokeDTO;
import com.ruoyi.system.dto.SetContractDto;
import com.ruoyi.system.dto.TContractDTO;
import com.ruoyi.system.dto.TerminateContractDTO;
import com.ruoyi.system.export.ContractExport;
import com.ruoyi.system.model.*;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TCheckAcceptRecord;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TContractRentType;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.TTenant;
import com.ruoyi.system.query.TContractBillQuery;
import com.ruoyi.system.query.TContractQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.StateProcessTemplateService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TCheckAcceptRecordService;
import com.ruoyi.system.service.TContractRentTypeService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.service.TTenantService;
import com.ruoyi.system.task.base.QuartzManager;
import com.ruoyi.system.task.base.TimeJobType;
import com.ruoyi.system.task.jobs.StateProcessJob;
@@ -43,16 +54,31 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * <p>
@@ -80,6 +106,8 @@
    private StateProcessTemplateService stateProcessTemplateService;
    @Autowired
    private FlwTaskMapper flwTaskMapper;
    @Autowired
    private TTenantService tenantService;
    @ApiOperation(value = "获取合同分页列表")
    @PostMapping(value = "/contractList")
@@ -93,12 +121,23 @@
    @PreAuthorize("@ss.hasPermi('contract:list:add')")
    public R<Boolean> addContract(@Validated @RequestBody TContractDTO dto) {
        LocalDateTime changeTime = dto.getChangeTime();
        long count = contractService.count(new LambdaQueryWrapper<TContract>().eq(TContract::getContractNumber, dto.getContractNumber()));
        long count = contractService.count(new LambdaQueryWrapper<TContract>()
                .eq(TContract::getContractNumber, dto.getContractNumber()));
        if (count!=0){
            return R.fail("合同编号不可重复");
        }
        dto.setChangeRent(dto.getMonthRent());
        dto.setChangeTime(null);
        //查询房产信息,获取所属营业部
        THouse house = houseService.getById(dto.getHouseId());
        if (Objects.isNull(house)) {
            throw new ServiceException("房产信息不存在");
        }
        house.setRentalReturnStatus("1");
        houseService.updateById(house);
        dto.setBusinessDeptId(house.getBusinessDeptId());
        // 生成合同编号
        dto.setContractNumber(CodeGenerateUtils.generateVolumeSn(house.getBusinessDeptId()));
        contractService.save(dto);
        if (dto.getStatus().equals("2")){
            //发起合同新增审批
@@ -126,7 +165,13 @@
                            new ImmutableMap.Builder<String, Long>().
                                    put("id", flwTask.getId())
                                    .build();
                    QuartzManager.addJob(StateProcessJob.class, (StateProcessJob.name+flwTask.getId()).toUpperCase(), TimeJobType.AUTO_AUDIT,new Date(new Date().getTime()+48*60*60*1000L), maps);
                    QuartzManager.addJob(
                            StateProcessJob.class,
                            (StateProcessJob.name+flwTask.getId()).toUpperCase(),
                            TimeJobType.AUTO_AUDIT,
                            new Date(new Date().getTime()+48*60*60*1000L),
                            maps
                    );
                }
            }
        }
@@ -148,6 +193,12 @@
    @PreAuthorize("@ss.hasPermi('contract:list:edit')")
    public R<Boolean> updateContract(@Validated @RequestBody TContractDTO dto) {
        dto.setChangeTime(null);
        //查询房产信息,获取所属营业部
        THouse house = houseService.getById(dto.getHouseId());
        if (Objects.isNull(house)) {
            throw new ServiceException("房产信息不存在");
        }
        dto.setBusinessDeptId(house.getBusinessDeptId());
        contractService.updateById(dto);
        contractRentTypeService.remove(new LambdaQueryWrapper<TContractRentType>()
                .eq(TContractRentType::getContractId,dto.getId()));
@@ -187,7 +238,13 @@
                            new ImmutableMap.Builder<String, Long>().
                                    put("id", flwTask.getId())
                                    .build();
                    QuartzManager.addJob(StateProcessJob.class, (StateProcessJob.name+flwTask.getId()).toUpperCase(), TimeJobType.AUTO_AUDIT,new Date(new Date().getTime()+48*60*60*1000L), maps);
                    QuartzManager.addJob(
                            StateProcessJob.class,
                            (StateProcessJob.name + flwTask.getId()).toUpperCase(),
                            TimeJobType.AUTO_AUDIT,
                            new Date(new Date().getTime() + 48 * 60 * 60 * 1000L),
                            maps
                    );
                }
            }
        }
@@ -211,7 +268,9 @@
        TContractVO res = new TContractVO();
        TContract contract = contractService.getById(id);
        BeanUtils.copyProperties(contract,res);
        TContractRentType contractRentType = contractRentTypeService.lambdaQuery().eq(TContractRentType::getContractId, id).one();
        TContractRentType contractRentType = contractRentTypeService.lambdaQuery()
                .eq(TContractRentType::getContractId, id)
                .one();
        if (contractRentType!=null){
            BeanUtils.copyProperties(contractRentType,res);
        }
@@ -231,8 +290,15 @@
        for (TBill tBill : list) {
            payMoney = payMoney.add(tBill.getOutstandingMoney()).add(tBill.getPayableFeesPenalty());
        }
        TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery().eq(TCheckAcceptRecord::getContractId, id).one();
        res.setCheckResult(Objects.nonNull(tCheckAcceptRecord)&&Objects.nonNull(tCheckAcceptRecord.getCheckResult())?tCheckAcceptRecord.getCheckResult():null);
        TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery()
                .eq(TCheckAcceptRecord::getContractId, id)
                .one();
        res.setCheckResult(
                Objects.nonNull(tCheckAcceptRecord)
                        &&Objects.nonNull(tCheckAcceptRecord.getCheckResult())
                        ?tCheckAcceptRecord.getCheckResult()
                        :null
        );
        res.setPayMoney(payMoney);
        return R.ok(res);
@@ -254,7 +320,6 @@
    @Log(title = "合同管理-确认结算", businessType =  BusinessType.UPDATE)
    @ApiOperation(value = "确认结算")
    @PostMapping(value = "/confirmSettlement")
    public R<Boolean> confirmSettlement(String id) {
        TContract contract = contractService.getById(id);
        contract.setStatus("8");
@@ -262,11 +327,17 @@
        // 将所有未缴费账单设置未已失效
        List<TBill> tBills = billService.list(new LambdaQueryWrapper<TBill>()
                .ne(TBill::getPayFeesStatus, 3)
                        .ne(TBill::getBillType,4)
                .eq(TBill::getContractId, contract.getId()));
        for (TBill tBill : tBills) {
            tBill.setPayFeesStatus("5");
        }
        billService.updateBatchById(tBills);        return R.ok();
        billService.updateBatchById(tBills);
        // 将房屋改成待出租
        THouse house = houseService.getById(contract.getHouseId());
        house.setLeaseStatus("1");
        houseService.updateById(house);
        return R.ok();
    }
    @ApiOperation(value = "终止合同剩余未缴费账单列表")
    @PostMapping(value = "/contractBillList")
@@ -295,55 +366,432 @@
        List<TContract> list = contractService.lambdaQuery().in(TContract::getId, dto.getIds()).list();
        List<String> res = new ArrayList<>();
        for (TContract contract : list) {
            TBill firstBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId())
                    .orderByDesc(TBill::getStartTime).last("limit 1").one();
            THouse tHouse = houseService.getById(contract.getHouseId());
            Map<String, Object> templateParam = new HashMap<>(5);
            templateParam.put("${partyOneName}", contract.getPartyOneName());
            templateParam.put("${partyTwoName}", contract.getPartyTwoName());
            templateParam.put("${houseAddress}", tHouse.getHouseAddress());
            templateParam.put("${houseArea}", tHouse.getHouseArea()+"m²");
            long between = ChronoUnit.DAYS.between(contract.getStartTime(), contract.getStartPayTime())+1;
            templateParam.put("${day}", between);
            templateParam.put("${endTimeFree}", DateUtils.localDateTimeToStringYear(contract.getStartPayTime().plusDays(1)));
            templateParam.put("${startPayTime}", DateUtils.localDateTimeToStringYear(contract.getStartPayTime()));
            templateParam.put("${startTime}", DateUtils.localDateTimeToStringYear(contract.getStartTime()));
            templateParam.put("${endTime}", DateUtils.localDateTimeToStringYear(contract.getEndTime()));
            templateParam.put("${monthRent}", "¥"+contract.getMonthRent()+"元");
            templateParam.put("${monthRentString}", "人民币"+NumberToChineseUtils.numberToChinese(contract.getMonthRent().setScale(2, BigDecimal.ROUND_DOWN).doubleValue()));
            String totalYear = Objects.nonNull(contract.getTotalYear())?contract.getTotalYear().toString():"";
            templateParam.put("${totalYear}", "¥"+totalYear+"元");
            String totalYearString = StringUtils.isNotEmpty(totalYear)?NumberToChineseUtils.numberToChinese(contract.getTotalYear().setScale(2, BigDecimal.ROUND_DOWN).doubleValue()):"";
            templateParam.put("${totalYearString}", "人民币"+totalYearString);
            templateParam.put("${payType}", contract.getPayType().equals("1")?"月":contract.getPayType().equals("2")?"季":"年");
            if(firstBill!=null){
                templateParam.put("${firstRent}", "¥"+(firstBill.getPayableFeesMoney())+"元");
            }else{
                templateParam.put("${firstRent}", "");
            }
            templateParam.put("${firstRentString}", "人民币"+NumberToChineseUtils.numberToChinese((contract.getPayType().equals("1")?contract.getMonthRent():contract.getPayType().equals("2")?contract.getMonthRent().multiply(new BigDecimal("3")):contract.getMonthRent().multiply(new BigDecimal("12")).setScale(2,BigDecimal.ROUND_DOWN)).doubleValue()));
            templateParam.put("${nextPayTime}", contract.getPayType().equals("1")?"月":contract.getPayType().equals("2")?"季":"年");
            templateParam.put("${deposit}", "¥"+contract.getDeposit()+"元");
            templateParam.put("${depositString}", NumberToChineseUtils.numberToChinese(contract.getDeposit().setScale(2, BigDecimal.ROUND_DOWN).doubleValue()));
            templateParam.put("${partyOnePerson}", contract.getPartyOnePerson());
            templateParam.put("${partyOnePhone}", contract.getPartyOnePhone());
            templateParam.put("${partyTwoPerson}", contract.getPartyTwoPerson());
            templateParam.put("${partyTwoPhone}", contract.getPartyTwoPhone());
            // 验收时间
            TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery().eq(TCheckAcceptRecord::getContractId, contract.getId()).last("limit 1").one();
            if (tCheckAcceptRecord!=null &&tCheckAcceptRecord.getCheckTime()!=null ){
                templateParam.put("${checkTime}", DateUtils.localDateTimeToStringYear(tCheckAcceptRecord.getCheckTime()));
            }else{
                templateParam.put("${checkTime}", "");
            }
            String url = wordUtil.generatePdf("/usr/local/project/file/", "1_yzj_租赁合同.docx", templateParam, "租赁合同", "/usr/local/project/file/");
            String url = generateContract(contract,new TContractDTO());
            res.add(url);
        }
        return R.ok(res);
    }
    // 计算两个日期相差天数的方法实现:
    public static long calculateDaysBetween(LocalDateTime start, LocalDateTime end) {
        return ChronoUnit.DAYS.between(start, end);
    }
    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2024, 1, 1, 0, 0);
        LocalDateTime end = LocalDateTime.of(2024, 1, 5, 12, 0);
        long days = calculateDaysBetween(start, end); // 返回4天(不满一天不计)
    }
    private String generateContract(TContract contract,TContractDTO dto) {
        String templateFileName = "1_yzj_租赁合同_个人.docx";
        String contractId = contract.getId();
        TBill firstBill = null;
        TCheckAcceptRecord tCheckAcceptRecord = null;
        if (StringUtils.isNotEmpty(contractId)) {
            firstBill = billService.lambdaQuery()
                    .eq(TBill::getContractId, contractId)
                    .eq(TBill::getBillType, 1)
                    .orderByAsc(TBill::getStartTime)
                    .ne(TBill::getManualAddition, DisabledEnum.YES.getCode())
                    .last("limit 1")
                    .one();
            tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery()
                    .eq(TCheckAcceptRecord::getContractId, contractId)
                    .last("limit 1")
                    .one();
        }
        TTenant tenant = null;
        THouse tHouse = null;
        if (StringUtils.isNotEmpty(contract.getTenantId())) {
            tenant = tenantService.getById(contract.getTenantId());
            tHouse = houseService.getById(contract.getHouseId());
        }
        Map<String, Object> templateParam = new HashMap<>(5);
        fill(templateParam, "contractNumber", contract.getContractNumber());
        fill(templateParam, "partyOneName", contract.getPartyOneName());
        if (Objects.nonNull(tenant)) {
            fill(templateParam, "mailAddress", tenant.getMailAddress());
            fill(templateParam, "idCard", tenant.getIdCard());
            fill(templateParam, "residentName", tenant.getResidentName());
            fill(templateParam, "bankNumber", tenant.getBankNumber());
            fill(templateParam, "bankName", tenant.getBankName());
            fill(templateParam, "partyTwoName", tenant.getLessee());
            fill(templateParam, "email", tenant.getEmail());
            // 企业、政府机构、国有企业
            if (Objects.nonNull(tenant.getTenantAttributes())
                    && (tenant.getTenantAttributes().equals("2")
                    || tenant.getTenantAttributes().equals("5")
                    || tenant.getTenantAttributes().equals("7"))) {
                fill(templateParam, "creditCode", tenant.getCreditCode());
                fill(templateParam, "legalPerson", tenant.getLegalPerson());
                templateFileName = "1_yzj_租赁合同_企业.docx";
            }
        }
        if (Objects.nonNull(tHouse)) {
            fill(templateParam, "houseAddress", tHouse.getHouseAddress());
            fill(templateParam, "houseArea", tHouse.getHouseArea() + "m²");
        }
        // 日期相关参数处理
        fill(templateParam, "remark", contract.getRemark());
        fill(templateParam, "houseUseScope", StringUtils.isNotEmpty(contract.getHouseUseScope()) ? contract.getHouseUseScope() : "————");
        fill(templateParam, "days", ChronoUnit.DAYS.between(
                contract.getStartTime(), contract.getEndTime()));
        long between = ChronoUnit.DAYS.between(
                contract.getStartTime(), contract.getStartPayTime()) + 1;
        fill(templateParam, "day", between);
        // 财务相关参数处理
        fill(templateParam, "endTimeFree", DateUtils.localDateTimeToStringYear(
                contract.getStartPayTime().plusDays(1)));
        fill(templateParam, "startPayTime", DateUtils.localDateTimeToStringYear(
                contract.getStartPayTime()));
        fill(templateParam, "startTime", DateUtils.localDateTimeToStringYear(
                contract.getStartTime()));
        fill(templateParam, "endTime", DateUtils.localDateTimeToStringYear(
                contract.getEndTime()));
        // 金额格式化处理
        fill(templateParam, "monthRent", "¥" + contract.getMonthRent() + "元");
        fill(templateParam, "monthRentString", "人民币" + NumberToChineseUtils.numberToChinese(
                contract.getMonthRent().setScale(2, RoundingMode.DOWN).doubleValue()));
        String totalYear = Objects.nonNull(contract.getTotalYear())
                ? contract.getTotalYear().toString()
                : "";
        fill(templateParam, "totalYear", "¥" + totalYear + "元");
        String totalYearString = StringUtils.isNotEmpty(totalYear)
                ? NumberToChineseUtils.numberToChinese(
                contract.getTotalYear().setScale(2, RoundingMode.DOWN).doubleValue())
                : "";
        fill(templateParam, "totalYearString", "人民币" + totalYearString);
        // 支付类型处理
        String payType = contract.getPayType().equals("1") ? "月"
                : contract.getPayType().equals("2") ? "季"
                : "年";
        fill(templateParam, "payType", payType);
        BigDecimal extracted = extracted(contract,dto);
        System.out.println("金额========================="+extracted);
        fill(templateParam, "firstRent", "¥" + extracted + "元");
        // 其他财务字段
        fill(templateParam, "firstRentString", "人民币" + NumberToChineseUtils.numberToChinese(extracted.doubleValue()));
//        fill(templateParam, "firstRent",
//                "¥"+(contract.getPayType().equals("1")
//                        ? contract.getMonthRent()
//                        :contract.getPayType().equals("2")
//                        ?contract.getMonthRent().multiply(new BigDecimal("3"))
//                        :contract.getMonthRent().multiply(new BigDecimal("12"))
//                        .setScale(2, RoundingMode.DOWN)).doubleValue()+"元");
//
//
//        fill(templateParam, "firstRentString",
//                "人民币"+NumberToChineseUtils.numberToChinese(
//                        (contract.getPayType().equals("1")
//                                ? contract.getMonthRent()
//                                :contract.getPayType().equals("2")
//                                ?contract.getMonthRent().multiply(new BigDecimal("3"))
//                                :contract.getMonthRent().multiply(new BigDecimal("12"))
//                                .setScale(2, RoundingMode.DOWN)).doubleValue()));
        fill(templateParam, "nextPayTime", payType);
        fill(templateParam, "deposit", "¥" + contract.getDeposit() + "元");
        fill(templateParam, "depositString", NumberToChineseUtils.numberToChinese(
                contract.getDeposit().setScale(2, RoundingMode.DOWN).doubleValue()));
        // 联系方式
        fill(templateParam, "partyOnePerson", contract.getPartyOnePerson());
        fill(templateParam, "partyOnePhone", contract.getPartyOnePhone());
        fill(templateParam, "partyTwoPerson", contract.getPartyTwoPerson());
        fill(templateParam, "partyTwoPhone", contract.getPartyTwoPhone());
        // 验收时间处理
        if (tCheckAcceptRecord != null && tCheckAcceptRecord.getCheckTime() != null) {
            fill(templateParam, "checkTime", DateUtils.localDateTimeToStringYear(
                    tCheckAcceptRecord.getCheckTime()));
        } else {
            fill(templateParam, "checkTime", "");
        }
        return wordUtil.generatePdf(
                "/usr/local/project/file/",
                templateFileName,
                templateParam,
                "租赁合同",
                "/usr/local/project/file/");
    }
    private BigDecimal extracted(TContract contract,TContractDTO dto) {
        TContractRentType tContractRentType = null;
        if (contract.getIsIncreasing()){
            tContractRentType = new TContractRentType();
            tContractRentType.setContractId(contract.getId());
            tContractRentType.setIncreasingDecreasing(dto.getIncreasingDecreasing());
            tContractRentType.setIncreasingDecreasingType(dto.getIncreasingDecreasingType());
            tContractRentType.setNumericalValue(dto.getNumericalValue());
            tContractRentType.setChangeTime(dto.getChangeTime());
            tContractRentType.setCycleTime(dto.getCycleTime());
        }
        // 生成第一笔账单
        // 第一次应缴费日期
        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());
        if (contract.getPayType().equals("2")) {
            // 季付 取3 6 9 12
            int temp = 0 ;
            if (contract.getStartPayTime().getMonthValue() <= 3 ) {
                temp = 3;
            } else if (contract.getStartPayTime().getMonthValue() <= 6) {
                temp = 6;
            } else if (contract.getStartPayTime().getMonthValue() <= 9) {
                temp = 9;
            } else {
                temp = 12;
            }
            if (contract.getEndTime().isAfter(contract.getStartPayTime().withMonth(temp).with(TemporalAdjusters.lastDayOfMonth()))){
                rentBill.setEndTime(contract.getStartPayTime().withMonth(temp).with(TemporalAdjusters.lastDayOfMonth()));
            }else {
                rentBill.setEndTime(contract.getEndTime());
            }
        } else if (contract.getPayType().equals("3")) {
            if (contract.getEndTime().isAfter(contract.getStartPayTime().withMonth(12).with(TemporalAdjusters.lastDayOfMonth()))){
                rentBill.setEndTime(contract.getStartPayTime().withMonth(12).with(TemporalAdjusters.lastDayOfMonth()));
            }else {
                rentBill.setEndTime(contract.getEndTime());
            }
        } else {
            rentBill.setEndTime(rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()));
        }
        if (tContractRentType != null && rentBill.getEndTime().isAfter(tContractRentType.getChangeTime())){
            long moneyDays = 0;
            if (tContractRentType.getChangeTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(rentBill.getEndTime())){
                moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), tContractRentType.getChangeTime().with(TemporalAdjusters.lastDayOfMonth())) + 1;
            }else{
                moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(),rentBill.getEndTime()) + 1;
            }
            // 计算租金变动的天数
            contract.setChangeTime(tContractRentType.getChangeTime());
            // 递增递减的租金
            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)).setScale(2, BigDecimal.ROUND_DOWN));
                            // 变动后的每月租金
                            contract.setChangeRent(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN));
                            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)).setScale(2, BigDecimal.ROUND_DOWN));
                            contract.setChangeRent(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN));
                            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)).setScale(2, BigDecimal.ROUND_DOWN);
                            contract.setChangeRent(contract.getChangeRent().add(tContractRentType.getNumericalValue()));
                            break;
                        case 2:
                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).setScale(2, BigDecimal.ROUND_DOWN);
                            contract.setChangeRent(contract.getChangeRent().subtract(tContractRentType.getNumericalValue()));
                            break;
                    }
                    break;
            }
            LocalDateTime localDateTime = tContractRentType.getChangeTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
            while(true){
                if (localDateTime.isBefore(rentBill.getEndTime())){
                    if (localDateTime.plusMonths(1).isBefore(rentBill.getEndTime())){
                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent());
                        localDateTime = localDateTime.plusMonths(1);
                    }else {
                        break;
                    }
                }else{
                    break;
                }
            }
            long temp  = ChronoUnit.DAYS.between(localDateTime,rentBill.getEndTime()) + 1;
            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(temp)));
            // 不需要涨租金的时间段
            long originalDays = 0;
            if (contract.getFirstPayTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(tContractRentType.getChangeTime())){
                originalDays = Math.abs(ChronoUnit.DAYS.between(contract.getFirstPayTime(), contract.getFirstPayTime().with(TemporalAdjusters.lastDayOfMonth())));
            }else{
                originalDays = Math.abs(ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime()));
            }
            originalMoney = originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(originalDays)));
            LocalDateTime originalTime = contract.getFirstPayTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
            while(true){
                if (originalTime.isBefore(tContractRentType.getChangeTime())){
                    if (originalTime.plusMonths(1).isBefore(tContractRentType.getChangeTime())){
                        originalMoney = originalMoney.add(contract.getMonthRent());
                        originalTime = originalTime.plusMonths(1);
                    }else {
                        break;
                    }
                }else{
                    break;
                }
            }
            long tempOriginal  = ChronoUnit.DAYS.between(localDateTime,tContractRentType.getChangeTime()) ;
            originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(tempOriginal)));
            rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
            rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
        } else {
            // 不走递增递减
            if (contract.getPayType().equals("2")){
                BigDecimal money = new BigDecimal("0");
                // 第一个月计算天
                int dayOfMonth = rentBill.getStartTime().getDayOfMonth();
                if (dayOfMonth == 1) {
                    System.err.println("第一笔账单 1号计算整月:");
                    money = money.add(contract.getMonthRent());
                } else {
                    long allDays = Math.abs(ChronoUnit.DAYS.between(rentBill.getStartTime(), rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())) + 1);
                    System.err.println("第一笔账单 计算天数"+allDays);
                    money =money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
                    System.err.println("第一笔账单 计算天数金额"+money);
                }
                // 后续
                if (contract.getStartPayTime().getMonthValue()==3|| contract.getStartPayTime().getMonthValue()==6|| contract.getStartPayTime().getMonthValue()==9|| contract.getStartPayTime().getMonthValue()==12){
                    System.err.println("后续账单 月为3 6 9 12金额"+money);
                    rentBill.setPayableFeesMoney(money);
                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                }else{
                    LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                    System.err.println("后续账单逻辑时间"+localDateTime);
                    while (true){
                        if (localDateTime.toLocalDate().isBefore(rentBill.getEndTime().toLocalDate())){
                            System.err.println("后续while 在结束之前");
                            money = money.add(contract.getMonthRent());
                        }else if(localDateTime.toLocalDate().equals(rentBill.getEndTime().toLocalDate())){
                            System.err.println("后续while 结束");
                            money = money.add(contract.getMonthRent());
                            break;
                        }else {
                            System.err.println("后续while 加一个月大于结束时间");
                            if (localDateTime.with(TemporalAdjusters.firstDayOfMonth()).isBefore(rentBill.getEndTime())){
                                long a = ChronoUnit.DAYS.between(localDateTime.with(TemporalAdjusters.firstDayOfMonth()),rentBill.getEndTime())+1;
                                System.err.println("后续while 加一个月大于结束时间 计算天数"+a);
                                money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(
                                        new BigDecimal(ChronoUnit.DAYS.between(localDateTime.with(TemporalAdjusters.firstDayOfMonth()),rentBill.getEndTime())+1))
                                );
                            }
                            break;
                        }
                        localDateTime = localDateTime.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                    }
                    rentBill.setPayableFeesMoney(money);
                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                }
            }else if (contract.getPayType().equals("3")){
                BigDecimal money = new BigDecimal("0");
                // 第一个月计算天
                int dayOfMonth = rentBill.getStartTime().getDayOfMonth();
                if (dayOfMonth == 1) {
                    money = money.add(contract.getMonthRent());
                } else {
                    long allDays = ChronoUnit.DAYS.between(rentBill.getStartTime(), rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())) ;
                    money =money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
                }
                // 后续
                if (contract.getStartPayTime().getMonthValue()==12){
                    rentBill.setPayableFeesMoney(money);
                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                }else{
//                                LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                    LocalDateTime localDateTime = rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
                    while (true){
                        if (localDateTime.isBefore(rentBill.getEndTime())){
                            localDateTime = localDateTime.plusMonths(1);
                            money = money.add(contract.getMonthRent());
                        }else{
                            money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth())))));
                            break;
                        }
                    }
                    rentBill.setPayableFeesMoney(money);
                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                }
            }else {
                long allDays = ChronoUnit.DAYS.between(contract.getStartPayTime(), rentBill.getEndTime()) + 1;
                int dayOfMonth = rentBill.getStartTime().getDayOfMonth();
                if (dayOfMonth == 1) {
                    rentBill.setPayableFeesMoney(contract.getMonthRent());
                } else {
                    rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
                }
                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
            }
        }
        // 押金账单
        TBill depositBill = new TBill();
        depositBill.setContractId(contract.getId());
        depositBill.setContractNumber(contract.getContractNumber());
        depositBill.setPayableFeesMoney(contract.getDeposit());
        depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney());
        depositBill.setStartTime(contract.getStartPayTime());
        depositBill.setEndTime(contract.getEndTime());
        depositBill.setPayableFeesTime(firstPayTime.toLocalDate());
        depositBill.setPayFeesStatus("1");
        depositBill.setBillType("2");
        rentBill.setBusinessDeptId(contract.getBusinessDeptId());
        depositBill.setBusinessDeptId(contract.getBusinessDeptId());
        return rentBill.getPayableFeesMoney() ;
    }
    private void fill(Map<String, Object> templateParam, String key, Object value) {
        if (StringUtils.isEmpty(key)){
            throw new RuntimeException("key不能为空");
        }
        templateParam.put("${"+key+"}", value != null ? value : "");
    }
    /**
     * 生成预览版合同附件
     */
    @ApiOperation(value = "生成预览版合同附件")
    @PostMapping("/generateContractPreview")
    public R<String> generateContractPreview(@RequestBody TContractDTO dto)
    {
        TContract contract = new TContract();
        BeanUtil.copyProperties(dto,contract);
        return R.ok(generateContract(contract,dto));
    }
    /**
@@ -353,10 +801,10 @@
    @PreAuthorize("@ss.hasPermi('contract:list:export')")
    @Log(title = "导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void exportOpticalInspection(@RequestBody TContractQuery query)
    {
    public void exportOpticalInspection(@RequestBody TContractQuery query) throws UnsupportedEncodingException {
        List<ContractExport> contractExports = new ArrayList<>();
        List<TContract> exportList = contractService.contractExportList(query);
        for (TContract contract : exportList) {
            ContractExport contractExport = new ContractExport();
            contractExport.setContractNumber(contract.getContractNumber());
@@ -366,33 +814,61 @@
            contractExport.setCreateTime(DateUtils.localDateTimeToStringYear(contract.getCreateTime()));
            contractExport.setStartTime(DateUtils.localDateTimeToStringYear(contract.getStartTime()));
            contractExport.setEndTime(DateUtils.localDateTimeToStringYear(contract.getEndTime()));
            contractExport.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE,contract.getPayType()));
            contractExport.setDeposit(contract.getDeposit()+"");
            contractExport.setStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_STATUS,contract.getStatus()));
            contractExport.setDeposit(contract.getDeposit() + "");
            contractExports.add(contractExport);
            contractExport.setPayType(
                    DictUtils.getDictLabel(
                            DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE, contract.getPayType())
            );
            contractExport.setStatus(
                    DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_STATUS, contract.getStatus()));
        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), ContractExport.class, contractExports);
        HttpServletResponse response = WebUtils.response();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("合同列表.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
        response.setHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode("合同列表.xls", "utf-8"));
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        try (Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), ContractExport.class, contractExports);
             ServletOutputStream outputStream = response.getOutputStream()) {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @ApiOperation("上传合同附件")
    @PostMapping(value = "/upload-file")
    public R<Boolean> uploadFile(@RequestBody TContractDTO dto ) {
        if (Objects.isNull(dto.getId())) {
            throw new ServiceException("合同id不能为空");
        }
        TContract contract = contractService.getById(dto.getId());
        if (Objects.isNull(contract)) {
            throw new ServiceException("合同不存在");
        }
  /*      if (StringUtils.isNotBlank(contract.getContractFile())) {
            List<String> contractFileList = Arrays.stream(contract.getContractFile().split(",")).collect(Collectors.toList());
            List<String> memoryList = Arrays.stream(contract.getMemory().split(",")).collect(Collectors.toList());
            List<String> contractNameList = Arrays.stream(contract.getContractFileName().split(",")).collect(Collectors.toList());
            contractFileList.addAll(Arrays.asList(dto.getContractFile().split(",")));
            contractNameList.addAll(Arrays.asList(dto.getContractFileName().split(",")));
            memoryList.addAll(Arrays.asList(dto.getMemory().split(",")));
            contract.setContractFile(String.join(",", contractFileList));
            contract.setContractFileName(String.join(",", contractNameList));
            contract.setMemory(String.join(",", memoryList));
        } else {
            contract.setContractFile(dto.getContractFile());
            contract.setContractFileName(dto.getContractFileName());
            contract.setMemory(dto.getMemory());
        }*/
        contract.setContractFile(dto.getContractFile());
        contract.setContractFileName(dto.getContractFileName());
        contract.setMemory(dto.getMemory());
        return R.ok(contractService.updateById(contract));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java
@@ -51,7 +51,7 @@
    /**
     * 获取部门管理管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:department:list')")
    @PreAuthorize("@ss.hasPermi('system:department')")
    @ApiOperation(value = "获取部门管理分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<DeptVO>> pageList(@RequestBody TDeptQuery query) {
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java
@@ -46,7 +46,7 @@
    /**
     * 获取故障区域管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:faultArea:list')")
    @PreAuthorize("@ss.hasPermi('system:faultArea')")
    @ApiOperation(value = "获取故障区域分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TFaultAreaDic>> pageList(@RequestBody TFaultAreaDicQuery query) {
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java
@@ -42,7 +42,7 @@
    /**
     * 获取故障描述管理列表
     */
    @PreAuthorize("@ss.hasPermi('system:tag:list')")
    @PreAuthorize("@ss.hasPermi('system:tag')")
    @ApiOperation(value = "获取故障描述分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TFaultDescribeDicVO>> pageList(@RequestBody TFaultDescribeDicQuery query) {
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
@@ -41,7 +41,7 @@
    /**
     * 获取报修管理列表
     */
    @PreAuthorize("@ss.hasPermi('houseManage:acceptance:list')")
    @PreAuthorize("@ss.hasPermi('houseManage:acceptance')")
    @ApiOperation(value = "获取报修分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TFaultRepairMessageVO>> pageList(@RequestBody TFaultRepairMessageQuery query) {
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFlowManagementController.java
@@ -3,6 +3,7 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.model.TFlowManagement;
import com.ruoyi.system.query.TFlowManagementQuery;
import com.ruoyi.system.service.TFlowManagementService;
@@ -36,6 +37,7 @@
    @ApiOperation(value = "获取流水列表")
    @PostMapping("/list")
    public R<PageInfo<TFlowManagement>> list(@RequestBody TFlowManagementQuery query) {
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        return R.ok(flowService.pageList(query));
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/THouseController.java
@@ -1,6 +1,7 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
@@ -77,7 +78,7 @@
    @ApiOperation(value = "获取房屋分页列表")
    @PostMapping(value = "/houseList")
    @PreAuthorize("@ss.hasPermi('house:list')")
    public R<PageInfo<THouse>> houseList(@RequestBody THouseQuery query) {
    public R<IPage<THouse>> houseList(@RequestBody THouseQuery query) {
        return R.ok(tHouseService.houseList(query));
    }
    @ApiOperation(value = "历史租户列表")
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInvoiceController.java
@@ -5,6 +5,7 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.TencentMailUtil;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.model.TBill;
@@ -12,10 +13,16 @@
import com.ruoyi.system.query.TInvoiceQuery;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TInvoiceService;
import com.ruoyi.web.controller.tool.TencentCosUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
/**
@@ -33,10 +40,13 @@
    private TInvoiceService invoiceService;
    @Autowired
    TBillService tBillService;
    @Autowired
    TencentCosUtil tencentCosUtil;
    @PreAuthorize("@ss.hasPermi('invoice:list')")
    @ApiOperation(value = "获取开票列表")
    @PostMapping("/list")
    public R<PageInfo<TInvoice>> list(@RequestBody TInvoiceQuery query) {
        query.setBusinessDeptId(SecurityUtils.getBusinessDeptId());
        return R.ok(invoiceService.pageList(query));
    }
@@ -58,7 +68,51 @@
    @PostMapping("/uploadVoucher")
    @PreAuthorize("@ss.hasPermi('invoice:list:payment')")
    public R<Boolean> uploadVoucher(@RequestBody TInvoiceQuery query) {
        return R.ok(invoiceService.uploadVoucher(query));
        String invoiceVoucher = query.getInvoiceVoucher();
        String invoiceVoucherName = query.getInvoiceVoucherName();
        if (invoiceVoucher == null || invoiceVoucherName == null) {
            return R.fail("请上传发票文件");
        }
        String[] voucherUrls = invoiceVoucher.split(",");
        String[] voucherNames = invoiceVoucherName.split(",");
        // 确保两个数组长度一致
        int length = Math.min(voucherUrls.length, voucherNames.length);
        if (length == 0) {
            return R.fail("请上传发票文件");
        }
        // 构建附件列表
        List<Map<String, String>> attachments = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            String voucherUrl = voucherUrls[i];
            String fileName = voucherNames[i];
            Map<String, String> attachment = new HashMap<>(2); // 初始容量为2,避免扩容
            String tempDir = System.getProperty("java.io.tmpdir");
            Path filePath = Paths.get(tempDir, "invoice");
            // 保存到临时目录
            tencentCosUtil.download(voucherUrl,filePath.toString(),fileName);
            attachment.put("filePath", filePath.toString());
            attachment.put("fileName", fileName);
            attachments.add(attachment);
        }
        return R.ok(invoiceService.uploadVoucher(query,attachments));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TRentalReturnRecordController.java
New file
@@ -0,0 +1,79 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.model.TRentalReturnRecord;
import com.ruoyi.system.query.RentalReturnAuditQuery;
import com.ruoyi.system.query.RentalReturnRecordQuery;
import com.ruoyi.system.service.ITRentalReturnRecordService;
import com.ruoyi.system.vo.RentalReturnRecordVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/rentalReturnRecord")
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@Api(tags = {"房屋管理-退租申请"})
public class TRentalReturnRecordController extends BaseController {
    private final ITRentalReturnRecordService rentalReturnRecordService;
    /**
     * 申请记录列表
     */
    @ApiOperation(value = "申请记录列表")
    @GetMapping("list")
    @PreAuthorize("@ss.hasPermi('houseManage:apply:list')")
    public R<IPage<RentalReturnRecordVO>> list(Page<RentalReturnRecordVO> page, RentalReturnRecordQuery query) {
        return R.ok(rentalReturnRecordService.queryRentalReturnRecordList(page, query));
    }
    /**
     * 审核记录删除
     */
    @ApiOperation(value = "审核记录删除")
    @GetMapping("delete")
    @PreAuthorize("@ss.hasPermi('houseManage:apply:delete')")
    public R<String> delete(@ApiParam (value = "id") String id) {
        boolean remove = rentalReturnRecordService.update(new LambdaUpdateWrapper<TRentalReturnRecord>()
                .set(TRentalReturnRecord::getIsAdminDelete, true)
                .eq(TRentalReturnRecord::getId, id)
                .ne(TRentalReturnRecord::getAuditStatus, 1));
        if (!remove){
            return R.fail("删除失败");
        }
        return R.ok("删除成功");
    }
    /**
     * 申请记录详情
     */
    @ApiOperation(value = "申请记录详情")
    @GetMapping("detail")
    @PreAuthorize("@ss.hasPermi('houseManage:apply:detail')")
    public R<RentalReturnRecordVO> detail(@ApiParam (value = "id") String id) {
        RentalReturnRecordVO rentalReturnRecordVO = rentalReturnRecordService.queryRentalReturnRecordById(id);
        return R.ok(rentalReturnRecordVO);
    }
    /**
     * 申请审核
     */
    @ApiOperation(value = "申请审核")
    @PostMapping("audit")
    @PreAuthorize("@ss.hasPermi('houseManage:apply:audit')")
    public R<String> audit(@RequestBody RentalReturnAuditQuery returnAuditQuery) {
        rentalReturnRecordService.audit(returnAuditQuery, getUserId(), getUsername());
        return R.ok("审核成功");
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TStreetController.java
New file
@@ -0,0 +1,50 @@
package com.ruoyi.web.controller.api;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.model.TStreet;
import com.ruoyi.system.service.ITStreetService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
 * 街道 前端控制器
 * </p>
 *
 * @author mitao
 * @since 2025-03-19
 */
@Api(tags = {"街道相关接口"})
@RestController
@RequestMapping("/t-street")
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class TStreetController {
    private final ITStreetService tStreetService;
    @GetMapping("/list")
    @ApiOperation(value = "获取街道列表")
    public R<List<TStreet>> list() {
        return R.ok(tStreetService.list());
    }
    @GetMapping("/init")
    @ApiOperation(value = "初始化街道列表")
    public R<?> init(){
        ArrayList<String> strings = Lists.newArrayList("八廓街道", "吉日街道", "布达拉宫广场街道", "公德林街道", "扎细街道", "纳金街道", "娘热街道", "金珠西路街道", "堆龙德庆区东嘎街道", "两岛街道", "柳梧新区柳梧乡", "色拉街道", "蔡公堂街道", "娘热路街道", "夺底街道", "纳如街道");
        strings.forEach(streetName->{
            TStreet tStreet = new TStreet();
            tStreet.setStreetName(streetName);
            tStreetService.save(tStreet);
        });
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTenantController.java
@@ -115,7 +115,10 @@
    @ApiOperation(value = "获取合同分页列表")
    @GetMapping(value = "/contractListByTenantId")
    public R<List<TContract>> contractListByTenantId(@RequestParam String tenantId) {
        return R.ok(contractService.list(Wrappers.lambdaQuery(TContract.class).eq(TContract::getTenantId, tenantId)));
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        return R.ok(contractService.list(Wrappers.lambdaQuery(TContract.class)
                .eq(!businessDeptId.equals("0"), TContract::getBusinessDeptId, businessDeptId)
                .eq(TContract::getTenantId, tenantId)));
    }
    /**
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -62,7 +62,7 @@
    @Autowired
    private ISysMenuService menuService;
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @PreAuthorize("@ss.hasPermi('system:role')")
    @ApiOperation(value = "角色列表")
    @PostMapping("/list")
    public AjaxResult list(@RequestBody SysRoleQuery query)
@@ -71,7 +71,7 @@
        return AjaxResult.success(list);
    }
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @PreAuthorize("@ss.hasPermi('system:role')")
    @ApiOperation(value = "角色列表不分页")
    @PostMapping("/listNotPage")
    public AjaxResult list()
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -22,6 +22,7 @@
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -56,6 +57,7 @@
     */
    @ApiOperation(value = "获取用户列表")
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:user')")
    public AjaxResult list(@RequestBody SysUserQuery query)
    {
        PageInfo<SysUserVO> list = userService.pageList(query);
@@ -64,6 +66,8 @@
    @ApiOperation(value = "获取用户列表-不分页")
    @PostMapping("/listNotPage")
    @PreAuthorize("@ss.hasPermi('system:user')")
    public AjaxResult listNotPage()
    {
        List<SysUser> list = userService.selectList();
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java
@@ -27,6 +27,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
@@ -256,4 +261,29 @@
    }
    /**
     * 将文件下载到指定目录
     * @param fileUrl
     * @param saveDir
     * @param fileName
     * @throws IOException
     */
    public void download(String fileUrl, String saveDir, String fileName){
        fileUrl = fileUrl.replace(cosConfig.getRootSrc(), "");
        // 下载文件并获取输入流
        COSObject object = cosClient.getObject(cosConfig.getBucketName(),fileUrl);
        try (
                InputStream in = object.getObjectContent();
                ){
            Path targetPath = Paths.get(saveDir, fileName);
            // 确保目录存在
            Files.createDirectories(targetPath.getParent());
            // 将文件保存到目标路径
            Files.copy(in, targetPath, StandardCopyOption.REPLACE_EXISTING);
        }catch (IOException e){
            log.error("读取cos图片发生异常", e);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java
@@ -1,87 +1,87 @@
package com.ruoyi.web.controller.tool;
import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.*;
public class WordTemplateProcessor {
    public static void fillTemplate(String templatePath, String outputPath,Map<String, String> dataMap) {
        try {
            // 读取模板文件
            FileInputStream fis = new FileInputStream(templatePath);
            XWPFDocument document = new XWPFDocument(fis);
            // 替换段落中的标记
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                replaceParagraph(paragraph, dataMap);
            }
            // 替换表格中的标记
            for (XWPFTable table : document.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph paragraph : cell.getParagraphs()) {
                            replaceParagraph(paragraph, dataMap);
                        }
                    }
                }
            }
            // 保存文件
            FileOutputStream fos = new FileOutputStream(outputPath);
            document.write(fos);
            // 关闭资源
            fos.close();
            fis.close();
            document.close();
            System.out.println("模板填充完成!文件保存在: " + outputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void replaceParagraph(XWPFParagraph paragraph, Map<String, String> dataMap) {
        String paragraphText = paragraph.getText();
        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
            if (paragraphText.contains(entry.getKey())) {
                List<XWPFRun> runs = paragraph.getRuns();
                TextSegment found = paragraph.searchText(entry.getKey(), new PositionInParagraph());
                if (found != null) {
                    // 替换文本
                    int beginRun = found.getBeginRun();
                    int endRun = found.getEndRun();
                    if (beginRun >= 0 && endRun >= 0) {
                        // 删除原有runs
                        for (int runPos = beginRun; runPos <= endRun; runPos++) {
                            paragraph.removeRun(runPos);
                        }
                        // 创建新run
                        XWPFRun newRun = paragraph.insertNewRun(beginRun);
                        newRun.setText(entry.getValue());
                        // 复制原有格式
                        if (runs.size() > 0 && runs.get(0) != null) {
                            XWPFRun styleRun = runs.get(0);
                            newRun.setFontFamily(styleRun.getFontFamily());
                            newRun.setFontSize(styleRun.getFontSize());
                            newRun.setBold(styleRun.isBold());
                            newRun.setItalic(styleRun.isItalic());
                        }
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        String templatePath = "/path/to/template.docx";
        String outputPath = "/path/to/output.docx";
//        fillTemplate(templatePath, outputPath, user);
    }
}
//package com.ruoyi.web.controller.tool;
//
//import org.apache.poi.xwpf.usermodel.*;
//import java.io.*;
//import java.util.*;
//
//public class WordTemplateProcessor {
//
//    public static void fillTemplate(String templatePath, String outputPath,Map<String, String> dataMap) {
//        try {
//            // 读取模板文件
//            FileInputStream fis = new FileInputStream(templatePath);
//            XWPFDocument document = new XWPFDocument(fis);
//
//            // 替换段落中的标记
//            for (XWPFParagraph paragraph : document.getParagraphs()) {
//                replaceParagraph(paragraph, dataMap);
//            }
//
//            // 替换表格中的标记
//            for (XWPFTable table : document.getTables()) {
//                for (XWPFTableRow row : table.getRows()) {
//                    for (XWPFTableCell cell : row.getTableCells()) {
//                        for (XWPFParagraph paragraph : cell.getParagraphs()) {
//                            replaceParagraph(paragraph, dataMap);
//                        }
//                    }
//                }
//            }
//
//            // 保存文件
//            FileOutputStream fos = new FileOutputStream(outputPath);
//            document.write(fos);
//
//            // 关闭资源
//            fos.close();
//            fis.close();
//            document.close();
//
//            System.out.println("模板填充完成!文件保存在: " + outputPath);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    private static void replaceParagraph(XWPFParagraph paragraph, Map<String, String> dataMap) {
//        String paragraphText = paragraph.getText();
//        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
//            if (paragraphText.contains(entry.getKey())) {
//                List<XWPFRun> runs = paragraph.getRuns();
//                TextSegment found = paragraph.searchText(entry.getKey(), new PositionInParagraph());
//                if (found != null) {
//                    // 替换文本
//                    int beginRun = found.getBeginRun();
//                    int endRun = found.getEndRun();
//
//                    if (beginRun >= 0 && endRun >= 0) {
//                        // 删除原有runs
//                        for (int runPos = beginRun; runPos <= endRun; runPos++) {
//                            paragraph.removeRun(runPos);
//                        }
//                        // 创建新run
//                        XWPFRun newRun = paragraph.insertNewRun(beginRun);
//                        newRun.setText(entry.getValue());
//                        // 复制原有格式
//                        if (runs.size() > 0 && runs.get(0) != null) {
//                            XWPFRun styleRun = runs.get(0);
//                            newRun.setFontFamily(styleRun.getFontFamily());
//                            newRun.setFontSize(styleRun.getFontSize());
//                            newRun.setBold(styleRun.isBold());
//                            newRun.setItalic(styleRun.isItalic());
//                        }
//                    }
//                }
//            }
//        }
//    }
//
//    public static void main(String[] args) {
//
//        String templatePath = "/path/to/template.docx";
//        String outputPath = "/path/to/output.docx";
//
////        fillTemplate(templatePath, outputPath, user);
//    }
//}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
@@ -5,17 +5,22 @@
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -174,10 +179,19 @@
            System.setProperty("file.encoding", "UTF-8");
            XWPFDocument document = new XWPFDocument(fis);
            XWPFParagraph pic = document.createParagraph();
            XWPFRun picRun = pic.createRun();
            Map<String, Object> dataMap1 = new HashMap<>();
//            dataMap.put("${picture}", picRun.addPicture(
//                    new FileInputStream("/usr/local/project/file/1.jpg"), XWPFDocument.PICTURE_TYPE_JPEG,
//                    "/usr/local/project/file/1.jpg",
//                    Units.toEMU(60),
//                    Units.toEMU(30)
//            ));
            // 处理段落
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                replaceParagraph(paragraph, dataMap);
                replaceParagraph1(paragraph);
            }
            // 处理表格
@@ -266,6 +280,19 @@
            replaceRunRange(paragraph, info);
        }
    }
    private static void replaceParagraph1(XWPFParagraph paragraph) throws IOException, InvalidFormatException {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun r : runs) {
            String text = r.getText(0);
            if (text != null && text.contains("{{image}}")) {
                r.setText("", 0);
                FileInputStream is = new FileInputStream("/usr/local/project/file/1.jpg");
                r.addBreak();
                r.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "/usr/local/project/file/1.jpg", Units.toEMU(60), Units.toEMU(30));
                is.close();
            }
        }
    }
    private static String processPlaceholder(String text, Map<String, Object> dataMap) {
        // 处理括号内的占位符
ruoyi-admin/src/main/resources/application-test.yml
@@ -162,7 +162,7 @@
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 1
  expireTime: 120
mybatis-plus:
  # 此处在多数据源中生效
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
@@ -2,7 +2,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
@@ -15,23 +14,53 @@
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.bo.ProcessTaskListBO;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.dto.TInvoiceDTO;
import com.ruoyi.system.model.*;
import com.ruoyi.system.query.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.*;
import com.ruoyi.system.model.TBanner;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TCheckAcceptRecord;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TContractRentType;
import com.ruoyi.system.model.TFaultRepairMessage;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.TTenant;
import com.ruoyi.system.query.TBannerQuery;
import com.ruoyi.system.query.TBillAppletQuery;
import com.ruoyi.system.query.TCheckAcceptRecordAppletQuery;
import com.ruoyi.system.query.TExamineAppletQuery;
import com.ruoyi.system.query.TFaultRepairMessageAppletQuery;
import com.ruoyi.system.query.TTenantAppletQuery;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.StateProcessTemplateService;
import com.ruoyi.system.service.TBannerService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TCheckAcceptRecordService;
import com.ruoyi.system.service.TContractRentTypeService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.TFaultRepairMessageService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.service.TTenantService;
import com.ruoyi.system.vo.ExamineVO;
import com.ruoyi.system.vo.MyHouseVO;
import com.ruoyi.system.vo.MyToDoVO;
import com.ruoyi.system.vo.PayListVO;
import com.ruoyi.system.vo.ProcessTaskListVO;
import com.ruoyi.system.vo.TBillVO;
import com.ruoyi.system.vo.TCheckAcceptRecordVO;
import com.ruoyi.system.vo.TContractVO;
import com.ruoyi.system.vo.TFaultRepairMessageVO;
import com.ruoyi.system.vo.TenantVO;
import com.ruoyi.web.controller.tool.MyFileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jdk.nashorn.internal.parser.Token;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@@ -202,6 +231,7 @@
                myToDoVO.setStartTime(DateUtils.localDateTimeToStringYear(contract.getStartTime()));
                myToDoVO.setPropertyRightPerson(tHouse.getPropertyRightPerson());
                myToDoVO.setPhone(tHouse.getPhone());
                myToDoVO.setRentalReturnStatus(tHouse.getRentalReturnStatus() == null ? "1" : tHouse.getRentalReturnStatus());
                List<TBill> billList = bills.stream().filter(e -> e.getContractId().equals(contract.getId())).collect(Collectors.toList());
                List<PayListVO> payList = new ArrayList<>();
                for (TBill tBill : billList) {
@@ -257,6 +287,8 @@
    @ApiOperation(value = "管理员-房屋验收单列表")
    @PostMapping(value = "/admin/houseCheck")
    public R<PageInfo<TCheckAcceptRecordVO>> houseCheck(@RequestBody TCheckAcceptRecordAppletQuery query) {
        LoginUserApplet loginUserApplet = tokenService.getLoginUserApplet();
        query.setSysUserId(loginUserApplet.getUserId());
        return R.ok(checkAcceptRecordService.pageListApplet(query));
    }
@@ -295,6 +327,20 @@
        // 添加验收记录
        dto.setCheckPerson(tokenService.getLoginUser().getUser().getNickName());
        checkAcceptRecordService.updateById(dto);
        TCheckAcceptRecord checkAcceptRecord = checkAcceptRecordService.getById(dto.getId());
        TContract contract = contractService.getById(checkAcceptRecord.getContractId());
        // 添加账单
        TBill tBill = new TBill();
        tBill.setContractId(checkAcceptRecord.getContractId());
        tBill.setContractNumber(contract.getContractNumber());
        tBill.setPayableFeesMoney(dto.getCheckMoney());
        tBill.setPayableFeesTime(LocalDate.now());
        tBill.setPayFeesStatus("1");
        tBill.setBillType("4");
        tBill.setOverDays(0);
        tBill.setBusinessDeptId(contract.getBusinessDeptId());
        tBill.setOutstandingMoney(dto.getCheckMoney());
        billService.save(tBill);
        return R.ok();
    }
    /**
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -9,7 +9,6 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CodeGenerateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.dto.BatchBillDTO;
import com.ruoyi.system.dto.TBillDto;
@@ -22,12 +21,14 @@
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
 * <p>
@@ -64,7 +65,7 @@
    public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){
        String userId = tokenService.getLoginUserApplet().getUserId();
        query.setUserId(userId);
        PageInfo<TBillDto> pageInfo = tBillService.queryPage(query);
        PageInfo<TBillDto> pageInfo = tBillService.queryPageForApplet(query);
        return R.ok(pageInfo);
    }
@@ -129,17 +130,39 @@
    @PostMapping(value = "/invoice")
    public R<String> invoice(@RequestBody TInvoiceDTO dto) {
        String userId = tokenService.getLoginUserApplet().getUserId();
        List<String> billIds = dto.getBillIds();
        dto.setApplyName(tenantService.getById(userId).getResidentName());
        String code;
        do {
            code = CodeGenerateUtils.generateVolumeSn();
        } while (invoiceService.count(Wrappers.lambdaQuery(TInvoice.class).eq(TInvoice::getInvoiceNumber, code)) > 0);
        dto.setInvoiceNumber(CodeGenerateUtils.generateVolumeSn());
        String deptId = "";
        List<TBill> list = tBillService.list(Wrappers.lambdaQuery(TBill.class).in(TBill::getId, billIds));
        for (String billId : billIds) {
            TBill tBill = list.stream().filter(bill -> bill.getId().equals(billId)).findFirst().orElse(null);
            if(StringUtils.hasLength(deptId)){
                if(Objects.nonNull(tBill)){
                    if(!deptId.equals(tBill.getBusinessDeptId())){
                        return R.fail("请选择同一运营部门账单开票");
                    }else {
                        deptId = tBill.getBusinessDeptId();
                    }
                }
            }else {
                if(Objects.nonNull(tBill)){
                    deptId = tBill.getBusinessDeptId();
                }else {
                    return R.fail("请选择同一运营部门账单开票");
                }
            }
        }
        dto.setBusinessDeptId(deptId);
        // 添加开票信息
        invoiceService.save(dto);
        // 添加开票信息中间表信息
        List<String> billIds = dto.getBillIds();
        List<TInvoiceToBill> sysInvoiceToBills = new ArrayList<>();
        for (String billId : billIds) {
            TInvoiceToBill tInvoiceToBill = new TInvoiceToBill();
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TRentalReturnRecordController.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUserApplet;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TRentalReturnRecord;
import com.ruoyi.system.service.ITRentalReturnRecordService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.vo.RentalRetureApplyVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/rentalReturnRecord")
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@Api(tags = {"房屋管理-退租申请"})
public class TRentalReturnRecordController extends BaseController {
    private final ITRentalReturnRecordService rentalReturnRecordService;
    private final TokenService tokenService;
    /**
     * 申请退租
     */
    @ApiOperation(value = "申请退租")
    @PostMapping("/apply")
    public R<?> apply(@RequestBody RentalRetureApplyVO rentalReture) {
        rentalReturnRecordService.apply(rentalReture, tokenService.getLoginUserApplet().getUserId());
        return R.ok();
    }
    /**
     * 申请详情
     */
    @ApiOperation(value = "申请详情")
    @GetMapping("/detail")
    public R<TRentalReturnRecord> detail(@ApiParam (value = "合同id") @RequestParam String contractId) {
        TRentalReturnRecord rentalReturnRecord = rentalReturnRecordService.getOne(new LambdaQueryWrapper<TRentalReturnRecord>()
                .eq(TRentalReturnRecord::getContractId, contractId)
                .last("limit 1")
                .orderByDesc(TRentalReturnRecord::getCreateTime));
        if (rentalReturnRecord == null){
            return R.fail("暂无申请记录");
        }
        TRentalReturnRecord detail = rentalReturnRecordService.getOne(new LambdaQueryWrapper<TRentalReturnRecord>()
                .eq(TRentalReturnRecord::getId, rentalReturnRecord.getId()));
        return R.ok(detail);
    }
}
ruoyi-common/pom.xml
@@ -144,10 +144,15 @@
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <!--mybatis-plus-->
<!--        <dependency>-->
<!--            <groupId>com.baomidou</groupId>-->
<!--            <artifactId>mybatis-plus-boot-starter</artifactId>-->
<!--            <version>3.5.2</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
            <version>3.5.7</version>
        </dependency>
        <!--lombok-->
        <dependency>
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -1,18 +1,18 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.*;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.xss.Xss;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.xss.Xss;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
/**
 * 用户对象 sys_user
@@ -131,6 +131,10 @@
    @TableField(exist = false)
    private List<String> deptIds;
    @ApiModelProperty(value = "营业部id")
    @TableField("business_dept_id")
    private String businessDeptId;
    public String getRoleName() {
        return roleName;
    }
ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java
@@ -72,5 +72,24 @@
        timestampPart = timestampPart.substring(0, 0);
        return dateTime + timestampPart;
    }
    /**
     * @return
     * @Description 生成统一支付单号  规则:年(2)月(2)日(2)时(2)分(2)+timestamp*5位随机整数取后5位
     * @Author xiaochen
     */
    public static String generateVolumeSn(String code) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
        String dateTime = dateFormat.format(calendar.getTime());
        dateTime = dateTime.substring(0,8);
        String timestampPart = "" + (Math.random() * 10000) * (System.currentTimeMillis() / 10000);
        timestampPart = timestampPart.replace(".", "").replace("E", "");
        timestampPart = timestampPart.substring(0, 6);
        return dateTime + code + timestampPart;
    }
    public static void main(String[] args) {
        System.err.println(generateVolumeSn("2"));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -1,16 +1,21 @@
package com.ruoyi.common.utils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
 * 时间工具类
@@ -267,7 +272,7 @@
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, startMonth);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date first = cal.getTime();
@@ -279,9 +284,9 @@
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, lastMonth);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        Date last = cal.getTime();
        map.put("last", last);
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
@@ -1,6 +1,7 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.core.domain.model.LoginUserApplet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -13,6 +14,7 @@
 * 
 * @author ruoyi
 */
@Slf4j
public class SecurityUtils
{
    /**
@@ -44,7 +46,20 @@
            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * 获取营业部ID
     **/
    public static String getBusinessDeptId()
    {
        try
        {
            return getLoginUser().getUser().getBusinessDeptId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取营业部ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * 获取用户账户
     **/
@@ -56,8 +71,10 @@
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
            log.error("获取用户信息发生异常",e);
//            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
        return "";
    }
    /**
     * 获取用户账户小程序
ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java
@@ -8,17 +8,17 @@
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import java.net.URLEncoder;
import javax.activation.URLDataSource;
import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
@@ -132,14 +132,44 @@
            // 设置邮件标题
            message.setSubject("发票");
            // 创建邮件内容
            Multipart multipart = createMultipart(list);
            Multipart multipart = new MimeMultipart();
            // 添加文本消息部分
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setHeader("Content-Type", "text/plain;charset=utf-8");
            messageBodyPart.setContent("您在小程序提交的开票申请已开票成功,请查看附件内容","text/html;charset=UTF-8");
            multipart.addBodyPart(messageBodyPart);
            List<Path> tempFilePath = new ArrayList<>();
            // 添加附件部分
            for (Map<String, String> map : list) {
                messageBodyPart = new MimeBodyPart();
                String filePath = map.get("filePath");
                String fileName = map.get("fileName");
                Path path = Paths.get(filePath, fileName);
                tempFilePath.add(path);
                FileDataSource source = new FileDataSource(path.toString());
                messageBodyPart.setDataHandler(new DataHandler(source));
                // String filenameEncode = MimeUtility.encodeText(fileName, "UTF-8", "base64");
                // String encodedFileName = Base64.getEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8));
                // String filenameEncode = MimeUtility.encodeText(encodedFileName);
                messageBodyPart.setFileName(fileName);
                messageBodyPart.setHeader("Content-Transfer-Encoding", "base64");
                messageBodyPart.setHeader("Content-Disposition", "attachment");
                messageBodyPart.setHeader("Content-Type", "application/octet-stream;name=\"" + fileName + "\"");
                multipart.addBodyPart(messageBodyPart);
            }
            // 设置邮件内容
            message.setContent(multipart);
            // 发送邮件
            Transport.send(message);
            // 删除临时目录里面的文件
            for (Path path : tempFilePath) {
                Files.deleteIfExists(path);
            }
        } catch (MessagingException | UnsupportedEncodingException | MalformedURLException e) {
            log.error("发送邮件发生异常", e);
            throw new ServiceException("发送邮件失败, 请检查");
        } catch (IOException e) {
            throw new RuntimeException("文件下载发生异常");
        }
    }
@@ -167,31 +197,6 @@
                return new PasswordAuthentication(userName, password);
            }
        };
    }
    private Multipart createMultipart(List<Map<String, String>> list) throws MessagingException, UnsupportedEncodingException, MalformedURLException {
        Multipart multipart = new MimeMultipart();
        // 添加文本消息部分
        BodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setHeader("Content-Type", "text/plain;charset=utf-8");
        messageBodyPart.setContent("您在小程序提交的开票申请已开票成功,请查看附件内容","text/html;charset=UTF-8");
        multipart.addBodyPart(messageBodyPart);
        // 添加附件部分
        for (Map<String, String> map : list) {
            messageBodyPart = new MimeBodyPart();
            String url = map.get("url");
            String fileName = map.get("fileName");
            URLDataSource source = new URLDataSource(new URL(url));
            messageBodyPart.setDataHandler(new DataHandler(source));
            String filenameEncode = MimeUtility.encodeText(fileName, "UTF-8", "base64");
            messageBodyPart.setFileName(filenameEncode);
            messageBodyPart.setHeader("Content-Transfer-Encoding", "base64");
            messageBodyPart.setHeader("Content-Disposition", "attachment");
            messageBodyPart.setHeader("Content-Type", "application/octet-stream;name=\"" + filenameEncode + "\"");
            multipart.addBodyPart(messageBodyPart);
        }
        return multipart;
    }
   // public static void main(String[] args) throws UnsupportedEncodingException {
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -1,27 +1,15 @@
package com.ruoyi.framework.web.service;
import javax.annotation.Resource;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.entity.TTenantResp;
import com.ruoyi.common.core.domain.model.LoginUserApplet;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.system.model.TTenant;
import com.ruoyi.system.service.TTenantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.TTenantResp;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.LoginUserApplet;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.BlackListException;
import com.ruoyi.common.exception.user.CaptchaException;
@@ -35,8 +23,20 @@
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.model.TTenant;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.TTenantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * 登录校验方法
ruoyi-system/src/main/java/com/ruoyi/system/dto/OfflinePayCheckDto.java
@@ -41,7 +41,7 @@
    private String flowId;
    @ApiModelProperty("支付类型")
    @NotEmpty(message = "支付类型不能为空")
    @NotNull(message = "支付类型不能为空")
    private Integer payType;
ruoyi-system/src/main/java/com/ruoyi/system/dto/TContractDTO.java
@@ -1,9 +1,7 @@
package com.ruoyi.system.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TTenant;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java
@@ -6,6 +6,7 @@
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
@@ -13,8 +14,11 @@
    @ApiModelProperty(value = "水电费列表")
    private List<TBillDetail> details;
    /**
     *
     */
    @ApiModelProperty(value = "调整金额(有违约金,就调整违约金并调整欠费,没有违约金,就直接调整欠费)")
    private BigDecimal editAmount;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/TerminateContractDTO.java
@@ -1,10 +1,13 @@
package com.ruoyi.system.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@ApiModel(value = "终止合同DTO")
@@ -16,4 +19,9 @@
    @ApiModelProperty(value = "备注说明")
    private String terminateRemark;
    @ApiModelProperty(value = "终止日期")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime terminateTime;
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBankFlowMapper.java
@@ -15,6 +15,6 @@
 * @since 2025-02-07
 */
public interface TBankFlowMapper extends BaseMapper<TBankFlow> {
    TBankFlowStatisticsVo getPaymentStats(@Param("req") TBankFlowQuery query);
    TBankFlowStatisticsVo getPaymentStats(@Param("req") TBankFlowQuery query,@Param("businessDeptId") String businessDeptId);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
@@ -5,11 +5,12 @@
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.vo.ScreenRentRankVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
@@ -25,6 +26,8 @@
    PageInfo<TBillDto> page(@Param("pageInfo") PageInfo<TBill> pageInfo, @Param("query") TBillQuery query);
    PageInfo<TBillDto> pageForApplet(@Param("pageInfo") PageInfo<TBill> pageInfo, @Param("query") TBillQuery query);
    List<TBillDto> getBillList(@Param("query")TBillQuery query);
    /**
@@ -37,13 +40,24 @@
    TBillDto selectDetailByBillId(@Param("billId") String billId);
    BigDecimal statisticsAllRent();
    BigDecimal statisticsAllRent(@Param("query") TBillQuery query);
    BigDecimal statisticsNoPay();
    BigDecimal statisticsNoPay(@Param("query") TBillQuery query);
    BigDecimal statisticsPayed();
    BigDecimal statisticsPayed(@Param("query") TBillQuery query);
    BigDecimal statisticsOverdue();
    BigDecimal statisticsOverdue(@Param("query") TBillQuery query);
    Integer batchBillCount(@Param("userId")String userId, @Param("billIds")List<String> billIds);
    /**
     * 街道租金排行
     * @return
     */
    List<ScreenRentRankVO> getStreetRentRank(@Param("businessDeptId") String businessDeptId);
    /**
     * 查询季付账单
     * @param businessDeptId
     * @return
     */
    List<TBill> getJiFuBillList(@Param("businessDeptId") String businessDeptId, @Param("first") Date first, @Param("last") Date last);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBusinessDeptMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.model.TBusinessDept;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 * 营业部 Mapper 接口
 * </p>
 *
 * @author mitao
 * @since 2025-03-24
 */
public interface TBusinessDeptMapper extends BaseMapper<TBusinessDept> {
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TContractMapper.java
@@ -2,7 +2,10 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.query.TContractAppletQuery;
import com.ruoyi.system.query.TContractBillQuery;
import com.ruoyi.system.query.TContractQuery;
@@ -21,11 +24,18 @@
 */
public interface TContractMapper extends BaseMapper<TContract> {
    List<TContract> contractList(@Param("query") TContractQuery query, @Param("pageInfo") PageInfo<TContract> pageInfo);
    List<TContract> contractList(@Param("query") TContractQuery query, @Param("pageInfo") PageInfo<TContract> pageInfo,@Param("businessDeptId") String businessDeptId);
    List<TContract> contractAppletList(@Param("query")TContractAppletQuery query, @Param("pageInfo")  PageInfo<TContract> pageInfo);
    List<BillVO> contractBillList(@Param("query") TContractBillQuery query, @Param("pageInfo") PageInfo<BillVO> pageInfo);
    List<TContract> contractExportList(@Param("query")TContractQuery query);
    /**
     * 本月新增租户数
     * @return
     */
    Integer getCurrentMonthRentCount(@Param("businessDeptId") String businessDeptId);
    PageInfo<TContract> page(@Param("pageInfo") PageInfo<TContract> pageInfo,@Param("query") TContractQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFlowManagementMapper.java
@@ -15,5 +15,6 @@
 * @since 2025-01-17
 */
public interface TFlowManagementMapper extends BaseMapper<TFlowManagement> {
    TFlowManagementStatisticsVo getPaymentStats(@Param("req") TFlowManagementQuery query);
    TFlowManagementStatisticsVo getPaymentStats(@Param("req") TFlowManagementQuery query,@Param("businessDeptId") String businessDeptId);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/THouseMapper.java
@@ -23,5 +23,10 @@
    List<THouse> houseList(@Param("req") THouseQuery query, @Param("pageInfo") PageInfo<THouse> pageInfo);
    List<HouseVO> userHistoryList(@Param("req")TUserHistoryQuery query, @Param("pageInfo")PageInfo<HouseVO> pageInfo);
    /**
     * 获取本季度已出租面积
     * @param businessDeptId
     * @return
     */
    Double getRentedArea(@Param("businessDeptId") String businessDeptId);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TRentalReturnRecordMapper.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.system.model.TRentalReturnRecord;
import com.ruoyi.system.query.RentalReturnRecordQuery;
import com.ruoyi.system.vo.RentalReturnRecordVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface TRentalReturnRecordMapper extends BaseMapper<TRentalReturnRecord> {
    IPage<RentalReturnRecordVO> queryRentalReturnRecordList(@Param("page") IPage<RentalReturnRecordVO> page,
                                                           @Param("query") RentalReturnRecordQuery query);
    RentalReturnRecordVO queryRentalReturnRecordById(@Param("id") String id);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TStreetMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.model.TStreet;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 * 街道 Mapper 接口
 * </p>
 *
 * @author mitao
 * @since 2025-03-19
 */
public interface TStreetMapper extends BaseMapper<TStreet> {
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTenantMapper.java
@@ -38,4 +38,11 @@
    List<ExamineVO> examineList(@Param("query")TExamineAppletQuery dto, @Param("pageInfo")PageInfo<ExamineVO> pageInfo);
    /**
     * 根据营业部id获取租户列表
     * @param query
     * @param pageInfo
     * @return
     */
    List<TenantVO> pageListByBusinessDeptId(@Param("query") TTenantQuery query, @Param("pageInfo")PageInfo<TenantVO> pageInfo);
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TBankFlow.java
@@ -32,6 +32,10 @@
    @TableId("id")
    private String id;
    @ApiModelProperty(value = "营运部门ID")
    @TableField("business_dept_id")
    private String businessDeptId;
    @ApiModelProperty(value = "银行流水号")
    @TableField("bank_serial_number")
    private String bankSerialNumber;
ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
@@ -1,24 +1,23 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.core.domain.BaseModel;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Transient;
import springfox.documentation.annotations.ApiIgnore;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
/**
 * <p>
@@ -76,6 +75,10 @@
    @TableField("contract_id")
    private String contractId;
    @ApiModelProperty(value = "营运部门ID")
    @TableField("business_dept_id")
    private String businessDeptId;
    @ApiModelProperty(value = "合同编号")
    @TableField("contract_number")
    private String contractNumber;
@@ -98,7 +101,7 @@
    private BigDecimal payFeesMoney;
    @ApiModelProperty(value = "缴费日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("pay_fees_time")
    private LocalDateTime payFeesTime;
@@ -180,6 +183,12 @@
    @TableField(exist = false)
    private BigDecimal preOutstand;
    @ApiModelProperty(value = "是否管理后台添加 1=是 0=否 用于生成合同附件时过滤管理后台添加的账单,查询首个账单")
    @TableField("is_manual_addition")
    private Integer manualAddition;
ruoyi-system/src/main/java/com/ruoyi/system/model/TBusinessDept.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * <p>
 * 营业部
 * </p>
 *
 * @author mitao
 * @since 2025-03-24
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_business_dept")
@ApiModel(value="TBusinessDept对象", description="营业部")
public class TBusinessDept extends BaseModel implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "营业部名称")
    private String name;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
@@ -1,14 +1,9 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
@@ -16,7 +11,8 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
@@ -129,7 +125,6 @@
    @ApiModelProperty(value = "合同附件,多个逗号拼接")
    @TableField("contract_file")
    @NotBlank(message = "合同附件不能为空")
    private String contractFile;
    @ApiModelProperty(value = "备注")
@@ -149,6 +144,15 @@
    @ApiModelProperty(value = "合同状态 1=待提交 2=待审批 3=未签订 4=已签订 5=已驳回 6=已终止 7=待结算 8=已结算 9 = 签订待审核")
    @TableField("status")
    private String status;
    /**
     * 签订时间
     */
    @ApiModelProperty(value = "签订时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("sign_time")
    private LocalDateTime signTime;
    @ApiModelProperty(value = "内存大小多个文件逗号拼接")
    @TableField("memory")
    private String memory;
@@ -174,4 +178,16 @@
    @TableField(exist = false)
    private String instanceId;
    @ApiModelProperty(value = "房屋使用范围")
    @TableField("house_use_scope")
    private String houseUseScope;
    @ApiModelProperty(value = "终止日期-前端传的")
    @TableField("terminate_time")
    private LocalDateTime terminateTime;
    @ApiModelProperty(value = "营业部id")
    @TableField("business_dept_id")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java
@@ -119,4 +119,8 @@
    @TableField("status")
    private Integer status;
    @ApiModelProperty(value = "故障因素: 1-人为因素 2-市政因素")
    @TableField("fault_cause")
    private Integer faultCause;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TFlowManagement.java
@@ -35,6 +35,10 @@
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "营运部门ID")
    @TableField("business_dept_id")
    private String businessDeptId;
    @ApiModelProperty(value = "系统流水号")
    @TableField("sys_serial_number")
    private String sysSerialNumber;
ruoyi-system/src/main/java/com/ruoyi/system/model/THouse.java
@@ -1,18 +1,18 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
@@ -81,6 +81,11 @@
    @ApiModelProperty(value = "租赁状态 1=待出租 2=已出租 3=维修中")
    @TableField("lease_status")
    private String leaseStatus;
    @ApiModelProperty(value = "退租状态 1=未退租 2=退租申请中 3=已退租")
    @TableField("rental_return_status")
    private String rentalReturnStatus;
    @ApiModelProperty(value = "楼栋")
    @TableField("building")
    private String building;
@@ -94,4 +99,20 @@
    @ApiModelProperty(value = "住户类型 1月租 2季租 3年租")
    @TableField(exist = false)
    private String tenantType;
    @ApiModelProperty(value = "所属街道id")
    @TableField("street_id")
    private String streetId;
    @ApiModelProperty(value = "经度")
    @TableField("longitude")
    private BigDecimal longitude;
    @ApiModelProperty(value = "纬度")
    @TableField("latitude")
    private BigDecimal latitude;
    @ApiModelProperty(value = "营业部id")
    @TableField("business_dept_id")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java
@@ -1,12 +1,9 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
@@ -16,6 +13,7 @@
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
 * <p>
@@ -79,4 +77,8 @@
    @TableField(exist = false)
    private Integer viewCount;
    @ApiModelProperty(value = "营业部id")
    @TableField("business_dept_id")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoice.java
@@ -35,6 +35,10 @@
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "营运部门ID")
    @TableField("business_dept_id")
    private String businessDeptId;
    @ApiModelProperty(value = "申请编号")
    @TableField("invoice_number")
    private String invoiceNumber;
ruoyi-system/src/main/java/com/ruoyi/system/model/TRentalReturnRecord.java
New file
@@ -0,0 +1,85 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("t_rental_return_record")
@ApiModel("退租记录")
public class TRentalReturnRecord extends BaseModel {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    @ApiModelProperty(value = "退租记录id")
    private String id;
    /**
     * 租户id
     */
    @ApiModelProperty(value = "租户id")
    private String tenantId;
    /**
     * 房屋id
     */
    @ApiModelProperty(value = "房屋id")
    private String houseId;
    /**
     * 合同id
     */
    @ApiModelProperty(value = "合同id")
    private String contractId;
    /**
     * 图片
     */
    @ApiModelProperty(value = "图片")
    private String images;
    /**
     * 退租说明
     */
    @ApiModelProperty(value = "退租说明")
    private String reasonForReturn;
    /**
     * 审批意见
     */
    @ApiModelProperty(value = "审批意见")
    private String auditOpinion;
    /**
     * 审批时间
     */
    @ApiModelProperty(value = "审批时间")
    private LocalDateTime auditTime;
    /**
     * 审批状态: 1-待审核 2-审核通过 3-审核驳回
     */
    @ApiModelProperty(value = "审批状态: 1-待审核 2-审核通过 3-审核驳回")
    private Integer auditStatus;
    /**
     * 审批人id
     */
    @ApiModelProperty(value = "审批人id")
    private Long auditUserId;
    /**
     * 管理后台删除标识
     */
    @ApiModelProperty(value = "管理后台删除标识")
    private Boolean isAdminDelete;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TStreet.java
New file
@@ -0,0 +1,38 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
 * <p>
 * 街道
 * </p>
 *
 * @author mitao
 * @since 2025-03-19
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_street")
@ApiModel(value="TStreet对象", description="街道")
public class TStreet extends BaseModel implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "物品名称")
    private String streetName;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java
@@ -1,14 +1,9 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDate;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
@@ -18,6 +13,7 @@
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
/**
 * <p>
@@ -92,4 +88,20 @@
    @TableField("open_id")
    private String openId;
    @ApiModelProperty(value = "法人")
    @TableField("legal_person")
    private String legalPerson;
    @ApiModelProperty(value = "社会统一信用代码")
    @TableField("credit_code")
    private String creditCode;
    @ApiModelProperty(value = "开户行")
    @TableField("bank_name")
    private String bankName;
    @ApiModelProperty(value = "承租人")
    @TableField("lessee")
    private String lessee;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/RentalReturnAuditQuery.java
New file
@@ -0,0 +1,27 @@
package com.ruoyi.system.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("退租审核查询")
public class RentalReturnAuditQuery {
    /**
     * id
     */
    @ApiModelProperty(value = "id")
    private String id;
    /**
     * 审核结果:2-审核通过 3-审核驳回
     */
    @ApiModelProperty(value = "审核结果:2-审核通过 3-审核驳回")
    private Integer auditResult;
    /**
     * 审核意见
     */
    @ApiModelProperty(value = "审核意见")
    private String auditOpinion;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/RentalReturnRecordQuery.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.system.query;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
@ApiModel("退租记录查询")
public class RentalReturnRecordQuery {
    /**
     * 申请开始日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "申请开始日期")
    private LocalDateTime startDate;
    /**
     * 申请结束日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "申请结束日期")
    private LocalDateTime endDate;
    /**
     * 房屋名称
     */
    @ApiModelProperty(value = "房屋名称")
    private String houseName;
    /**
     * 合同编号
     */
    @ApiModelProperty(value = "合同编号")
    private String contractNumber;
    /**
     * 提交人
     */
    @ApiModelProperty(value = "提交人")
    private String submitter;
    private String businessDeptId;
    private Boolean isAdminDelete;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java
@@ -23,4 +23,7 @@
    @ApiModelProperty(value = "状态  0=正常 1=停用")
    private String status;
    @ApiModelProperty(value = "营业部id",hidden = true)
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TBankFlowQuery.java
@@ -57,4 +57,7 @@
    @ApiModelProperty(value = "支付结束时间")
    private String payEndTime;
    @ApiModelProperty(value = "营运部门ID")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java
@@ -1,11 +1,15 @@
package com.ruoyi.system.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class TBillQuery extends BasePage {
    @ApiModelProperty(value = "营运部门ID")
    private String businessDeptId;
    /**
     * 缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期
     */
@@ -31,4 +35,6 @@
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordAppletQuery.java
@@ -15,4 +15,8 @@
    @ApiModelProperty(value = "状态 不传为全部 1待验收 2已验收")
    private Integer status;
    private String sysUserId;
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java
@@ -1,6 +1,5 @@
package com.ruoyi.system.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.model.TimeRangeQueryBody;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -19,4 +18,7 @@
    @ApiModelProperty(value = "验收结果 1=合格 0=不合格")
    private Boolean checkResult;
    @ApiModelProperty(value = "营业部id",hidden = true)
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TContractQuery.java
@@ -27,4 +27,7 @@
    @ApiModelProperty(value = "查询多个状态")
    private List<Integer> statuses;
    @ApiModelProperty(value = "营运部门ID")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java
@@ -1,6 +1,5 @@
package com.ruoyi.system.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -24,4 +23,7 @@
    @ApiModelProperty(value = "处理人")
    private String handlePerson;
    @ApiModelProperty(value = "营业部id", hidden = true)
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TFlowManagementQuery.java
@@ -59,5 +59,8 @@
    @ApiModelProperty(value = "支付结束时间")
    private String payEndTime;
    @ApiModelProperty(value = "营运部门ID")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/THouseQuery.java
@@ -18,4 +18,7 @@
    @ApiModelProperty(value = "租赁状态 1=待出租 2=已出租 3=维修中")
    private String leaseStatus;
    @ApiModelProperty(value = "所属营业部", hidden = true)
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TInvoiceQuery.java
@@ -58,4 +58,7 @@
    @ApiModelProperty(value = "开票文件名称")
    private String invoiceVoucherName;
    @ApiModelProperty(value = "营运部门ID")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/TTenantQuery.java
@@ -1,7 +1,6 @@
package com.ruoyi.system.query;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -16,6 +15,9 @@
    @ApiModelProperty(value = "联系电话")
    private String phone;
    @ApiModelProperty(value = "营业部id")
    private String businessDeptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/ITBusinessDeptService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.service;
import com.ruoyi.system.model.TBusinessDept;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * 营业部 服务类
 * </p>
 *
 * @author mitao
 * @since 2025-03-24
 */
public interface ITBusinessDeptService extends IService<TBusinessDept> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/ITRentalReturnRecordService.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.TRentalReturnRecord;
import com.ruoyi.system.query.RentalReturnAuditQuery;
import com.ruoyi.system.query.RentalReturnRecordQuery;
import com.ruoyi.system.vo.RentalRetureApplyVO;
import com.ruoyi.system.vo.RentalReturnRecordVO;
public interface ITRentalReturnRecordService extends IService<TRentalReturnRecord> {
    IPage<RentalReturnRecordVO> queryRentalReturnRecordList(Page<RentalReturnRecordVO> page, RentalReturnRecordQuery query);
    RentalReturnRecordVO queryRentalReturnRecordById(String id);
    void apply(RentalRetureApplyVO rentalReture,String tenantId);
    void audit(RentalReturnAuditQuery returnAuditQuery, Long userId, String userName);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/ITStreetService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.service;
import com.ruoyi.system.model.TStreet;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * 街道 服务类
 * </p>
 *
 * @author mitao
 * @since 2025-03-19
 */
public interface ITStreetService extends IService<TStreet> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
@@ -2,18 +2,22 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.dto.*;
import com.ruoyi.system.dto.BillStatisticsDto;
import com.ruoyi.system.dto.CachPayDto;
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;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.vo.ScreenRentRankVO;
import com.taxi591.bankapi.dto.ChargeBillRequest;
import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.List;
/**
 * <p>
@@ -26,6 +30,9 @@
public interface TBillService extends IService<TBill> {
    PageInfo<TBillDto> queryPage(TBillQuery query);
    PageInfo<TBillDto> queryPageForApplet(TBillQuery query);
    /**
     *
@@ -84,7 +91,31 @@
    Boolean cashPay(CachPayDto offlinePayDto);
    BillStatisticsDto statistics();
    BillStatisticsDto statistics(TBillQuery query);
    Integer batchBillCount(String userId, List<String> billIds);
    /**
     * 查询街道租金排行
     * @return
     */
    List<ScreenRentRankVO> getStreetRentRank(String businessDeptId);
    /**
     * 查询季付账单
     * @param businessDeptId
     * @return
     */
    List<TBill> getJiFuBillList(String businessDeptId);
    /**
     * 查询当前季度的季付账单
     * @param businessDeptId
     * @param first
     * @param last
     * @return
     */
    List<TBill> getJiFuBillListByTime(String businessDeptId, Date first, Date last);
    void editAmount(TbillSaveDto bill);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java
@@ -11,6 +11,7 @@
import com.ruoyi.system.query.TContractQuery;
import com.ruoyi.system.vo.BillVO;
import com.ruoyi.system.vo.CheckAcceptRecordVO;
import com.ruoyi.system.vo.ScreenRentIncomeTrendVO;
import java.util.List;
@@ -43,4 +44,10 @@
    Boolean updateContractAuditStatus(String projectId, Integer submitStatus);
    /**
     * 本月新增租户数
     * @return
     */
    Integer getCurrentMonthRentCount(String businessDeptId);
    PageInfo<TContract> queryPage(TContractQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/THouseService.java
@@ -20,4 +20,11 @@
    PageInfo<THouse> houseList(THouseQuery query);
    PageInfo<HouseVO> userHistoryList(TUserHistoryQuery query);
    /**
     * 获取本季度已出租面积
     * @param businessDeptId
     * @return
     */
    Double getRentedArea(String businessDeptId);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TInvoiceService.java
@@ -7,6 +7,7 @@
import com.ruoyi.system.query.TInvoiceQuery;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -19,5 +20,5 @@
public interface TInvoiceService extends IService<TInvoice> {
    PageInfo<TInvoice> pageList(TInvoiceQuery query);
    List<TInvoice> makeQuery(TInvoiceQuery query);
    Boolean uploadVoucher(TInvoiceQuery query);
    Boolean uploadVoucher(TInvoiceQuery query, List<Map<String, String>> map);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java
@@ -28,17 +28,23 @@
import com.google.common.collect.ImmutableMap;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.enums.ProcessCategoryEnum;
import com.ruoyi.common.enums.SubmitStatusEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.TCheckAcceptRecordMapper;
import com.ruoyi.system.model.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TCheckAcceptRecord;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TContractRentType;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractRentTypeService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.task.base.QuartzManager;
import com.ruoyi.system.task.base.TimeJobType;
import com.ruoyi.system.task.jobs.StateProcessJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@@ -46,7 +52,11 @@
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -81,19 +91,22 @@
    private final THouseService houseService;
    public static void main(String[] args) {
        LocalDate localDate1 = LocalDate.now().withYear(2025).withMonth(1).withDayOfMonth(31);
        System.err.println(localDate1.plusMonths(1));
//        LocalDate localDate1 = LocalDate.now().withYear(2025).withMonth(2).withDayOfMonth(10).with;
//        System.err.println(localDate1.plusMonths(1));
////        LocalDate localDate2 = LocalDate.now().withYear(2025).withMonth(4).withDayOfMonth(16);
//        LocalDateTime localDate1 = LocalDateTime.now().withYear(2025).withMonth(4).withDayOfMonth(16);
//        LocalDateTime localDate2 = LocalDateTime.now().withYear(2025).withMonth(10).withDayOfMonth(24);
//
//        LocalDateTime localDate1 = LocalDateTime.now().withYear(2025).withMonth(2).withDayOfMonth(10).withHour(00).withMinute(00).withSecond(00);
//        LocalDateTime localDate2 = LocalDateTime.now().withYear(2025).withMonth(3).withDayOfMonth(31).withHour(00).withMinute(00).withSecond(00);
//        LocalDateTime with = localDate1.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
//        boolean before = with.isBefore(localDate2);
//        System.err.println(before);
//        long between = ChronoUnit.DAYS.between(localDate1, localDate2)+1;
        int monthValue = LocalDateTime.now().getMonthValue();
         LocalDateTime.now();
         LocalDateTime.now();
        System.err.println(LocalDateTime.now().isBefore(LocalDateTime.now()));
//        int monthValue = LocalDateTime.now().getMonthValue();
//         LocalDateTime.now();
//         LocalDateTime.now();
        int dayOfMonth = LocalDateTime.now().getMonthValue();
        System.err.println(dayOfMonth);
//        System.err.println(LocalDateTime.now().isBefore(LocalDateTime.now()));
    }
    @Override
@@ -259,6 +272,7 @@
    }
    /**
     * 业务状态变更
     */
@@ -291,9 +305,9 @@
                    }
                    List<TContractRentType> contractRentTypes = contractRentTypeService.list();
                    TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
                    // 生成第一笔账单
                    // 第一次应缴费日期
                    LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
                    TBill rentBill = new TBill();
                    rentBill.setContractId(contract.getId());
@@ -415,22 +429,41 @@
                            // 第一个月计算天
                            int dayOfMonth = rentBill.getStartTime().getDayOfMonth();
                            if (dayOfMonth == 1) {
                                System.err.println("第一笔账单 1号计算整月:");
                                money = money.add(contract.getMonthRent());
                            } else {
                                long allDays = ChronoUnit.DAYS.between(contract.getStartPayTime(), contract.getStartPayTime().with(TemporalAdjusters.lastDayOfMonth())) + 1;
                                long allDays = Math.abs(ChronoUnit.DAYS.between(rentBill.getStartTime(), rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())) + 1);
                                System.err.println("第一笔账单 计算天数"+allDays);
                                money =money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
                                System.err.println("第一笔账单 计算天数金额"+money);
                            }
                            // 后续
                            if (contract.getStartPayTime().getMonthValue()==3||contract.getStartPayTime().getMonthValue()==6||contract.getStartPayTime().getMonthValue()==9||contract.getStartPayTime().getMonthValue()==12){
                                System.err.println("后续账单 月为3 6 9 12金额"+money);
                                rentBill.setPayableFeesMoney(money);
                                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                            }else{
                                LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                                System.err.println("后续账单逻辑时间"+localDateTime);
                                while (true){
                                    if (localDateTime.isBefore(rentBill.getEndTime())){
                                    if (localDateTime.toLocalDate().isBefore(rentBill.getEndTime().toLocalDate())){
                                        System.err.println("后续while 在结束之前");
                                        money = money.add(contract.getMonthRent());
                                    }else{
                                        money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth()))+1)));
                                    }else if(localDateTime.toLocalDate().equals(rentBill.getEndTime().toLocalDate())){
                                        System.err.println("后续while 结束");
                                        money = money.add(contract.getMonthRent());
                                        break;
                                    }else {
                                        System.err.println("后续while 加一个月大于结束时间");
                                        if (localDateTime.with(TemporalAdjusters.firstDayOfMonth()).isBefore(rentBill.getEndTime())){
                                            long a = ChronoUnit.DAYS.between(localDateTime.with(TemporalAdjusters.firstDayOfMonth()),rentBill.getEndTime())+1;
                                            System.err.println("后续while 加一个月大于结束时间 计算天数"+a);
                                            money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(
                                                    new BigDecimal(ChronoUnit.DAYS.between(localDateTime.with(TemporalAdjusters.firstDayOfMonth()),rentBill.getEndTime())+1))
                                            );
                                        }
                                        break;
                                    }
                                    localDateTime = localDateTime.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
@@ -445,7 +478,7 @@
                            if (dayOfMonth == 1) {
                                money = money.add(contract.getMonthRent());
                            } else {
                                long allDays = ChronoUnit.DAYS.between(contract.getStartPayTime(), contract.getStartPayTime().with(TemporalAdjusters.lastDayOfMonth())) + 1;
                                long allDays = ChronoUnit.DAYS.between(rentBill.getStartTime(), rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())) ;
                                money =money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
                            }
                            // 后续
@@ -453,15 +486,16 @@
                                rentBill.setPayableFeesMoney(money);
                                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
                            }else{
                                LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
//                                LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                                LocalDateTime localDateTime = rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
                                while (true){
                                    if (localDateTime.isBefore(rentBill.getEndTime())){
                                        localDateTime = localDateTime.plusMonths(1);
                                        money = money.add(contract.getMonthRent());
                                    }else{
                                        money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth()))+1)));
                                        money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth())))));
                                        break;
                                    }
                                    localDateTime = localDateTime.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                                }
                                rentBill.setPayableFeesMoney(money);
                                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
@@ -492,6 +526,8 @@
                    depositBill.setBillType("2");
                    contractService.updateById(contract);
                    rentBill.setBusinessDeptId(contract.getBusinessDeptId());
                    depositBill.setBusinessDeptId(contract.getBusinessDeptId());
                    billService.save(rentBill);
                    billService.save(depositBill);
                    // 生成后续账单
@@ -711,6 +747,7 @@
                                tBill.setContractNumber(contract.getContractNumber());
                                tBill.setPayFeesStatus("1");
                                tBill.setBillType("1");
                                tBill.setBusinessDeptId(contract.getBusinessDeptId());
                                billService.save(tBill);
                                beforeBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).with(TemporalAdjusters.lastDayOfMonth()));
@@ -919,10 +956,16 @@
                                BigDecimal originalMoney = new BigDecimal("0");
                                // 不需要涨租金的时间段
                                long originalDays = 0;
                                if (tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(tBill.getEndTime())){
                                    originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())));
                                if (tBill.getStartTime().getDayOfMonth()==1&&(tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().isAfter(tBill.getEndTime().toLocalDate())||tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().equals(tBill.getEndTime().toLocalDate()))){
                                    // 计算整月
                                    originalMoney = originalMoney.add(contract.getChangeRent());
                                }else{
                                    originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getEndTime()));
                                    // 计算天
                                    if (tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(tBill.getEndTime())){
                                        originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())))+1;
                                    }else{
                                        originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getEndTime()))+1;
                                    }
                                }
                                originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(originalDays)));
                                LocalDateTime originalTime = tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
@@ -947,16 +990,28 @@
                            BigDecimal originalMoney = new BigDecimal("0");
                            // 不需要涨租金的时间段
                            long originalDays = 0;
                            if (tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(tBill.getEndTime())){
                                originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())));
                            if (tBill.getStartTime().getDayOfMonth()==1
                                    &&
                                    (
                                            tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().isBefore(tBill.getEndTime().toLocalDate())
                                            ||tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().equals(tBill.getEndTime().toLocalDate())
                                    )
                            ){
                                // 计算整月
                                originalMoney = originalMoney.add(contract.getChangeRent());
                            }else{
                                originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getEndTime()));
                                // 计算天
                                if (tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).isBefore(tBill.getEndTime())){
                                    originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())))+1;
                                }else{
                                    originalDays = Math.abs(ChronoUnit.DAYS.between(tBill.getStartTime(), tBill.getEndTime()))+1;
                                }
                                originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(originalDays)));
                            }
                            originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(originalDays)));
                            LocalDateTime originalTime = tBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
                            while(true){
                                if (originalTime.isBefore(tBill.getEndTime())){
                                    if (originalTime.plusMonths(1).isBefore(tContractRentType.getChangeTime())){
                                    if (originalTime.plusMonths(1).isBefore(tBill.getEndTime())){
                                        originalMoney = originalMoney.add(contract.getChangeRent());
                                        originalTime = originalTime.plusMonths(1);
                                    }else {
@@ -966,19 +1021,22 @@
                                    break;
                                }
                            }
                            long tempOriginal  = ChronoUnit.DAYS.between(originalTime,tBill.getEndTime());
                            originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(tempOriginal)));
                            if (originalTime.isBefore(tBill.getEndTime())||originalTime.toLocalDate().equals(tBill.getEndTime().toLocalDate())){
                                long tempOriginal  = ChronoUnit.DAYS.between(originalTime,tBill.getEndTime())+1;
                                originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(tempOriginal)));
                            }
                            tBill.setPayableFeesMoney(originalMoney);
                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
                        }
                        if (tBill.getEndTime().getDayOfMonth() >= 15) {
//                        if (tBill.getEndTime().getDayOfMonth() >= 15) {
//                            tBill.setPayableFeesTime(tBill.getStartTime().withDayOfMonth(15).toLocalDate());
//                        } else if (tBill.getStartTime().getYear() == tBill.getEndTime().getYear() && tBill.getStartTime().getMonthValue() == tBill.getEndTime().getMonthValue()) {
//                            // 如果同年同月 且日小于15 缴费时间取合同
//                            tBill.setPayableFeesTime(tBill.getStartTime().toLocalDate());
//                        } else {
                            tBill.setPayableFeesTime(tBill.getStartTime().withDayOfMonth(15).toLocalDate());
                        } else if (tBill.getStartTime().getYear() == tBill.getEndTime().getYear() && tBill.getStartTime().getMonthValue() == tBill.getEndTime().getMonthValue()) {
                            // 如果同年同月 且日小于15 缴费时间取合同
                            tBill.setPayableFeesTime(tBill.getStartTime().toLocalDate());
                        } else {
                            tBill.setPayableFeesTime(tBill.getStartTime().withDayOfMonth(15).toLocalDate());
                        }
//                        }
                        tBill.setBusinessDeptId(contract.getBusinessDeptId());
                        billService.save(tBill);
                    }
                }
@@ -986,10 +1044,18 @@
            }
            case CATEGORY3: {
                // 合同提前终止审批
                int submitStatus = status == 0 ? 4 : (status == 1 ? 7 : 5);
                int submitStatus = status == 0 ? 4 : (status == 1 ? 7 : 4);
                contractService.updateContractAuditStatus(processParameter.getString("projectId"), submitStatus);
                // 生成验收记录
                TContract contract = contractService.getById(processParameter.getString("projectId"));
                //更新合同结束时间
                contract.setEndTime(contract.getTerminateTime());
                contractService.updateById(contract);
                // 修改房屋状态
                THouse house = houseService.getById(contract.getHouseId());
                house.setLeaseStatus("1");
                houseService.updateById(house);
                TCheckAcceptRecord tCheckAcceptRecord = new TCheckAcceptRecord();
                tCheckAcceptRecord.setContractId(contract.getId());
                tCheckAcceptRecord.setHouseId(contract.getHouseId());
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ScreenService.java
New file
@@ -0,0 +1,245 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.vo.ScreenRentIncomeTrendVO;
import com.ruoyi.system.vo.ScreenRentRankVO;
import com.ruoyi.system.vo.ScreenTopStaticsDataVO;
import com.ruoyi.system.vo.TenantCountTrendVO;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * @author mitao
 * @date 2025/3/19
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ScreenService {
    private final THouseService tHouseService;
    private final TContractService tContractService;
    private final TBillService tBillService;
    private final TContractService contractService;
    /**
     * 获取顶部统计数据
     * @return
     */
    public ScreenTopStaticsDataVO getTopStaticsData() {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        Map<String, Date> quarterDate = DateUtils.getQuarterDate(new Date());
        Date first = quarterDate.get("first");
        Date last = quarterDate.get("last");
        ScreenTopStaticsDataVO vo = new ScreenTopStaticsDataVO();
        //房屋总面积
        List<THouse> houseList = tHouseService.lambdaQuery()
                .eq(!businessDeptId.equals("0"), THouse::getBusinessDeptId, businessDeptId)
                .list();
        Double totalArea = houseList.stream()
                .map(item -> Double.parseDouble(item.getHouseArea()))
                .reduce(0D, Double::sum);
        vo.setHouseTotalArea(totalArea);
        //已出租面积
        Double totalRentedArea =  tHouseService.getRentedArea(businessDeptId);
        vo.setHouseRentedArea(totalRentedArea);
        //总计应收租金
        List<TBill> billList = tBillService.getJiFuBillList(businessDeptId);
        BigDecimal totalReceivableRent = billList.stream()
                .filter(item -> !item.getPayFeesStatus().equals("5"))
                .map(TBill::getPayableFeesMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(new BigDecimal("10000"),2, RoundingMode.DOWN);
        vo.setTotalReceivableRent(totalReceivableRent);
        //总计已收租金
        BigDecimal totalReceivedRent = billList.stream()
                .map(TBill::getPayFeesMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(new BigDecimal("10000"),2, RoundingMode.DOWN);
        vo.setTotalReceivedRent(totalReceivedRent);
        //本月新增租户数
        Integer newTenantCount = tContractService.getCurrentMonthRentCount(businessDeptId);
        vo.setNewTenantCount(newTenantCount);
        //总计租户数 系统租户列表里有生效合同绑定的租户总数。
        List<TContract> tContracts = tContractService.lambdaQuery()
                .eq(TContract::getPayType,2) //季付
                .in(TContract::getStatus, "4", "5", "6", "7", "8", "9")
                .eq(!businessDeptId.equals("0"), TContract::getBusinessDeptId, businessDeptId)
                .list();
        long count = tContracts.stream()
                .map(TContract::getTenantId)
                .distinct()
                .count();
        vo.setTotalTenantCount((int) count);
        List<TBill> currentQuarterBillList = tBillService.getJiFuBillListByTime(businessDeptId, first, last);
        //本季度已交租金
        BigDecimal totalRentPaid = currentQuarterBillList.stream()
                .map(TBill::getPayFeesMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(new BigDecimal("10000"),2, RoundingMode.DOWN);
        vo.setTotalRentPaid(totalRentPaid);
        //本季度应交租金
        BigDecimal totalRentShould = currentQuarterBillList.stream()
                .filter(item -> !item.getPayFeesStatus().equals("5"))
                .map(TBill::getPayableFeesMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(new BigDecimal("10000"),2, RoundingMode.DOWN);
        vo.setTotalRentShould(totalRentShould);
        //本季度欠费
        BigDecimal totalRentOwe = currentQuarterBillList.stream()
                .map(TBill::getOutstandingMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN);
        vo.setTotalRentOwe(totalRentOwe);
        //总计欠费
        BigDecimal totalRentOweAll = billList.stream()
                .map(TBill::getOutstandingMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN);
        vo.setTotalRentOweAll(totalRentOweAll);
        return vo;
    }
    /**
     * 区域租金排名
     * @return
     */
    public List<ScreenRentRankVO> streetRentRank() {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        return  tBillService.getStreetRentRank(businessDeptId);
    }
    /**
     * 租金收入趋势
     * @return
     */
    public ScreenRentIncomeTrendVO rentIncomeTrend() {
        ScreenRentIncomeTrendVO vo = new ScreenRentIncomeTrendVO();
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        // 获取当前日期
        Date currentDate = new Date();
        List<String> quarterLabels = new ArrayList<>(); // 季度标签列表
        List<BigDecimal> incomeData = new ArrayList<>(); //收入数据列表
        List<BigDecimal> outstandingData = new ArrayList<>();  // 欠费数据列表
        // 获取最近7个季度的数据
        for (int i = 6; i >= 0; i--) {
            // 计算对应季度的起止时间
            Date targetDate = DateUtils.addMonths(currentDate, -3 * i);
            Map<String, Date> quarterDate = DateUtils.getQuarterDate(targetDate);
            Date quarterStart = quarterDate.get("first");
            Date quarterEnd = quarterDate.get("last");
            // 获取该季度的账单数据
            List<TBill> quarterBills = tBillService.getJiFuBillListByTime(businessDeptId, quarterStart, quarterEnd);
            // 计算季度租金收入总和
            BigDecimal quarterIncome = quarterBills.stream()
                    .map(TBill::getPayFeesMoney)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN);
            // 计算季度欠费总和
            BigDecimal quarterOutstanding = quarterBills.stream()
                    .map(TBill::getOutstandingMoney)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN);
            // 生成季度标签 (格式: YY-MM月)
            Calendar cal = Calendar.getInstance();
            cal.setTime(quarterEnd);
            String label = String.format("%02d-%d月",
                    cal.get(Calendar.YEAR) % 100,
                    cal.get(Calendar.MONTH) + 1);
            quarterLabels.add(label);
            incomeData.add(quarterIncome);
            outstandingData.add(quarterOutstanding);  // 添加欠费数据
        }
        vo.setQuarters(quarterLabels);
        vo.setIncomeData(incomeData);
        vo.setOutstandingData(outstandingData);  // 设置欠费数据到VO
        return vo;
    }
    public R<List<TenantCountTrendVO>> getTenantCountTrend() {
        // 获取当前日期
        Date currentDate = new Date();
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        List<TenantCountTrendVO> list = new ArrayList<>();
        for (int i = 6; i >= 0; i--) {
            Date targetDate = DateUtils.addMonths(currentDate, -3 * i);
            Map<String, Date> quarterDate = DateUtils.getQuarterDate(targetDate);
            Date quarterStart = quarterDate.get("first");
            Date quarterEnd = quarterDate.get("last");
            System.out.println("第" + (i + 1) + "季度的起止时间:" + quarterStart + " - " + quarterEnd);
            List<TContract> contracts = contractService.list(new LambdaQueryWrapper<TContract>()
                    .eq(!"0".equals(businessDeptId), TContract::getBusinessDeptId, businessDeptId)
                    .eq(TContract::getPayType, 2)
                    .isNotNull(TContract::getSignTime)
                    .between(TContract::getSignTime, quarterStart, quarterEnd)
                    .orderByAsc(TContract::getSignTime));
            TenantCountTrendVO vo = new TenantCountTrendVO();
            // 生成季度标签 (格式: YY-MM月)
            Calendar cal = Calendar.getInstance();
            cal.setTime(quarterEnd);
            String label = String.format("%02d-%d月",
                    cal.get(Calendar.YEAR) % 100,
                    cal.get(Calendar.MONTH) + 1);
            vo.setDate(label);
            long count = contracts.stream().map(TContract::getTenantId).distinct().count();
            vo.setCount(count);
            list.add(vo);
        }
        return R.ok(list);
    }
//
//
//
//
//
//
//
//        DateTimeFormatter quarterFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
//
//        List<TenantCountTrendVO> trendData = contracts.stream()
//                .collect(Collectors.groupingBy(contract -> {
//                    LocalDate date = contract.getSignTime().toLocalDate();
//                    int quarter = (date.getMonthValue() - 1) / 3 + 1;
//                    return YearQuarter.from(date.withMonth(quarter * 3 - 2));
//                }, TreeMap::new, Collectors.counting()))
//                .entrySet().stream()
//                .map(entry -> new TenantCountTrendVO(
//                        entry.getKey().format(quarterFormatter),
//                        entry.getValue()))
//                .collect(Collectors.toList());
//
//        return R.ok(trendData);
//    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java
@@ -580,6 +580,14 @@
        if (processTaskListBO.getSortBy() == 2) {
            stateTaskQuery.orderByDesc(BaseModel::getCreateTime);
        }
        // 查询合同信息
        List<TContract> tContracts = contractMapper.selectList(Wrappers.<TContract>lambdaQuery()
                .in(TContract::getStatus, 2,3,4));
        List<String> contractIds = tContracts.stream().map(TContract::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(contractIds)){
            return new PageInfo<>();
        }
        stateTaskQuery.in(StateTaskCenter::getProjectId, contractIds);
        stateTaskQuery.in(StateTaskCenter::getFlowId, instanceIds);
        PageInfo pageInfo = new PageInfo(processTaskListBO.getPageNum(), processTaskListBO.getPageSize());
        PageInfo<StateTaskCenter> taskCenters = stateTaskCenterService.page(pageInfo,stateTaskQuery);
@@ -803,6 +811,14 @@
        if (processTaskListBO.getSortBy() == 2) {
            stateTaskQuery.orderByDesc(BaseModel::getCreateTime);
        }
        // 查询合同信息
        List<TContract> tContracts = contractMapper.selectList(Wrappers.<TContract>lambdaQuery()
                .in(TContract::getStatus, 2,3,4));
        List<String> contractIds = tContracts.stream().map(TContract::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(contractIds)){
            return new PageInfo<>();
        }
        stateTaskQuery.in(StateTaskCenter::getProjectId, contractIds);
        stateTaskQuery.in(StateTaskCenter::getFlowId, instanceId);
        PageInfo pageInfo = new PageInfo<>(processTaskListBO.getPageNum(), processTaskListBO.getPageSize());
        PageInfo<StateTaskCenter> taskCenters = stateTaskCenterService.page(pageInfo,stateTaskQuery);
@@ -1004,6 +1020,7 @@
        FlwTask flwTask = flwTaskMapper.selectById(taskId);
        // 直接拒绝当前流程
        flowLongEngine.runtimeService().reject(flwTask.getInstanceId(), currentFlowCreator());
        flwTaskMapper.deleteById(taskId);
        // 动作执行记录
        StateProcessInstanceAction record = new StateProcessInstanceAction();
        record.setId(IdUtils.simpleUUID());
@@ -1334,6 +1351,17 @@
        if (processTaskListBO.getSortBy() == 2) {
            stateTaskQuery.orderByDesc(FlwHisTask::getCreateTime);
        }
        List<TContract> tContracts = contractMapper.selectList(Wrappers.<TContract>lambdaQuery()
                .in(TContract::getStatus, 2,3,4));
        List<String> contractIds = tContracts.stream().map(TContract::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(contractIds)){
            return new PageInfo<>();
        }
        List<StateTaskCenter> list = stateTaskCenterService.list(Wrappers.<StateTaskCenter>lambdaQuery().in(StateTaskCenter::getProjectId, contractIds));
        if(!CollectionUtils.isEmpty(list)){
            List<String> flowIds = list.stream().map(StateTaskCenter::getFlowId).collect(Collectors.toList());
            stateTaskQuery.in(FlwHisTask::getInstanceId, flowIds);
        }
        stateTaskQuery.eq(FlwHisTask::getParentTaskId, 0L);
        stateTaskQuery.like(FlwHisTask::getCreateId, userId);
        PageInfo pageInfo = new PageInfo<>(processTaskListBO.getPageNum(), processTaskListBO.getPageSize());
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateTaskCenterServiceImpl.java
@@ -5,7 +5,6 @@
import com.ruoyi.system.bo.ProcessTaskListBO;
import com.ruoyi.system.mapper.StateTaskCenterMapper;
import com.ruoyi.system.model.StateTaskCenter;
import com.ruoyi.system.model.TFaultAreaDic;
import com.ruoyi.system.service.StateTaskCenterService;
import com.ruoyi.system.vo.ProcessTaskListVO;
import org.springframework.stereotype.Service;
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -1,27 +1,8 @@
package com.ruoyi.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.validation.Validator;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.model.TDept;
import com.ruoyi.system.model.TDeptToUser;
import com.ruoyi.system.query.SysUserQuery;
import com.ruoyi.system.service.TDeptToUserService;
import com.ruoyi.system.vo.SysUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
@@ -33,8 +14,32 @@
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.SysUserPost;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysPostMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserPostMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.mapper.TDeptMapper;
import com.ruoyi.system.mapper.TDeptToUserMapper;
import com.ruoyi.system.model.TDept;
import com.ruoyi.system.model.TDeptToUser;
import com.ruoyi.system.query.SysUserQuery;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.TDeptToUserService;
import com.ruoyi.system.vo.SysUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * 用户 业务层处理
@@ -665,6 +670,8 @@
    @Override
    public PageInfo<SysUserVO> pageList(SysUserQuery query) {
        PageInfo<SysUserVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        query.setBusinessDeptId(businessDeptId);
        List<SysUserVO> list = userMapper.pageList(query,pageInfo);
        if(CollectionUtils.isEmpty(list)){
            return pageInfo;
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBankFlowServiceImpl.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.importExcel.TBankFlowImportExcel;
import com.ruoyi.system.mapper.TBankFlowMapper;
@@ -46,13 +47,14 @@
                .ge(StringUtils.isNotEmpty(query.getPayStartTime()),TBankFlow::getPayTime,query.getPayStartTime())
                .lt(StringUtils.isNotEmpty(query.getPayEndTime()),TBankFlow::getPayTime,query.getPayEndTime())
                .eq(null != query.getFlowStatus(),TBankFlow::getFlowStatus,query.getFlowStatus())
                .eq(StringUtils.isNotEmpty(query.getBusinessDeptId())&& !"0".equals(query.getBusinessDeptId()),TBankFlow::getBusinessDeptId,query.getBusinessDeptId())
                .orderByDesc(TBankFlow::getCreateTime);
        return this.baseMapper.selectPage(pageInfo, queryWrapper);
    }
    @Override
    public TBankFlowStatisticsVo getPaymentStats(TBankFlowQuery query) {
        return this.baseMapper.getPaymentStats(query);
        return this.baseMapper.getPaymentStats(query,SecurityUtils.getBusinessDeptId());
    }
    /**
@@ -62,10 +64,12 @@
     */
    @Override
    public List<TBankFlow> searchByBankSerialNumber(String bankSerialNumber) {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotEmpty(bankSerialNumber),TBankFlow::getBankSerialNumber,bankSerialNumber)
                .eq(StringUtils.isNotEmpty(bankSerialNumber) && !"0".equals(bankSerialNumber),TBankFlow::getBusinessDeptId,businessDeptId)
                .orderByDesc(TBankFlow::getPayTime);
        PageInfo<TBankFlow> pageInfo = new PageInfo<>(1, 20);
        pageInfo = this.baseMapper.selectPage(pageInfo, queryWrapper);
        return pageInfo.getRecords();
@@ -73,6 +77,7 @@
    @Override
    public void saveImportBatch(List<TBankFlowImportExcel> list, List<TBankFlowImportExcel> failList) {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        for (TBankFlowImportExcel row : list) {
            try {
                TBankFlow preexist = findUniq(row.getBankSerialNumber());
@@ -83,6 +88,7 @@
                }
                TBankFlow flow = new TBankFlow();
                BeanUtils.copyProperties(row,flow);
                flow.setBusinessDeptId(businessDeptId);
                try {
                    LocalDateTime parse = LocalDateTime.parse(row.getPayTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    flow.setPayTime(parse);
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -1,24 +1,43 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.config.SmsProperties;
import com.ruoyi.common.constant.AmountConstant;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.DisabledEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.dto.*;
import com.ruoyi.system.dto.BillStatisticsDto;
import com.ruoyi.system.dto.CachPayDto;
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;
import com.ruoyi.system.model.*;
import com.ruoyi.system.model.TBankFlow;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TBillDetail;
import com.ruoyi.system.model.TFlowManagement;
import com.ruoyi.system.model.TInvoiceToBill;
import com.ruoyi.system.model.TOrderBill;
import com.ruoyi.system.model.TPayOrder;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.query.TInvoiceToBillQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.TBankFlowService;
import com.ruoyi.system.service.TBillConfirmService;
import com.ruoyi.system.service.TBillDetailService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TFlowManagementService;
import com.ruoyi.system.service.TInvoiceToBillService;
import com.ruoyi.system.service.TOrderBillService;
import com.ruoyi.system.service.TPayOrderService;
import com.ruoyi.system.vo.ScreenRentRankVO;
import com.taxi591.bankapi.dto.ChargeBillRequest;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -28,7 +47,6 @@
import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
@@ -88,6 +106,12 @@
        return info;
    }
    public PageInfo<TBillDto> queryPageForApplet(TBillQuery query){
        PageInfo<TBill> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        PageInfo<TBillDto> info = tBillMapper.pageForApplet(pageInfo, query);
        return info;
    }
    @Override
    public List<String> getBillIds(TBillQuery query) {
        List<TBillDto> billDtos = tBillMapper.getBillList(query);
@@ -124,11 +148,13 @@
        if (isok){
            try {
                TBill save = new TBill();
                save.setId(tBill.getId());
                TBill presist = getById(tBill.getId());
                //如果账单是已缴费状态,本方法不再进行更新账单
                if (presist.getPayFeesStatus().equals("3")){
                    throw new ServiceException("该账单已缴费完成");
                }
                save.setBusinessDeptId(presist.getBusinessDeptId());
                switch (type){
                    // 仅更新除金额字段外的属性
                    case 1:
@@ -161,6 +187,7 @@
                            BigDecimal outstand = presist.getPayableFeesMoney()
                                    .add(save.getPayableFeesPenalty())
                                    .subtract(presist.getPayFeesMoney());
                            save.setOutstandingMoney(outstand);
                        }
                        //处理缴费金额
@@ -226,6 +253,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBill(TbillSaveDto bill) {
        bill.setManualAddition(DisabledEnum.YES.getCode());
        save(bill);
        if (bill.getBillType().equals("3")){
            if (bill.getDetails()==null || bill.getDetails().size()==0){
@@ -280,6 +308,7 @@
            TFlowManagement save = new TFlowManagement();
            save.setPayType(3);
            save.setPayer(dto.getPayer());
            save.setBusinessDeptId(bill.getBusinessDeptId());
            save.setPayTime(bankflow.getPayTime());
            save.setSysSerialNumber(OrderNos.getDid(30));
            save.setBankSerialNumber(bankflow.getBankSerialNumber());
@@ -305,6 +334,7 @@
        save.setPayType(3);
        save.setPayer(dto.getPayer());
        save.setPayTime(billSave.getPayFeesTime());
        save.setBusinessDeptId(bill.getBusinessDeptId());
        save.setSysSerialNumber(OrderNos.getDid(30));
        save.setFlowType(1);
        save.setPaymentBillId(back.getId());
@@ -323,62 +353,67 @@
        String uuid = UUID.fastUUID().toString();
        boolean lock = redisCache.trylockLoop(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo, uuid, 60);
        if (lock){
            TPayOrder order = tPayOrderService.getById(orderNo);
            if (order==null){
                throw new ServiceException("订单不存在");
            }
            if (StringUtils.isNotEmpty(order.getPayNo())){
                log.info("订单号已处理:{}",orderNo);
                return;
            }
            /**
             * 更新订单状态
             */
            TPayOrder save = new TPayOrder();
            save.setId(order.getId());
            save.setStatus(1);
            save.setPayNo(billRequest.getMessage().getInfo().getTraceNo());
            save.setPayType(billRequest.getMessage().getHead().getChannel());
            try {
                save.setPayTime(DateUtils.parseDate(billRequest.getMessage().getHead().getTimeStamp(),"yyyyMMddHHmmssSSS"));
            } catch (ParseException e) {
                throw new ServiceException("日期格式化错误");
                TPayOrder order = tPayOrderService.getById(orderNo);
                if (order==null){
                    throw new ServiceException("订单不存在");
                }
                if (StringUtils.isNotEmpty(order.getPayNo())){
                    log.info("订单号已处理:{}",orderNo);
                    return;
                }
                /**
                 * 更新订单状态
                 */
                TPayOrder save = new TPayOrder();
                save.setId(order.getId());
                save.setStatus(1);
                save.setPayNo(billRequest.getMessage().getInfo().getTraceNo());
                save.setPayType(billRequest.getMessage().getHead().getChannel());
                try {
                    save.setPayTime(DateUtils.parseDate(billRequest.getMessage().getHead().getTimeStamp(),"yyyyMMddHHmmssSSS"));
                } catch (ParseException e) {
                    throw new ServiceException("日期格式化错误");
                }
                save.setCallbackTime(new Date());
                BigDecimal payAmount = new BigDecimal(billRequest.getMessage().getInfo().getPayBillAmt());
                save.setActPayAmount(payAmount
                        .multiply(AmountConstant.b100).longValue());
                save.setStatus(1);
                save.setPayInfo(billRequest.getMessage().toString());
                tPayOrderService.updateById(save);
                /**
                 * 更新账单状态
                 */
                List<TOrderBill> orderBills = orderBillService.getByOrderNo(order.getId());
                List<TBill> bills = orderBills.stream().map(ob -> getById(ob.getBillId())).collect(Collectors.toList());
                lockAndUpdateByAmountBatch(bills,payAmount,(bill)->{
                    TFlowManagement saveFlow = new TFlowManagement();
                    saveFlow.setPayType(1);
                    saveFlow.setPayer(order.getUserId());
                    saveFlow.setBusinessDeptId(bill.getBusinessDeptId());
                    saveFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
                    saveFlow.setSysSerialNumber(OrderNos.getDid(30));
                    saveFlow.setBankSerialNumber(save.getPayNo());
                    saveFlow.setFlowType(2);
                    saveFlow.setPaymentBillId(bill.getId());
                    saveFlow.setDeductionMoney(bill.getDeductionMoney());
                    saveFlow.setFlowMoney(payAmount);
                    saveFlow.setRemainingMoney(bill.getOutstandingMoney());
                    saveFlow.setPreOutstand(bill.getPreOutstand());
                    tFlowManagementService.save(saveFlow);
                });
//                TBankFlow bankFlow = new TBankFlow();
//                bankFlow.setPayType(1);
//                bankFlow.setPayer(order.getUserId());
//                bankFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
//                bankFlow.setBankSerialNumber(save.getPayNo());
//                bankFlow.setFlowMoney(payAmount);
//                bankFlow.setFlowStatus(1);
//                tBankFlowService.save(bankFlow);
            }finally {
                redisCache.unlock(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo,uuid);
            }
            save.setCallbackTime(new Date());
            BigDecimal payAmount = new BigDecimal(billRequest.getMessage().getInfo().getPayBillAmt());
            save.setActPayAmount(payAmount
                    .multiply(AmountConstant.b100).longValue());
            save.setStatus(1);
            save.setPayInfo(billRequest.getMessage().toString());
            tPayOrderService.updateById(save);
            /**
             * 更新账单状态
             */
            List<TOrderBill> orderBills = orderBillService.getByOrderNo(order.getId());
            List<TBill> bills = orderBills.stream().map(ob -> getById(ob.getBillId())).collect(Collectors.toList());
            lockAndUpdateByAmountBatch(bills,payAmount,(bill)->{
                TFlowManagement saveFlow = new TFlowManagement();
                saveFlow.setPayType(1);
                saveFlow.setPayer(order.getUserId());
                saveFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
                saveFlow.setSysSerialNumber(OrderNos.getDid(30));
                saveFlow.setBankSerialNumber(save.getPayNo());
                saveFlow.setFlowType(2);
                saveFlow.setPaymentBillId(bill.getId());
                saveFlow.setDeductionMoney(bill.getDeductionMoney());
                saveFlow.setFlowMoney(payAmount);
                saveFlow.setRemainingMoney(bill.getOutstandingMoney());
                saveFlow.setPreOutstand(bill.getPreOutstand());
                tFlowManagementService.save(saveFlow);
            });
            TBankFlow bankFlow = new TBankFlow();
            bankFlow.setPayType(1);
            bankFlow.setPayer(order.getUserId());
            bankFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
            bankFlow.setBankSerialNumber(save.getPayNo());
            bankFlow.setFlowMoney(payAmount);
            bankFlow.setFlowStatus(1);
            tBankFlowService.save(bankFlow);
        }
@@ -524,6 +559,7 @@
        TFlowManagement save = new TFlowManagement();
        save.setPayType(3);
        save.setPayer(dto.getPayer());
        save.setBusinessDeptId(bill.getBusinessDeptId());
        save.setPayTime(bankflow!=null?bankflow.getPayTime():DateUtils.dateToLocalDateTime(new Date()));
        save.setSysSerialNumber(OrderNos.getDid());
        save.setBankSerialNumber(bankflow!=null?bankflow.getBankSerialNumber():null);
@@ -538,12 +574,12 @@
    }
    @Override
    public BillStatisticsDto statistics() {
    public BillStatisticsDto statistics(TBillQuery query) {
        BillStatisticsDto dto = new BillStatisticsDto();
        dto.setRent(getBaseMapper().statisticsAllRent());
        dto.setNopay(getBaseMapper().statisticsNoPay());
        dto.setPayed(getBaseMapper().statisticsPayed());
        dto.setOverdue(getBaseMapper().statisticsOverdue());
        dto.setRent(getBaseMapper().statisticsAllRent(query));
        dto.setNopay(getBaseMapper().statisticsNoPay(query));
        dto.setPayed(getBaseMapper().statisticsPayed(query));
        dto.setOverdue(getBaseMapper().statisticsOverdue(query));
        return dto;
    }
@@ -552,5 +588,84 @@
        return this.baseMapper.batchBillCount(userId,billIds);
    }
    /**
     * 街道租金排行
     * @return
     */
    @Override
    public List<ScreenRentRankVO> getStreetRentRank(String businessDeptId) {
        return baseMapper.getStreetRentRank(businessDeptId);
    }
    /**
     * 查询季付账单
     * @param businessDeptId
     * @return
     */
    @Override
    public List<TBill> getJiFuBillList(String businessDeptId) {
        return baseMapper.getJiFuBillList(businessDeptId,null,null);
    }
    /**
     * 查询当前季度的季付账单
     * @param businessDeptId
     * @param first
     * @param last
     * @return
     */
    @Override
    public List<TBill> getJiFuBillListByTime(String businessDeptId, Date first, Date last) {
        return baseMapper.getJiFuBillList(businessDeptId,first,last);
    }
    @Override
    public void editAmount(TbillSaveDto bill) {
        String requestId = UUID.fastUUID().toString();
        String lockkey = CacheConstants.BILL_UPDATE_LOCK_KEY + bill.getId();
        boolean isok = redisCache.trylockLoop(lockkey, requestId, 60);
        if (isok){
            try {
                TBill presist = getById(bill.getId());
                TBill save = new TBill();
                save.setId(bill.getId());
                BigDecimal preOutstand = presist.getOutstandingMoney();
                // 如果传入的金额小于0,则是扣减,如果大于0,是增加金额,增加金额只加入欠费金额中
                if (bill.getEditAmount().compareTo(BigDecimal.ZERO)<0
                        && presist.getPayableFeesPenalty().compareTo(BigDecimal.ZERO)>0){
                    BigDecimal prePayableFeesPenalty = presist.getPayableFeesPenalty();
                    //违约金大于调整金额,够减
                    if (prePayableFeesPenalty.compareTo(bill.getEditAmount().abs())>=0){
                        BigDecimal afterPenalty = prePayableFeesPenalty.add(bill.getEditAmount());
                        save.setPayableFeesPenalty(afterPenalty);
                    }else{
                        BigDecimal afterPenalty = BigDecimal.ZERO;
                        save.setPayableFeesPenalty(afterPenalty);
                    }
                }
                BigDecimal afterOutstand = preOutstand.add(bill.getEditAmount());
                save.setOutstandingMoney(afterOutstand);
                updateById(save);
            }finally {
                redisCache.unlock(lockkey,requestId);
            }
        }
        //todo 记录金额修改记录
//        TFlowManagement flow = new TFlowManagement();
//        flow.setPayType(3);
//        flow.setPayer("管理员修改");
//        flow.setBusinessDeptId(presist.getBusinessDeptId());
//        flow.setPayTime(DateUtils.dateToLocalDateTime(new Date()));
//        flow.setSysSerialNumber(OrderNos.getDid(30));
//        flow.setFlowType(1);
//        flow.setPaymentBillId(back.getId());
//        flow.setDeductionMoney(back.getDeductionMoney());
//        flow.setFlowMoney(save.getOutstandingMoney());
//        flow.setRemainingMoney(back.getOutstandingMoney());
//        flow.setPreOutstand(back.getPreOutstand());
//        flow.setCreateBy(SecurityUtils.getUsername());
//        tFlowManagementService.save(flow);
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBusinessDeptServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.system.service.impl;
import com.ruoyi.system.model.TBusinessDept;
import com.ruoyi.system.mapper.TBusinessDeptMapper;
import com.ruoyi.system.service.ITBusinessDeptService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 营业部 服务实现类
 * </p>
 *
 * @author mitao
 * @since 2025-03-24
 */
@Service
public class TBusinessDeptServiceImpl extends ServiceImpl<TBusinessDeptMapper, TBusinessDept> implements ITBusinessDeptService {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
@@ -1,8 +1,12 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.TCheckAcceptRecordMapper;
import com.ruoyi.system.mapper.TContractMapper;
import com.ruoyi.system.mapper.THouseMapper;
@@ -11,15 +15,15 @@
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.query.TCheckAcceptRecordAppletQuery;
import com.ruoyi.system.query.TCheckAcceptRecordQuery;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.TCheckAcceptRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.vo.SysUserVO;
import com.ruoyi.system.vo.TCheckAcceptRecordVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
/**
 * <p>
@@ -36,9 +40,13 @@
    private TContractMapper contractMapper;
    @Autowired
    private THouseMapper houseMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Override
    public PageInfo<TCheckAcceptRecordVO> pageList(TCheckAcceptRecordQuery query) {
        PageInfo<TCheckAcceptRecordVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        query.setBusinessDeptId(businessDeptId);
        List<TCheckAcceptRecordVO> list = this.baseMapper.pageList(query,pageInfo);
        list.forEach(item -> {
            item.setCleanSituation(StringUtils.hasLength(item.getCleanSituation()) ?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation())):"");
@@ -53,8 +61,14 @@
    @Override
    public PageInfo<TCheckAcceptRecordVO> pageListApplet(TCheckAcceptRecordAppletQuery query) {
        List<TContract> tContracts = contractMapper.selectList(null);
        List<THouse> tHouses = houseMapper.selectList(null);
        SysUser sysUser = sysUserService.selectUserById(Long.valueOf(query.getSysUserId()));
        String businessDeptId = "";
        if (Objects.nonNull(sysUser) && !sysUser.getBusinessDeptId().equals("0")){
            businessDeptId = sysUser.getBusinessDeptId();
            query.setBusinessDeptId(businessDeptId);
        }
        List<TContract> tContracts = contractMapper.selectList(new LambdaQueryWrapper<TContract>().eq(StringUtils.hasLength(businessDeptId),TContract::getBusinessDeptId,businessDeptId));
        List<THouse> tHouses = houseMapper.selectList(new LambdaQueryWrapper<THouse>().eq(StringUtils.hasLength(businessDeptId),THouse::getBusinessDeptId,businessDeptId));
        PageInfo<TCheckAcceptRecordVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<TCheckAcceptRecordVO> list = this.baseMapper.pageListApplet(query,pageInfo);
        list.forEach(item -> {
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
@@ -4,11 +4,13 @@
import com.aizuda.bpm.mybatisplus.mapper.FlwHisTaskMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.ProcessCategoryEnum;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.bo.ProcessStartBO;
import com.ruoyi.system.dto.SignContractDTO;
@@ -17,7 +19,9 @@
import com.ruoyi.system.mapper.TCheckAcceptRecordMapper;
import com.ruoyi.system.mapper.TContractMapper;
import com.ruoyi.system.mapper.THouseMapper;
import com.ruoyi.system.model.*;
import com.ruoyi.system.model.TCheckAcceptRecord;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.query.TContractAppletQuery;
import com.ruoyi.system.query.TContractBillQuery;
import com.ruoyi.system.query.TContractQuery;
@@ -25,21 +29,18 @@
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractRentTypeService;
import com.ruoyi.system.service.TContractService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.vo.BillVO;
import com.ruoyi.system.vo.CheckAcceptRecordVO;
import com.ruoyi.system.vo.ScreenRentIncomeTrendVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * <p>
@@ -69,7 +70,9 @@
    @Override
    public PageInfo<TContract> contractList(TContractQuery query) {
        PageInfo<TContract> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<TContract> list = this.baseMapper.contractList(query,pageInfo);
        //获取当前登录用户信息
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        List<TContract> list = this.baseMapper.contractList(query,pageInfo,businessDeptId);
        for (TContract tContract : list) {
            tContract.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE,tContract.getPayType()));
            tContract.setStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_STATUS,tContract.getStatus()));
@@ -90,7 +93,9 @@
        PageInfo<TContract> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<TContract> list = this.baseMapper.contractAppletList(query,pageInfo);
        for (TContract tContract : list) {
            tContract.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE,tContract.getPayType()));
            tContract.setPayType(
                    DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE, tContract.getPayType())
            );
            tContract.setStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_STATUS,tContract.getStatus()));
            FlwHisTask flwHisTask = flwHisTaskMapper.selectOne(new LambdaQueryWrapper<FlwHisTask>()
                    .like(FlwHisTask::getVariable, tContract.getId())
@@ -120,6 +125,7 @@
    public void terminateContract(TerminateContractDTO dto) {
        TContract contract = this.baseMapper.selectById(dto.getId());
        contract.setTerminateRemark(dto.getTerminateRemark());
        contract.setTerminateTime(dto.getTerminateTime());
        this.baseMapper.updateById(contract);
        // 进入合同提前终止审批流程
        ProcessStartBO processStartBO = new ProcessStartBO();
@@ -195,7 +201,27 @@
    @Override
    public Boolean updateContractAuditStatus(String projectId, Integer status) {
        LambdaUpdateWrapper<TContract> contractLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        contractLambdaUpdateWrapper.eq(TContract::getId, projectId).set(TContract::getStatus, status);
        contractLambdaUpdateWrapper
                .eq(TContract::getId, projectId)
                .set(TContract::getStatus, status)
                .set(TContract::getSignTime, LocalDateTime.now());
        return this.update(contractLambdaUpdateWrapper);
    }
    /**
     * 本月新增租户数
     * @return
     */
    @Override
    public Integer getCurrentMonthRentCount(String businessDeptId) {
        return baseMapper.getCurrentMonthRentCount(businessDeptId);
    }
    @Override
    public PageInfo<TContract> queryPage(TContractQuery query) {
        PageInfo<TContract> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        pageInfo = this.baseMapper.page(pageInfo,query);
        return pageInfo;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java
@@ -1,13 +1,13 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.TFaultRepairMessageMapper;
import com.ruoyi.system.model.TFaultRepairMessage;
import com.ruoyi.system.query.TFaultRepairMessageAppletQuery;
import com.ruoyi.system.query.TFaultRepairMessageQuery;
import com.ruoyi.system.service.TFaultRepairMessageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.vo.SysOperLogVO;
import com.ruoyi.system.vo.TFaultRepairMessageVO;
import org.springframework.stereotype.Service;
@@ -31,6 +31,8 @@
    @Override
    public PageInfo<TFaultRepairMessageVO> pageList(TFaultRepairMessageQuery query) {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        query.setBusinessDeptId(businessDeptId);
        PageInfo<TFaultRepairMessageVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<TFaultRepairMessageVO> list = this.baseMapper.pageList(query,pageInfo);
        pageInfo.setRecords(list);
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFlowManagementServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.TFlowManagementMapper;
import com.ruoyi.system.model.TFlowManagement;
@@ -34,6 +35,7 @@
                .ge(StringUtils.isNotEmpty(query.getPayStartTime()),TFlowManagement::getPayTime,query.getPayStartTime())
                .lt(StringUtils.isNotEmpty(query.getPayEndTime()),TFlowManagement::getPayTime,query.getPayEndTime())
                .eq(null != query.getPayType(),TFlowManagement::getPayType,query.getPayType())
                .eq(StringUtils.isNotEmpty(query.getBusinessDeptId()) && !"0".equals(query.getBusinessDeptId()),TFlowManagement::getBusinessDeptId,query.getBusinessDeptId())
                .orderByDesc(TFlowManagement::getCreateTime)
        ;
        return this.baseMapper.selectPage(pageInfo,queryWrapper);
@@ -41,7 +43,7 @@
    @Override
    public TFlowManagementStatisticsVo getPaymentStats(TFlowManagementQuery query) {
        return this.baseMapper.getPaymentStats(query);
        return this.baseMapper.getPaymentStats(query, SecurityUtils.getBusinessDeptId());
    }
    @Override
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java
@@ -1,9 +1,11 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.TContractMapper;
import com.ruoyi.system.mapper.THouseMapper;
@@ -12,12 +14,12 @@
import com.ruoyi.system.query.THouseQuery;
import com.ruoyi.system.query.TUserHistoryQuery;
import com.ruoyi.system.service.THouseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.vo.HouseVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
@@ -34,10 +36,13 @@
    private TContractMapper contractMapper;
    @Override
    public PageInfo<THouse> houseList(THouseQuery query) {
        //查询当前登录用户所属部门
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        query.setBusinessDeptId(businessDeptId);
        PageInfo<THouse> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<THouse> list = this.baseMapper.houseList(query,pageInfo);
        List<TContract> tContracts = contractMapper.selectList(new LambdaQueryWrapper<TContract>()
                .eq(TContract::getStatus, 4)
                .in(TContract::getStatus, Arrays.asList(4,6,7))
                .le(TContract::getStartTime, LocalDateTime.now())
                .ge(TContract::getEndTime, LocalDateTime.now()));
        for (THouse tHouse : list) {
@@ -46,10 +51,16 @@
            if (tContract!=null){
                tHouse.setTenantType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE,tContract.getPayType()));
//                tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,"2"));
                tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,"2"));
            }else{
//                tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
                if (tHouse.getLeaseStatus().equals("3")){
                    tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
                }else{
                    tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,"1"));
                }
            }
                            tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
        }
        pageInfo.setRecords(list);
@@ -67,4 +78,14 @@
        pageInfo.setRecords(list);
        return pageInfo;
    }
    /**
     * 获取本季度已出租面积
     *
     * @param businessDeptId
     * @return
     */
    @Override
    public Double getRentedArea(String businessDeptId) {
        return baseMapper.getRentedArea(businessDeptId);
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceServiceImpl.java
@@ -53,12 +53,13 @@
                .eq(null != query.getStatus(),TInvoice::getStatus,query.getStatus())
                .ge(StringUtils.isNotEmpty(query.getInvoiceStartTime()),TInvoice::getInvoiceTime,query.getInvoiceStartTime())
                .le(StringUtils.isNotEmpty(query.getInvoiceEndTime()),TInvoice::getInvoiceTime,query.getInvoiceEndTime())
                .eq(StringUtils.isNotEmpty(query.getBusinessDeptId())&& ! "0".equals(query.getBusinessDeptId()),TInvoice::getBusinessDeptId,query.getBusinessDeptId())
                .orderByDesc(TInvoice::getCreateTime);
        return this.baseMapper.selectList(queryWrapper);
    }
    @Override
    public Boolean uploadVoucher(TInvoiceQuery query) {
    public Boolean uploadVoucher(TInvoiceQuery query, List<Map<String, String>> map) {
        // 检查是否存在对应的发票记录
        TInvoice preexist = getById(query.getId());
        if (preexist == null) {
@@ -73,77 +74,15 @@
        tInvoice.setInvoiceVoucherName(query.getInvoiceVoucherName());
        tInvoice.setInvoiceTime(query.getInvoiceTime());
        tInvoice.setStatus(2);
        // 处理附件信息
        List<Map<String, String>> attachments = buildAttachments(query.getInvoiceVoucher(), query.getInvoiceVoucherName());
        if (attachments.isEmpty()) {
            log.warn("未找到有效的附件信息");
            return updateById(tInvoice);
        }
        // 异步发送邮件
        CompletableFuture.runAsync(() -> {
            try {
                mailUtil.sendInvoice(preexist.getEmail(), attachments);
                mailUtil.sendInvoice(preexist.getEmail(), map);
            } catch (ServiceException e) {
                log.error("邮件发送失败", e);
            }
        });
        // 更新数据库
        return updateById(tInvoice);
    }
    private List<Map<String, String>> buildAttachments(String invoiceVoucher, String invoiceVoucherName) {
        if (invoiceVoucher == null || invoiceVoucherName == null) {
            return Collections.emptyList();
        }
        String[] voucherUrls = invoiceVoucher.split(",");
        String[] voucherNames = invoiceVoucherName.split(",");
        // 确保两个数组长度一致
        int length = Math.min(voucherUrls.length, voucherNames.length);
        if (length == 0) {
            return Collections.emptyList();
        }
        // 构建附件列表
        List<Map<String, String>> attachments = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            Map<String, String> attachment = new HashMap<>(2); // 初始容量为2,避免扩容
            attachment.put("url", voucherUrls[i]);
            attachment.put("fileName", voucherNames[i]);
            attachments.add(attachment);
        }
        return attachments;
    }
    // @Override
    // public Boolean uploadVoucher(TInvoiceQuery query) {
    //     TInvoice preexist = getById(query.getId());
    //     if (preexist == null){
    //         return false;
    //     }
    //     TInvoice tInvoice = new TInvoice();
    //     tInvoice.setId(query.getId());
    //     tInvoice.setInvoiceVoucher(query.getInvoiceVoucher());
    //     tInvoice.setInvoiceVoucherName(query.getInvoiceVoucherName());
    //     tInvoice.setInvoiceTime(query.getInvoiceTime());
    //     tInvoice.setStatus(2);
    //     List<Map<String, String>> mapArrayList = new ArrayList<>();
    //     String invoiceVoucher = query.getInvoiceVoucher();
    //     String invoiceVoucherName = query.getInvoiceVoucherName();
    //
    //     List<String> list = Arrays.stream(invoiceVoucher.split(",")).collect(Collectors.toList());
    //     for (int i = 0; i < list.size()-1; i++) {
    //         Map<String, String> map = new HashMap<>();
    //         map.put("url", list.get(i));
    //         map.put("fileName",invoiceVoucherName.split(",")[i]);
    //         mapArrayList.add(map);
    //     }
    //     mailUtil.sendInvoice(preexist.getEmail(),mapArrayList);
    //     return updateById(tInvoice);
    // }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TRentalReturnRecordServiceImpl.java
New file
@@ -0,0 +1,122 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUserApplet;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.enums.ProcessCategoryEnum;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.bo.ProcessStartBO;
import com.ruoyi.system.mapper.TRentalReturnRecordMapper;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.TRentalReturnRecord;
import com.ruoyi.system.query.RentalReturnAuditQuery;
import com.ruoyi.system.query.RentalReturnRecordQuery;
import com.ruoyi.system.service.ITRentalReturnRecordService;
import com.ruoyi.system.service.StateProcessTemplateService;
import com.ruoyi.system.service.TContractService;
import com.ruoyi.system.service.THouseService;
import com.ruoyi.system.vo.RentalRetureApplyVO;
import com.ruoyi.system.vo.RentalReturnRecordVO;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Service
@RequiredArgsConstructor(onConstructor_ = @__(@Lazy))
public class TRentalReturnRecordServiceImpl extends ServiceImpl<TRentalReturnRecordMapper, TRentalReturnRecord>
        implements ITRentalReturnRecordService {
    private final TContractService contractService;
    private final StateProcessTemplateService stateProcessTemplateService;
    private final THouseService houseService;
    @Override
    public IPage<RentalReturnRecordVO> queryRentalReturnRecordList(Page<RentalReturnRecordVO> page, RentalReturnRecordQuery query) {
        String businessDeptId = SecurityUtils.getBusinessDeptId();
        query.setBusinessDeptId(businessDeptId);
        query.setIsAdminDelete(true);
        return this.baseMapper.queryRentalReturnRecordList(page, query);
    }
    @Override
    public RentalReturnRecordVO queryRentalReturnRecordById(String id) {
        return this.baseMapper.queryRentalReturnRecordById(id);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(RentalRetureApplyVO rentalReture,String tenantId) {
        TContract contract = contractService.getById(rentalReture.getContractId());
        if (contract == null) {
            throw new ServiceException("该房屋暂无合同");
        }
        TRentalReturnRecord tRentalReturnRecord = new TRentalReturnRecord();
        tRentalReturnRecord.setTenantId(tenantId);
        tRentalReturnRecord.setHouseId(contract.getHouseId());
        tRentalReturnRecord.setContractId(contract.getId());
        tRentalReturnRecord.setReasonForReturn(rentalReture.getReasonForReturn());
        tRentalReturnRecord.setImages(rentalReture.getImages());
        tRentalReturnRecord.setAuditStatus(1);
        save(tRentalReturnRecord);
        boolean update = houseService.update(new LambdaUpdateWrapper<THouse>()
                .set(THouse::getRentalReturnStatus, "2")
                .eq(THouse::getId, contract.getHouseId()));
        if (!update){
            throw new ServiceException("更新房屋状态失败");
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(RentalReturnAuditQuery returnAuditQuery, Long userId,String userName) {
        TRentalReturnRecord record = getById(returnAuditQuery.getId());
        if (record == null){
            throw new ServiceException("申请记录不存在");
        }
        if (record.getAuditStatus() != 1){
            throw new ServiceException("申请记录已审核");
        }
        THouse house = houseService.getById(record.getHouseId());
        if (returnAuditQuery.getAuditResult() == 2){
            TContract contract = contractService.getById(record.getContractId());
            contract.setTerminateRemark(returnAuditQuery.getAuditOpinion());
            contract.setTerminateTime(record.getCreateTime());
            contractService.updateById(contract);
            // 进入合同提前终止审批流程
            ProcessStartBO processStartBO = new ProcessStartBO();
            processStartBO.setCategory(ProcessCategoryEnum.CATEGORY3.getValue().toString());
            processStartBO.setModuleName("合同提前终止审批");
            processStartBO.setName(contract.getContractName());
            processStartBO.setRemark("");
            Map<String, Object> variable = new HashMap<>();
            variable.put("projectId", record.getContractId());
            processStartBO.setVariable(variable);
            //开启工作流程
            stateProcessTemplateService.start(processStartBO);
            house.setRentalReturnStatus("3");
            houseService.updateById(house);
        }else {
            house.setRentalReturnStatus("1");
            houseService.updateById(house);
        }
        record.setAuditTime(LocalDateTime.now());
        record.setAuditStatus(returnAuditQuery.getAuditResult());
        record.setAuditOpinion(returnAuditQuery.getAuditOpinion());
        record.setAuditUserId(userId);
        record.setUpdateBy(userName);
        record.setUpdateTime(LocalDateTime.now());
        updateById(record);
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TStreetServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.system.service.impl;
import com.ruoyi.system.model.TStreet;
import com.ruoyi.system.mapper.TStreetMapper;
import com.ruoyi.system.service.ITStreetService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 街道 服务实现类
 * </p>
 *
 * @author mitao
 * @since 2025-03-19
 */
@Service
public class TStreetServiceImpl extends ServiceImpl<TStreetMapper, TStreet> implements ITStreetService {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java
@@ -8,12 +8,10 @@
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TTenantDTO;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.TContractMapper;
import com.ruoyi.system.mapper.THouseMapper;
import com.ruoyi.system.mapper.TTenantMapper;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.TDept;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.model.TTenant;
import com.ruoyi.system.query.TBillAppletQuery;
@@ -25,7 +23,6 @@
import com.ruoyi.system.vo.TBillVO;
import com.ruoyi.system.vo.TenantVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.token.TokenService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -51,7 +48,15 @@
    @Override
    public PageInfo<TenantVO> pageList(TTenantQuery query) {
        PageInfo<TenantVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<TenantVO> list = this.baseMapper.pageList(query,pageInfo);
 /*       String businessDeptId = SecurityUtils.getBusinessDeptId();
        List<TenantVO> list = null;
        if (StringUtils.isBlank(businessDeptId) || "0".equals(businessDeptId)) {
            list = this.baseMapper.pageList(query, pageInfo);
        } else {
            query.setBusinessDeptId(businessDeptId);
            list = this.baseMapper.pageListByBusinessDeptId(query,pageInfo);
        }*/
        List<TenantVO> list = this.baseMapper.pageList(query, pageInfo);
        for (TenantVO tenantVO : list) {
            tenantVO.setTenantAttributesName(StringUtils.isNotBlank(tenantVO.getTenantAttributes())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_ATTRIBUTE,tenantVO.getTenantAttributes()):"");
            tenantVO.setTenantTypeName(StringUtils.isNotBlank(tenantVO.getTenantType())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_TYPE,tenantVO.getTenantType()):"");
ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java
@@ -2,6 +2,9 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.mapper.TBillMapper;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TContract;
@@ -27,6 +30,8 @@
    private TContractService contractService;
    @Autowired
    private TBillMapper billMapper;
    @Autowired
    RedisCache redisCache;
    // 用于更新违约金账单
    // 每分钟执行一次的定时任务
@@ -34,8 +39,8 @@
    public void dayOfProportionBill() {
        try {
            // 查询所有未缴费账单
            List<TBill> list = billMapper.selectList(new LambdaQueryWrapper<TBill>().eq(TBill::getPayFeesStatus, 1)
                    .le(TBill::getPayableFeesTime,LocalDate.now()));
            List<TBill> list = billMapper.selectList(new LambdaQueryWrapper<TBill>().ne(TBill::getPayFeesStatus, 5)
                    .ne(TBill::getOutstandingMoney,0));
            for (TBill tBill : list) {
                tBill.setPayFeesStatus("4");
                TContract contract = contractService.getById(tBill.getContractId());
@@ -50,18 +55,26 @@
                    // 违约金比例
                    BigDecimal proportion = contract.getProportion();
                    // 按每天 待缴费金额 * XX% 增加违约金费用
                    if (tBill.getOutstandingMoney().compareTo(new BigDecimal("0"))==0){
                    if (contract.getTotalYear().compareTo(new BigDecimal("0"))==0){
                        tBill.setPayFeesStatus("3");
                        billMapper.updateById(tBill);
                        continue;
                    }
                    BigDecimal money = tBill.getOutstandingMoney().multiply(new BigDecimal(100).add(proportion)).divide(new BigDecimal(100),2, BigDecimal.ROUND_DOWN);
                    tBill.setOverDays((int) l);
                    BigDecimal bigDecimal = tBill.getOutstandingMoney().multiply(proportion).setScale(2, BigDecimal.ROUND_DOWN);
                    tBill.setPayableFeesPenalty(tBill.getPayableFeesPenalty()!=null?tBill.getPayableFeesPenalty():new BigDecimal("0").add(bigDecimal));
                    tBill.setOutstandingMoney(money);
                    billMapper.updateById(tBill);
                    String requestId = UUID.fastUUID().toString();
                    String lockkey = CacheConstants.BILL_UPDATE_LOCK_KEY + tBill.getId();
                    boolean isok = redisCache.trylockLoop(lockkey, requestId, 60);
                    if (isok){
                        try {
                            BigDecimal money = tBill.getOutstandingMoney().multiply(new BigDecimal(100).add(proportion)).divide(new BigDecimal(100),2, BigDecimal.ROUND_DOWN);
                            tBill.setOverDays((int) l);
                            BigDecimal bigDecimal = tBill.getOutstandingMoney().multiply(proportion).setScale(2, BigDecimal.ROUND_DOWN);
                            tBill.setPayableFeesPenalty(tBill.getPayableFeesPenalty()!=null?tBill.getPayableFeesPenalty():new BigDecimal("0").add(bigDecimal));
                            tBill.setOutstandingMoney(money);
                            billMapper.updateById(tBill);
                        }finally {
                            redisCache.unlock(lockkey,requestId);
                        }
                    }
                }
            }
        } catch (Exception e) {
ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseMapDistributionVO.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
@ApiModel("房屋分布")
public class HouseMapDistributionVO {
    @ApiModelProperty(value = "房屋名称")
    private String houseName;
    @ApiModelProperty(value = "房屋地址")
    private String houseAddress;
    @ApiModelProperty(value = "房屋状态 1=待出租 2=已出租 3=维修中 4=欠费")
    private String houseStatus;
    @ApiModelProperty(value = "租户")
    private String tenant;
    @ApiModelProperty(value = "租金状态")
    private String rentStatus;
    @ApiModelProperty(value = "本季租金")
    private String rent;
    @ApiModelProperty(value = "经度")
    private BigDecimal longitude;
    @ApiModelProperty(value = "纬度")
    private BigDecimal latitude;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/MyHouseVO.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.system.model.TBill;
import io.swagger.annotations.ApiModel;
@@ -35,6 +36,8 @@
    private String propertyRightPerson;
    @ApiModelProperty(value = "房东联系方式")
    private String phone;
    @ApiModelProperty(value = "退租状态 1=未退租 2=退租申请中 3=已退租")
    private String rentalReturnStatus;
    @ApiModelProperty(value = "交租记录")
    private List<PayListVO> payList;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/RealTimeRentDataVO.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "实时租赁数据")
public class RealTimeRentDataVO {
    @ApiModelProperty(value = "街道名称")
    private String streetName;
    @ApiModelProperty(value = "房间名称")
    private String roomName;
    @ApiModelProperty(value = "租赁状态 1=待出租 2=已出租 3=维修中")
    private String leaseStatus;
    public RealTimeRentDataVO(String streetName, String roomName, String leaseStatus) {
        this.streetName = streetName;
        this.roomName = roomName;
        this.leaseStatus = leaseStatus;
    }
    public RealTimeRentDataVO() {
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/RentalRetureApplyVO.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("退租申请")
public class RentalRetureApplyVO {
    /**
     * 合同id
     */
    @ApiModelProperty(value = "合同id")
    private String contractId;
    /**
     * 退租说明
     */
    @ApiModelProperty(value = "退租说明")
    private String reasonForReturn;
    /**
     * 图片
     */
    @ApiModelProperty(value = "图片")
    private String images;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/RentalReturnRecordVO.java
New file
@@ -0,0 +1,90 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
@ApiModel("退租记录")
public class RentalReturnRecordVO {
    /**
     * 退租记录id
     */
    @ApiModelProperty(value = "退租记录id")
    private String id;
    /**
     * 提交时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "提交时间")
    private LocalDateTime applicationDate;
    /**
     * 房屋名称
     */
    @ApiModelProperty(value = "房屋名称")
    private String houseName;
    /**
     * 房屋地址
     */
    @ApiModelProperty(value = "房屋地址")
    private String houseAddress;
    /**
     * 租赁合同编号
     */
    @ApiModelProperty(value = "租赁合同编号")
    private String contractNumber;
    /**
     * 图片
     */
    @ApiModelProperty(value = "图片")
    private String images;
    /**
     * 提交人
     */
    @ApiModelProperty(value = "提交人")
    private String submitter;
    /**
     * 联系方式
     */
    @ApiModelProperty(value = "联系方式")
    private String submitterPhone;
    /**
     * 退租说明
     */
    @ApiModelProperty(value = "退租说明")
    private String reasonForReturn;
    /**
     * 验收状态
     */
    @ApiModelProperty(value = "验收状态: 1-待审核 2-审核通过 3-审核驳回")
    private String auditStatus;
    /**
     * 提交时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "提交时间")
    private LocalDateTime createTime;
    /**
     * 审批意见
     */
    @ApiModelProperty(value = "审批意见")
    private String auditOpinion;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenRentIncomeTrendVO.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
 * @author mitao
 * @date 2025/3/20
 */
@Data
@ApiModel("租金收入区域视图对象")
public class ScreenRentIncomeTrendVO {
    @ApiModelProperty("x轴 时间列表")
    private List<String> quarters;
    @ApiModelProperty("y轴 收入列表(万元)")
    private List<BigDecimal> incomeData;
    @ApiModelProperty("y轴 欠费列表(万元)")
    private List<BigDecimal> outstandingData;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenRentRankVO.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author mitao
 * @date 2025/3/19
 */
@Data
@ApiModel("区域租金排名")
public class ScreenRentRankVO {
    @ApiModelProperty("街道名称")
    private String streetName;
    @ApiModelProperty("租金")
    private BigDecimal rentAmount;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/ScreenTopStaticsDataVO.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author mitao
 * @date 2025/3/19
 */
@Data
@ApiModel("顶部统计数据")
public class ScreenTopStaticsDataVO {
    @ApiModelProperty("房屋总面积")
    private Double houseTotalArea;
    @ApiModelProperty("已出租面积")
    private Double houseRentedArea;
    @ApiModelProperty("总计应收租金(万元)")
    private BigDecimal totalReceivableRent;
    @ApiModelProperty("总计已收租金(万元)")
    private BigDecimal totalReceivedRent;
    @ApiModelProperty("本月新增租户数")
    private Integer newTenantCount;
    @ApiModelProperty("总计租户数")
    private Integer totalTenantCount;
    @ApiModelProperty("本季度已交租金(万元)")
    private BigDecimal totalRentPaid;
    @ApiModelProperty("本季度应交租金(万元)")
    private BigDecimal totalRentShould;
    @ApiModelProperty("本季度欠费(万元)")
    private BigDecimal totalRentOwe;
    @ApiModelProperty("总计欠费(万元)")
    private BigDecimal totalRentOweAll;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/TenantCountTrendVO.java
New file
@@ -0,0 +1,22 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("租户数量趋势统计")
public class TenantCountTrendVO {
    @ApiModelProperty(value = "日期")
    private String date;
    @ApiModelProperty(value = "租户数量")
    private Long count;
    public TenantCountTrendVO(String date, Long count) {
        this.date = date;
        this.count = count;
    }
    public TenantCountTrendVO() {
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/YearQuarter.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.system.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
@Data
@AllArgsConstructor
public class YearQuarter implements Comparable<YearQuarter> {
    private int year;
    private int quarter;
    public static YearQuarter from(LocalDate date) {
        int quarter = (date.getMonthValue() - 1) / 3 + 1;
        return new YearQuarter(date.getYear(), quarter);
    }
    public String format(DateTimeFormatter formatter) {
        return formatter.format(LocalDate.of(year, quarter * 3 - 2, 1));
    }
    @Override
    public int compareTo(YearQuarter other) {
        return Comparator.comparingInt(YearQuarter::getYear)
                .thenComparingInt(YearQuarter::getQuarter)
                .compare(this, other);
    }
}
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -25,6 +25,7 @@
        <result property="remark"       column="remark"       />
        <result property="ifBlack"       column="ifBlack"       />
        <result property="districtId"       column="districtId"       />
        <result property="businessDeptId"       column="business_dept_id"       />
        <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
        <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
    </resultMap>
@@ -49,7 +50,7 @@
    </resultMap>
    
    <sql id="selectUserVo">
        select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
        select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, u.business_dept_id,
        d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
        r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
        from sys_user u
@@ -131,7 +132,7 @@
    <select id="selectUserById" parameterType="Long" resultType="com.ruoyi.common.core.domain.entity.SysUser">
        select u.user_id AS userId, u.dept_id AS deptId, u.user_name AS userName, u.nick_name AS nickName, u.email AS email, u.avatar AS avatar,
               u.phonenumber AS phonenumber, u.sex AS sex, u.status AS status, u.del_flag AS delFlag, u.login_ip AS loginIp,
               u.login_date AS loginDate, u.create_by AS createBy, u.create_time AS createTime, u.remark AS remark,u.ifBlack AS ifBlack, u.districtId AS districtId,
               u.login_date AS loginDate, u.create_by AS createBy, u.create_time AS createTime, u.remark AS remark,u.ifBlack AS ifBlack, u.districtId AS districtId,u.business_dept_id AS businessDeptId,
               ur.role_id AS roleId,sr.role_name AS roleName,u.deptName as deptName
        from sys_user u
        left join sys_user_role ur on u.user_id = ur.user_id
@@ -224,7 +225,8 @@
        select u.user_id AS userId, u.dept_id AS deptId, u.user_name AS userName, u.nick_name AS nickName, u.email AS email, u.avatar AS avatar,u.disable_remark AS disableRemark,
               u.phonenumber AS phonenumber, u.sex AS sex, u.status AS status, u.del_flag AS delFlag, u.login_ip AS loginIp,u.operating_time AS operatingTime,u.operating_person AS operatingPerson,
               u.login_date AS loginDate, u.create_by AS createBy, u.create_time AS createTime, u.remark AS remark,u.ifBlack AS ifBlack, u.districtId AS districtId,
               r.role_id AS roleId, r.role_name AS roleName, r.role_key AS roleKey, r.role_sort AS roleSort, r.data_scope AS dataScope, r.status as role_status,u.deptName as deptName
               r.role_id AS roleId, r.role_name AS roleName, r.role_key AS roleKey, r.role_sort AS roleSort, r.data_scope AS dataScope, r.status as role_status,u.deptName as deptName,
               u.business_dept_id AS businessDeptId
        from sys_user u
        left join sys_user_role ur on u.user_id = ur.user_id
        left join sys_role r on r.role_id = ur.role_id
@@ -247,6 +249,9 @@
            <foreach collection="query.roleIds" close=")" open="(" item="roleId" separator=",">
                #{roleId}
            </foreach>
        </if>
        <if test="query.businessDeptId != null and query.businessDeptId != '' and query.businessDeptId != 0">
            AND u.business_dept_id = #{query.businessDeptId}
        </if>
        ORDER BY u.create_time DESC
    </select>
@@ -271,6 +276,7 @@
             <if test="remark != null and remark != ''">remark,</if>
             <if test="ifBlack != null">ifBlack,</if>
             <if test="districtId != null">districtId,</if>
            <if test="businessDeptId != null">business_dept_id,</if>
             create_time
         )values(
             <if test="userId != null and userId != ''">#{userId},</if>
@@ -289,6 +295,7 @@
             <if test="remark != null and remark != ''">#{remark},</if>
            <if test="ifBlack != null">#{ifBlack},</if>
            <if test="districtId != null">#{districtId},</if>
            <if test="businessDeptId != null">#{businessDeptId},</if>
             sysdate()
         )
    </insert>
@@ -315,6 +322,7 @@
            <if test="disableRemark != null">disable_remark = #{disableRemark},</if>
            <if test="operatingTime != null">operating_time = #{operatingTime},</if>
            <if test="operatingPerson != null">operating_person = #{operatingPerson},</if>
            <if test="businessDeptId != null">business_dept_id = #{businessDeptId},</if>
             update_time = sysdate()
         </set>
         where user_id = #{userId}
ruoyi-system/src/main/resources/mapper/system/TBankFlowMapper.xml
@@ -58,6 +58,9 @@
            <if test="req.payEndTime != null and req.payEndTime != ''">
                and pay_time &lt;= #{req.payEndTime}
            </if>
            <if test='businessDeptId != null and businessDeptId != "" and businessDeptId != "0"'>
                and business_dept_id = #{businessDeptId}
            </if>
            AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
    </select>
ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
@@ -45,6 +45,7 @@
        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
        LEFT JOIN t_bill_type_sort_weight sw on sw.code=b.pay_fees_status
        <where>
            b.disabled=0
            <if test="query.payFeesStatus != null">
@@ -62,9 +63,57 @@
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!=0'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
        order by b.payable_fees_time desc,b.create_time desc
        order by sw.sort_weight desc,b.payable_fees_time asc
<!--        order by b.payable_fees_time desc,b.create_time desc-->
    </select>
    <select id="pageForApplet" resultType="com.ruoyi.system.dto.TBillDto">
        SELECT
        b.*,
        t.resident_name as residentName,
        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
        LEFT JOIN t_bill_type_sort_weight sw on sw.code=b.pay_fees_status
        <where>
            b.disabled=0
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
            <if test="query.phone != null and query.phone !=''">
                and t.phone = #{query.phone}
            </if>
            <if test="query.residentName != null and query.residentName !=''">
                and t.resident_name like concat('%',#{query.residentName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber !=''">
                and b.contract_number = #{query.contractNumber}
            </if>
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!="0"'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
        order by sw.sort_weight desc,b.payable_fees_time asc
    </select>
    <select id="getBillList" resultType="com.ruoyi.system.dto.TBillDto">
        SELECT
        b.*,
@@ -151,19 +200,128 @@
    </select>
    <select id="statisticsAllRent" resultType="java.math.BigDecimal">
        SELECT ifnull(sum(payable_fees_money),0) as amount FROM t_bill
        SELECT ifnull(sum(payable_fees_money),0) as amount 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.disabled=0 and b.pay_fees_status!='5'
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
            <if test="query.phone != null and query.phone !=''">
                and t.phone = #{query.phone}
            </if>
            <if test="query.residentName != null and query.residentName !=''">
                and t.resident_name like concat('%',#{query.residentName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber !=''">
                and b.contract_number = #{query.contractNumber}
            </if>
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!="0"'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
    </select>
    <select id="statisticsNoPay" resultType="java.math.BigDecimal">
        SELECT ifnull(sum(outstanding_money),0) as amount FROM t_bill where pay_fees_status!=3
        SELECT ifnull(sum(outstanding_money),0) as amount 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.disabled=0 and b.pay_fees_status!='3' and b.pay_fees_status!='5'
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
            <if test="query.phone != null and query.phone !=''">
                and t.phone = #{query.phone}
            </if>
            <if test="query.residentName != null and query.residentName !=''">
                and t.resident_name like concat('%',#{query.residentName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber !=''">
                and b.contract_number = #{query.contractNumber}
            </if>
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!="0"'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
    </select>
    <select id="statisticsPayed" resultType="java.math.BigDecimal">
        SELECT ifnull(sum(pay_fees_money),0) as amount FROM t_bill
        SELECT ifnull(sum(pay_fees_money),0) as amount 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.disabled=0 and b.pay_fees_status!='5'
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
            <if test="query.phone != null and query.phone !=''">
                and t.phone = #{query.phone}
            </if>
            <if test="query.residentName != null and query.residentName !=''">
                and t.resident_name like concat('%',#{query.residentName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber !=''">
                and b.contract_number = #{query.contractNumber}
            </if>
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!="0"'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
    </select>
    <select id="statisticsOverdue" resultType="java.math.BigDecimal">
        SELECT ifnull(sum(outstanding_money),0) as amount FROM t_bill where pay_fees_status=4
        SELECT ifnull(sum(outstanding_money),0) as amount 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.disabled=0 and b.pay_fees_status='4'
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
            <if test="query.phone != null and query.phone !=''">
                and t.phone = #{query.phone}
            </if>
            <if test="query.residentName != null and query.residentName !=''">
                and t.resident_name like concat('%',#{query.residentName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber !=''">
                and b.contract_number = #{query.contractNumber}
            </if>
            <if test="query.userId != null and query.userId !=''">
                and t.id = #{query.userId}
            </if>
            <if test='query.businessDeptId != null and query.businessDeptId != "" and query.businessDeptId!="0"'>
                and b.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.billType != null">
                and b.bill_type = #{query.billType}
            </if>
        </where>
    </select>
    <select id="batchBillCount" resultType="java.lang.Integer">
        SELECT
@@ -186,4 +344,32 @@
            AND b.bill_type = 3
        </where>
    </select>
    <select id="getStreetRentRank" resultType="com.ruoyi.system.vo.ScreenRentRankVO">
        SELECT
            ts.street_name,ROUND(COALESCE(SUM(tb.pay_fees_money),0) /10000,2) AS rentAmount
        FROM
            t_street ts
                LEFT JOIN t_house th ON ts.id = th.street_id
                LEFT JOIN t_contract tc ON tc.house_id = th.id AND tc.pay_type = 2
                LEFT JOIN t_bill tb ON tc.id = tb.contract_id AND tb.pay_fees_status != 5
            <where>
                <if test="businessDeptId != 0">
                    AND th.business_dept_id = #{businessDeptId}
                </if>
            </where>
        GROUP BY ts.id
        ORDER BY rentAmount DESC
    </select>
    <select id="getJiFuBillList" resultType="com.ruoyi.system.model.TBill" parameterType="java.lang.String">
        SELECT tb.* FROM t_bill tb LEFT JOIN t_contract tt ON tb.contract_id = tt.id
        <where>
            tt.pay_type = 2 AND tb.bill_type = ${@com.ruoyi.common.enums.BillTypeEnum@Zujin.getCode()} AND tb.pay_fees_status != 5
            <if test="businessDeptId != null and businessDeptId != 0">
                AND tb.business_dept_id = #{businessDeptId}
            </if>
            <if test="first!=null and last !=null">
                AND tb.payable_fees_time BETWEEN #{first} AND #{last}
            </if>
        </where>
    </select>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TBusinessDeptMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TBusinessDeptMapper">
</mapper>
ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
@@ -76,6 +76,9 @@
                AND t.check_time &gt;= #{query.startTime}
                AND t.check_time &lt;= #{query.endTime}
            </if>
            <if test="query.businessDeptId != null and query.businessDeptId != '' and query.businessDeptId != 0">
                AND c.business_dept_id = #{query.businessDeptId}
            </if>
            AND t.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        ORDER BY t.create_time DESC
@@ -99,6 +102,9 @@
            <if test="query.houseNameOrAddress != null and query.houseNameOrAddress != ''">
                AND (h.house_name LIKE concat('%', #{query.houseNameOrAddress}, '%') or h.house_address LIKE concat('%', #{query.houseNameOrAddress}, '%'))
            </if>
            <if test="query.businessDeptId != null and query.businessDeptId != ''">
                AND h.business_dept_id =#{query.businessDeptId}
            </if>
            AND t.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        ORDER BY t.create_time DESC
ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml
@@ -68,6 +68,9 @@
                    #{item}
                </foreach>
            </if>
            <if test="businessDeptId!=null and businessDeptId !='' and businessDeptId != 0">
                and t1.business_dept_id = #{businessDeptId}
            </if>
            AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        order by t1.create_time desc
@@ -124,5 +127,55 @@
        </where>
    </select>
    <select id="getCurrentMonthRentCount" resultType="java.lang.Integer">
        SELECT COUNT(DISTINCT tc.tenant_id) AS new_tenant_count
        FROM t_contract tc
        <where>
            -- 筛选本月签订的合同
            DATE_FORMAT(tc.sign_time, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m') AND tc.status IN ("4", "5", "6", "7", "8", "9") AND tc.pay_type = 2
            -- 且租户在本月前从未签订过任何合同
            AND NOT EXISTS (
            SELECT 1
            FROM t_contract tc_hist
            WHERE tc_hist.tenant_id = tc.tenant_id
            AND tc_hist.sign_time <![CDATA[ < ]]> DATE_FORMAT(CURDATE(), '%Y-%m-01') AND tc_hist.status IN ("4", "5", "6", "7", "8", "9")
            )
            <if test="businessDeptId!=0">
                AND tc.business_dept_id = #{businessDeptId}
            </if>
        </where>
    </select>
    <select id="page" resultType="com.ruoyi.system.model.TContract">
        select * from t_contract
        <where>
            <if test="query.partyTwoName != null and query.partyTwoName != ''">
                and party_two_name like concat('%',#{query.partyTwoName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber != ''">
                and contract_number like concat('%',#{query.contractNumber},'%')
            </if>
            <if test="query.contractName != null and query.contractName != ''">
                and contract_name like concat('%',#{query.contractName},'%')
            </if>
            <if test="query.status != null">
                and status = #{query.status}
            </if>
            <if test="query.tenantId != null">
                and tenant_id = #{query.tenantId}
            </if>
            <if test="query.statuses != null and query.statuses.size()>0">
                and status in
                <foreach collection="query.statuses" item="item" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
            <if test='query.businessDeptId!=null and query.businessDeptId !="" and query.businessDeptId != "0"'>
                and business_dept_id = #{query.businessDeptId}
            </if>
            AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        order by create_time desc
    </select>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
@@ -67,6 +67,7 @@
        t.create_by,
        t.update_by,
        t.disabled,
        t.fault_cause,
        i.item_name AS itemName,
        it.type_name AS itemTypeName,
        tnt.resident_name AS residentName
@@ -112,6 +113,7 @@
                 LEFT JOIN t_item i ON t.item_id = i.id
                 LEFT JOIN t_item_type it ON t.item_type_id = it.id
                 LEFT JOIN t_tenant tnt ON t.tenant_id = tnt.id
                 LEFT JOIN t_contract tc ON t.contract_id = tc.id
        <where>
            <if test="query.residentName != null and query.residentName != ''">
                AND tnt.resident_name LIKE CONCAT('%', #{query.residentName}, '%')
@@ -128,6 +130,9 @@
            <if test="query.handlePerson != null and query.handlePerson != ''">
                AND t.handle_person LIKE CONCAT('%', #{query.handlePerson}, '%')
            </if>
            <if test="query.businessDeptId != null and query.businessDeptId != '' and query.businessDeptId != 0">
                AND tc.business_dept_id = #{query.businessDeptId}
            </if>
            AND t.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        ORDER BY t.create_time DESC
ruoyi-system/src/main/resources/mapper/system/TFlowManagementMapper.xml
@@ -64,6 +64,9 @@
            <if test="req.payEndTime != null and req.payEndTime != ''">
                 and pay_time &lt;= #{req.payEndTime}
            </if>
            <if test='businessDeptId != null and businessDeptId != "" and businessDeptId != "0"'>
                and business_dept_id = #{businessDeptId}
            </if>
            AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
    </select>
ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml
@@ -55,6 +55,9 @@
            <if test="req.leaseStatus == 1">
                and (t2.start_time is null) and t1.lease_status = 1
            </if>
            <if test="req.businessDeptId != null and req.businessDeptId != '' and req.businessDeptId!=0">
                and t1.business_dept_id = #{req.businessDeptId}
            </if>
            AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        order by t1.create_time desc
@@ -83,5 +86,16 @@
          AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
    </select>
    <select id="getRentedArea" resultType="java.lang.Double">
        SELECT COALESCE(SUM(t1.house_area),0) FROM t_house t1
        LEFT JOIN t_contract t2 ON t1.id = t2.house_id AND t2.status = 4 AND t2.pay_type = 2
        <where>
            t1.lease_status != 1
            <if test="businessDeptId!=0">
                AND t1.business_dept_id = #{businessDeptId}
            </if>
            AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
    </select>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TRentalReturnRecordMapper.xml
New file
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TRentalReturnRecordMapper">
    <select id="queryRentalReturnRecordList" resultType="com.ruoyi.system.vo.RentalReturnRecordVO">
        SELECT
        trrr.id,
        trrr.tenant_id,
        trrr.house_id,
        trrr.contract_id,
        trrr.reason_for_return,
        trrr.audit_status,
        trrr.audit_user_id,
        trrr.create_time applicationDate,
        th.house_name,
        th.house_address,
        tc.contract_number,
        tt.resident_name submitter,
        tt.phone submitterPhone
        FROM
        t_rental_return_record trrr
        LEFT JOIN t_house th ON trrr.house_id = th.id
        LEFT JOIN t_contract tc ON trrr.contract_id = tc.id
        LEFT JOIN t_tenant tt ON tt.id = trrr.tenant_id
        <where>
            trrr.disabled = 0
            <if test="query.startDate != null and query.endDate !=null">
            AND trrr.create_time BETWEEN #{query.startDate} AND DATE_ADD(#{query.endDate}, INTERVAL 1 DAY)
            </if>
            <if test="query.isAdminDelete != null and query.isAdminDelete">
            AND trrr.is_admin_delete = 0
            </if>
            <if test="query.houseName != null and query.houseName != ''">
            AND th.house_name LIKE CONCAT('%',#{query.houseName},'%')
            </if>
            <if test="query.contractNumber != null and query.contractNumber != ''">
            AND tc.contract_number LIKE CONCAT('%',#{query.contractNumber},'%')
            </if>
            <if test="query.businessDeptId != null and query.businessDeptId != '' and query.businessDeptId != 0">
                AND tc.business_dept_id = #{query.businessDeptId}
            </if>
            <if test="query.submitter != null and query.submitter != ''">
            AND tt.resident_name LIKE CONCAT('%',#{query.submitter},'%')
            </if>
        </where>
        order by trrr.create_time desc
    </select>
    <select id="queryRentalReturnRecordById" resultType="com.ruoyi.system.vo.RentalReturnRecordVO"
            parameterType="java.lang.String">
        SELECT
            trrr.id,
            trrr.tenant_id,
            trrr.house_id,
            trrr.contract_id,
            trrr.reason_for_return,
            trrr.audit_status,
            trrr.audit_user_id,
            trrr.images,
            trrr.create_time,
            trrr.audit_opinion,
            th.house_name,
            th.house_address,
            tc.contract_number,
            tt.resident_name submitter,
            tt.phone submitterPhone
        FROM
            t_rental_return_record trrr
                LEFT JOIN t_house th ON trrr.house_id = th.id
                LEFT JOIN t_contract tc ON trrr.contract_id = tc.id
                LEFT JOIN t_tenant tt ON tt.id = trrr.tenant_id
        WHERE trrr.disabled = 0 AND trrr.id = #{id}
    </select>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TStreetMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TStreetMapper">
</mapper>
ruoyi-system/src/main/resources/mapper/system/TTenantMapper.xml
@@ -112,5 +112,28 @@
            </otherwise>
        </choose>
    </select>
    <select id="pageListByBusinessDeptId" resultType="com.ruoyi.system.vo.TenantVO">
        SELECT * FROM (
        SELECT tt.id, tt.resident_name, tt.checkIn_time, tt.tenant_attributes, tt.tenant_type, tt.phone,
        tt.id_card, tt.email,
        tt.bank_number, tt.mail_address, tt.create_time, tt.disabled,tt.account
        FROM t_tenant tt
        WHERE EXISTS (
        SELECT 1
        FROM t_contract tc
        WHERE tc.tenant_id = tt.id AND tc.business_dept_id = #{query.businessDeptId}
        )
        ) AS te
        <where>
            <if test="query.residentName != null and query.residentName != ''">
                AND te.resident_name LIKE concat('%',#{query.residentName},'%')
            </if>
            <if test="query.phone != null and query.phone != ''">
                AND te.phone LIKE concat('%',#{query.phone},'%')
            </if>
            AND te.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
        </where>
        ORDER BY te.create_time DESC
    </select>
</mapper>