From 96a7015065775e5c3bc3d6458b86b28ad7bfb46b Mon Sep 17 00:00:00 2001
From: yupeng <roc__yu@163.com>
Date: 星期四, 13 三月 2025 17:53:32 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into xizang-changyun

---
 ruoyi-admin/src/main/resources/application-test.yml                                           |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseVO.java                                   |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java                       |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java                                  |   41 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java                         |    5 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java    |   22 
 ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml                                 |   24 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java                         |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/StateProcessJob.java                    |    2 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java            |   13 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java                         |  247 ++++
 ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml                    |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java                             |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java                          |   92 ++
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java            |   47 +
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java                  |   25 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java               |    7 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java                         |  187 +--
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java              |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java                      |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java                   |   10 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java           |    4 
 ruoyi-system/src/main/resources/mapper/system/StateTaskCenterMapper.xml                       |    2 
 ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml                                |   21 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java                |    5 
 ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml                   |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java       |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordPdfGenerator.java                 |  106 ++
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java                  |   59 +
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MyFileUtil.java                      |  128 ++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java               |  114 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java             |  461 ++++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java            |  498 -----------
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java            |   87 +
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java                           |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java                              |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/dto/BatchBillDTO.java                             |   18 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java                         |  313 ++++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java   |   18 
 40 files changed, 1,838 insertions(+), 760 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
index 5a0e81a..8a363c6 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -92,11 +92,13 @@
     @PostMapping(value = "/addContract")
     @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()));
         if (count!=0){
             return R.fail("合同编号不可重复");
         }
         dto.setChangeRent(dto.getMonthRent());
+        dto.setChangeTime(null);
         contractService.save(dto);
         if (dto.getStatus().equals("2")){
             //发起合同新增审批
@@ -134,7 +136,7 @@
             tContractRentType.setIncreasingDecreasing(dto.getIncreasingDecreasing());
             tContractRentType.setIncreasingDecreasingType(dto.getIncreasingDecreasingType());
             tContractRentType.setNumericalValue(dto.getNumericalValue());
-            tContractRentType.setChangeTime(dto.getChangeTime());
+            tContractRentType.setChangeTime(changeTime);
             tContractRentType.setCycleTime(dto.getCycleTime());
             contractRentTypeService.save(tContractRentType);
         }
@@ -145,6 +147,7 @@
     @PostMapping(value = "/updateContract")
     @PreAuthorize("@ss.hasPermi('contract:list:edit')")
     public R<Boolean> updateContract(@Validated @RequestBody TContractDTO dto) {
+        dto.setChangeTime(null);
         contractService.updateById(dto);
         contractRentTypeService.remove(new LambdaQueryWrapper<TContractRentType>()
                 .eq(TContractRentType::getContractId,dto.getId()));
@@ -157,6 +160,36 @@
             tContractRentType.setChangeTime(dto.getChangeTime());
             tContractRentType.setCycleTime(dto.getCycleTime());
             contractRentTypeService.save(tContractRentType);
+        }
+        if (dto.getStatus().equals("2")){
+            //发起合同新增审批
+            ProcessStartBO processStartBO = new ProcessStartBO();
+            processStartBO.setCategory(ProcessCategoryEnum.CATEGORY1.getValue().toString());
+            processStartBO.setModuleName("合同新增审批");
+            processStartBO.setName(dto.getContractName());
+            //需要显示发起申请人所在单位
+//            String cedName = SecurityUtils.getLoginUser().getUser().getDept().getDeptName();
+//            String remark = String.format("【镇/街】:%s,【征收实施单位】:%s,【申请金额】:%s万元", stateProject.getStreet(), cedName, stateApplyRecord.getAmount());
+            processStartBO.setRemark("");
+            Map<String, Object> variable = new HashMap<>();
+            variable.put("projectId", dto.getId());
+            processStartBO.setVariable(variable);
+            //开启工作流程
+            Boolean start = stateProcessTemplateService.start(processStartBO);
+            if(start){
+                FlwTask flwTask = flwTaskMapper.selectOne(Wrappers.lambdaQuery(FlwTask.class)
+                        .like(FlwTask::getVariable, dto.getId())
+                        .orderByDesc(FlwTask::getCreateTime)
+                        .last("LIMIT 1"));
+                if(Objects.nonNull(flwTask)){
+                    // 添加定时任务
+                    Map<String, ? extends Object> maps =
+                            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);
+                }
+            }
         }
         return R.ok();
     }
@@ -178,8 +211,6 @@
         TContractVO res = new TContractVO();
         TContract contract = contractService.getById(id);
         BeanUtils.copyProperties(contract,res);
-        res.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE,res.getPayType()));
-        res.setStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_STATUS,res.getStatus()));
         TContractRentType contractRentType = contractRentTypeService.lambdaQuery().eq(TContractRentType::getContractId, id).one();
         if (contractRentType!=null){
             BeanUtils.copyProperties(contractRentType,res);
@@ -194,14 +225,14 @@
         res.setHouse(house);
         List<TBill> list = billService.lambdaQuery()
                 .eq(TBill::getContractId, id)
-                .in(TBill::getPayFeesStatus, Arrays.asList("1,4"))
+                .ne(TBill::getPayFeesStatus, 3)
                 .list();
         BigDecimal payMoney = new BigDecimal("0");
         for (TBill tBill : list) {
-            payMoney = payMoney.add(tBill.getPayFeesMoney()).add(tBill.getPayableFeesPenalty());
+            payMoney = payMoney.add(tBill.getOutstandingMoney()).add(tBill.getPayableFeesPenalty());
         }
         TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery().eq(TCheckAcceptRecord::getContractId, id).one();
-        res.setCheckResult(Objects.nonNull(tCheckAcceptRecord)?tCheckAcceptRecord.getCheckResult():false);
+        res.setCheckResult(Objects.nonNull(tCheckAcceptRecord)&&Objects.nonNull(tCheckAcceptRecord.getCheckResult())?tCheckAcceptRecord.getCheckResult():null);
         res.setPayMoney(payMoney);
 
         return R.ok(res);
@@ -228,7 +259,14 @@
         TContract contract = contractService.getById(id);
         contract.setStatus("8");
         contractService.updateById(contract);
-        return R.ok();
+        // 将所有未缴费账单设置未已失效
+        List<TBill> tBills = billService.list(new LambdaQueryWrapper<TBill>()
+                .ne(TBill::getPayFeesStatus, 3)
+                .eq(TBill::getContractId, contract.getId()));
+        for (TBill tBill : tBills) {
+            tBill.setPayFeesStatus("5");
+        }
+        billService.updateBatchById(tBills);        return R.ok();
     }
     @ApiOperation(value = "终止合同剩余未缴费账单列表")
     @PostMapping(value = "/contractBillList")
@@ -257,31 +295,51 @@
         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²");
-            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()));
+            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+"元");
+            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")?"季":"年");
-            templateParam.put("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,BigDecimal.ROUND_DOWN)+"元");
-            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());
-            String url = wordUtil.generatePdf("/template", "1_yzj_租赁合同.xml", templateParam, "租赁合同", "E:\\");
+            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/");
             res.add(url);
         }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java
index fa0e4a9..772f34c 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java
@@ -61,12 +61,20 @@
     /**
      * 获取部门管理管理列表
      */
-    @ApiOperation(value = "获取部门管理列表")
+    @ApiOperation(value = "获取部门管理列表-启用状态")
     @PostMapping(value = "/list")
     public R<List<TDept>> list() {
         return R.ok(deptService.list(Wrappers.lambdaQuery(TDept.class)
                 .eq(TDept::getStatus, 1)));
     }
+    /**
+     * 获取部门管理管理列表
+     */
+    @ApiOperation(value = "获取部门管理列表-所有状态")
+    @PostMapping(value = "/listAll")
+    public R<List<TDept>> listAll() {
+        return R.ok(deptService.list(Wrappers.lambdaQuery(TDept.class)));
+    }
 
     /**
      * 添加部门管理管理
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java
index ddd4270..d3530a7 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultDescribeDicController.java
@@ -16,6 +16,7 @@
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -67,6 +68,7 @@
     @ApiOperation(value = "修改故障描述")
     @PostMapping(value = "/update")
     public R<Boolean> update(@Validated @RequestBody TFaultDescribeDic dto) {
+        dto.setUpdateTime(LocalDateTime.now());
         return R.ok(faultDescribeDicService.updateById(dto));
     }
 
@@ -101,6 +103,6 @@
     public R<Boolean> deleteByIds(@RequestBody List<String> ids) {
         return R.ok(faultDescribeDicService.removeByIds(ids));
     }
-    
+
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index e4755e8..b44867f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -156,7 +156,7 @@
     @PostMapping("/add")
     public AjaxResult add(@Validated @RequestBody SysUser user)
     {
-        user.setUserName(user.getPhonenumber());
+        user.setUserName(user.getUserName());
         if (!userService.checkUserNameUnique(user))
         {
             return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
index 6db2c4f..2fc75ee 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
@@ -1,110 +1,83 @@
-package com.ruoyi.web.controller.task;
-
-
-import com.ruoyi.system.model.TBill;
-import com.ruoyi.system.model.TContract;
-import com.ruoyi.system.model.TContractRentType;
-import com.ruoyi.system.service.TBillService;
-import com.ruoyi.system.service.TContractRentTypeService;
-import com.ruoyi.system.service.TContractService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.temporal.ChronoUnit;
-import java.time.temporal.TemporalAdjusters;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import java.util.stream.Collectors;
-
-/**
- * @author zhibing.pu
- * @date 2023/7/11 8:39
- */
-@Component
-public class TaskUtil {
-    @Autowired
-    private TContractService contractService;
-    @Autowired
-    private TBillService billService;
-    @Autowired
-    private TContractRentTypeService contractRentTypeService;
-
-    // 每天凌晨00点执行的定时任务 用于生成违约金
-    @Scheduled(cron = "0 0 0 * * ?")
-    public void dayOfProportionBill() {
-        try {
-            // 查询所有未缴费账单
-            List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, 1).list();
-            for (TBill tBill : list) {
-                TContract contract = contractService.getById(tBill.getContractId());
-                LocalDate payableFeesTime = tBill.getPayableFeesTime();
-                LocalDateTime now = LocalDateTime.now();
-                // 计算两个时间相差多少个小时
-                long hours = ChronoUnit.HOURS.between(payableFeesTime, now);
-                long l = hours / 72;
-                if (l>0){
-                    // 违约金比例
-                    BigDecimal proportion = contract.getProportion();
-                    // 应缴违约金
-                    BigDecimal money = tBill.getOutstandingMoney().multiply(proportion);
-                    TBill changeBill = new TBill();
-                    changeBill.setId(tBill.getId());
-                    changeBill.setPayableFeesPenalty(money);
-                    billService.lockAndUpdateInfo(changeBill,2);
-                }
-            }
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-
-
-    // 每天凌晨00点执行的定时任务 根据应缴费日期修改账单状态
-    @Scheduled(cron = "0 0 0 * * ?")
-    public void dayOfEndBill() {
-        try {
-            List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, "2").list();
-            for (TBill tBill : list) {
-                if (tBill.getPayableFeesTime().equals(LocalDate.now())){
-                    tBill.setPayFeesStatus("1");
-                }
-            }
-            billService.updateBatchById(list);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-
-
-
-    public static void main(String[] args) {
-
-//        LocalDateTime now = LocalDateTime.now().minusMonths(1).withDayOfMonth(31);
-//        System.err.println(now);
-//        LocalDateTime now2 = now.plusMonths(1);
-//        System.err.println(now2);
+//package com.ruoyi.web.controller.task;
 //
-//        LocalDateTime now1 = LocalDateTime.now();
-//        long days = ChronoUnit.DAYS.between(now, now1);
-//        long days2 = ChronoUnit.DAYS.between(now.plusDays(1), now1);
 //
-//        System.err.println(days);
-//        System.err.println(days2);
-//        LocalDateTime endTime = now.with(TemporalAdjusters.lastDayOfMonth()).withSecond(59).withHour(23).withMinute(59);
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.ruoyi.common.utils.SmsUtil;
+//import com.ruoyi.system.mapper.TBillMapper;
+//import com.ruoyi.system.model.TBill;
+//import com.ruoyi.system.model.TContract;
+//import com.ruoyi.system.model.TContractRentType;
+//import com.ruoyi.system.service.TBillService;
+//import com.ruoyi.system.service.TContractRentTypeService;
+//import com.ruoyi.system.service.TContractService;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.scheduling.annotation.Scheduled;
+//import org.springframework.stereotype.Component;
 //
-//        System.err.println(endTime);
-
-    }
-
-}
+//import javax.annotation.Resource;
+//import java.math.BigDecimal;
+//import java.time.LocalDate;
+//import java.time.LocalDateTime;
+//import java.time.LocalTime;
+//import java.time.ZoneId;
+//import java.time.temporal.ChronoUnit;
+//import java.time.temporal.TemporalAdjusters;
+//import java.util.ArrayList;
+//import java.util.Date;
+//import java.util.List;
+//import java.util.Random;
+//import java.util.stream.Collectors;
+//
+///**
+// * @author zhibing.pu
+// * @date 2023/7/11 8:39
+// */
+//@Component
+//public class TaskUtil {
+//    @Autowired
+//    private TContractService contractService;
+//    @Autowired
+//    private TBillMapper billMapper;
+//    // 用于更新违约金账单
+//    // 每分钟执行一次的定时任务
+//
+//    @Scheduled(cron = "0 * * * * ?")
+//    public void dayOfProportionBill() {
+//        try {
+//            // 查询所有未缴费账单
+//            List<TBill> list = billMapper.selectList(new LambdaQueryWrapper<TBill>().eq(TBill::getPayFeesStatus, 1)
+//                    .le(TBill::getPayableFeesTime,LocalDate.now()));
+//            for (TBill tBill : list) {
+//                tBill.setPayFeesStatus("4");
+//                TContract contract = contractService.getById(tBill.getContractId());
+//                LocalDate payableFeesTime = tBill.getPayableFeesTime();
+//                // 将LocalDate转化为LocalDateTime
+//                LocalDateTime payableFeesTime1 = LocalDateTime.of(payableFeesTime, LocalTime.of(0, 0, 0));
+//                LocalDateTime now = LocalDateTime.now();
+//                // 计算两个时间相差多少个小时
+//                long hours = ChronoUnit.HOURS.between(payableFeesTime1, now);
+//                long l = hours / 24;
+//                if (l>=3){
+//                    // 违约金比例
+//                    BigDecimal proportion = contract.getProportion();
+//                    // 按每天 待缴费金额 * XX% 增加违约金费用
+//                    if (tBill.getOutstandingMoney().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);
+//                    tBill.setPayableFeesPenalty((tBill.getPayableFeesPenalty()!=null?tBill.getPayableFeesPenalty():BigDecimal.ZERO).add(money));
+//                    tBill.setOutstandingMoney(money);
+//                    billMapper.updateById(tBill);
+//
+//                }
+//            }
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+//
+//
+//}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
index c786d9b..ba43f3f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
@@ -4,6 +4,7 @@
 import com.documents4j.api.IConverter;
 import com.documents4j.job.LocalConverter;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xwpf.usermodel.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Component;
@@ -11,7 +12,13 @@
 
 import java.io.*;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 @Slf4j
 @Component
@@ -21,47 +28,223 @@
     /**
      * word 转 pdf
      *
-     * @param url
      */
-    public  String wordToPdf(String url,String filePath, String fileName) {
+//    public  String wordToPdf(String url,String filePath, String fileName) {
+//        try {
+//            DocumentType documentType = DocumentType.DOC;
+//            if(url.contains(".docx")){
+//                documentType = DocumentType.DOCX;
+//            }
+//            if(url.contains(".doc")){
+//                documentType = DocumentType.DOC;
+//            }
+//            if(url.contains(".xlsx")){
+//                documentType = DocumentType.XLSX;
+//            }else {
+//                if(url.contains(".xls")){
+//                    documentType = DocumentType.XLS;
+//                }
+//            }
+//            InputStream inputStream = new URL(url).openStream();
+//            ByteArrayOutputStream stream = new ByteArrayOutputStream();
+//            IConverter converter = LocalConverter.builder().build();
+//            converter.convert(inputStream)
+//                    .as(documentType)
+//                    .to(stream)
+//                    .as(DocumentType.PDF).execute();
+//
+//            //上传图片
+//            byte2File(stream.toByteArray(),filePath + "/pdf",fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf");
+//            MultipartFile multipartFile = convertToMultipartFile(stream,fileName.substring(0,fileName.lastIndexOf(".")) );
+//            String s = tencentCosUtil.upLoadFile(multipartFile,"/wordToPdf");
+//
+//            stream.close();
+//            inputStream.close();
+//            return s;
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        return null;
+//    }
+
+    public String wordToPdf(String filePath, String fileName) {
         try {
-            DocumentType documentType = DocumentType.DOC;
-            if(url.contains(".docx")){
-                documentType = DocumentType.DOCX;
-            }
-            if(url.contains(".doc")){
-                documentType = DocumentType.DOC;
-            }
-            if(url.contains(".xlsx")){
-                documentType = DocumentType.XLSX;
-            }else {
-                if(url.contains(".xls")){
-                    documentType = DocumentType.XLS;
+            // 确保路径正确性
+            String inputFile = new File(filePath, fileName).getAbsolutePath();
+            String outputDir = new File(filePath, "pdf").getAbsolutePath();
+
+            // 创建输出目录
+            new File(outputDir).mkdirs();
+
+            // 使用完整的转换参数
+            List<String> command = Arrays.asList(
+                    "/usr/bin/libreoffice",  // 使用完整路径
+                    "--headless",
+                    "--norestore",
+                    "--convert-to",
+                    "pdf:writer_pdf_Export:PDFExport{" +
+                            "EmbedStandardFonts=1;" +
+                            "EmbedFonts=1;" +
+                            "EmbedOnlyUsedFonts=0;" +
+                            "UseTaggedPDF=1" +
+                            "}",
+                    "--outdir",
+                    outputDir,
+                    inputFile
+            );
+
+            // 创建进程构建器
+            ProcessBuilder pb = new ProcessBuilder(command);
+
+            // 设置环境变量
+            Map<String, String> env = pb.environment();
+            env.put("LC_ALL", "zh_CN.UTF-8");
+            env.put("LANG", "zh_CN.UTF-8");
+            env.put("LANGUAGE", "zh_CN.UTF-8");
+
+            // 重定向错误流到标准输出
+            pb.redirectErrorStream(true);
+
+            // 启动进程
+            Process process = pb.start();
+
+            // 读取输出
+            StringBuilder output = new StringBuilder();
+            try (BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    output.append(line).append("\n");
+                    System.out.println(line);
                 }
             }
-            InputStream inputStream = new URL(url).openStream();
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            IConverter converter = LocalConverter.builder().build();
-            converter.convert(inputStream)
-                    .as(documentType)
-                    .to(stream)
-                    .as(DocumentType.PDF).execute();
 
-            //上传图片
-            byte2File(stream.toByteArray(),filePath + "/pdf",fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf");
-            MultipartFile multipartFile = convertToMultipartFile(stream,fileName.substring(0,fileName.lastIndexOf(".")) );
+            // 等待进程完成,设置超时
+            if (!process.waitFor(120, TimeUnit.SECONDS)) {
+                process.destroyForcibly();
+                throw new RuntimeException("转换超时");
+            }
+
+            int exitCode = process.exitValue();
+            if (exitCode != 0) {
+                throw new RuntimeException("转换失败,退出码:" + exitCode + "\n输出:" + output);
+            }
+
+            // 检查生成的PDF文件
+            String pdfFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
+            File pdfFile = new File(outputDir, pdfFileName);
+
+            if (!pdfFile.exists() || pdfFile.length() == 0) {
+                throw new RuntimeException("PDF文件未生成或为空");
+            }
+            String absolutePath = pdfFile.getAbsolutePath();
+
+            MultipartFile multipartFile = convertFileToMultipartFile(pdfFile);
             String s = tencentCosUtil.upLoadFile(multipartFile,"/wordToPdf");
-
-            stream.close();
-            inputStream.close();
             return s;
+
         } catch (Exception e) {
-            e.printStackTrace();
+            throw new RuntimeException("PDF转换失败: " + e.getMessage(), e);
         }
-        return null;
     }
 
+    public MultipartFile convertFileToMultipartFile(File file) throws IOException {
+        // 读取文件内容到字节数组
+        byte[] fileContent = Files.readAllBytes(file.toPath());
 
+        // 创建 MultipartFile 对象
+        MultipartFile multipartFile = new MockMultipartFile(
+                file.getName(),       // 文件名
+                file.getName(),       // 原始文件名
+                "application/pdf",  // 内容类型,根据实际情况调整
+                fileContent           // 文件内容
+        );
+
+        return multipartFile;
+    }
+
+    // 在使用前检查和配置环境
+    public static void setupEnvironment() {
+        try {
+            // 1. 检查LibreOffice安装
+            checkLibreOffice();
+
+            // 2. 检查和安装字体
+            installFonts();
+
+            // 3. 配置字体
+            configureFonts();
+
+            // 4. 验证环境变量
+            checkEnvironment();
+
+        } catch (Exception e) {
+            throw new RuntimeException("环境设置失败: " + e.getMessage(), e);
+        }
+    }
+
+    private static void checkLibreOffice() throws IOException, InterruptedException {
+        Process process = Runtime.getRuntime().exec("which libreoffice");
+        if (process.waitFor() != 0) {
+            throw new RuntimeException("LibreOffice未安装");
+        }
+    }
+
+    private static void installFonts() throws IOException, InterruptedException {
+        // 创建字体安装脚本
+        String scriptContent =
+                "#!/bin/bash\n" +
+                        "apt-get update\n" +
+                        "apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei fonts-arphic-ukai fonts-arphic-uming\n" +
+                        "fc-cache -fv\n";
+
+        File script = new File("/tmp/install_fonts.sh");
+        Files.write(script.toPath(), scriptContent.getBytes());
+        script.setExecutable(true);
+
+        // 执行脚本
+        Process process = Runtime.getRuntime().exec("sudo /tmp/install_fonts.sh");
+        process.waitFor();
+
+        // 清理脚本
+        script.delete();
+    }
+
+    private static void configureFonts() throws IOException {
+        // 创建字体配置文件
+        String fontConfig =
+                "<?xml version=\"1.0\"?>\n" +
+                        "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n" +
+                        "<fontconfig>\n" +
+                        "  <match target=\"pattern\">\n" +
+                        "    <test name=\"family\"><string>serif</string></test>\n" +
+                        "    <edit name=\"family\" mode=\"prepend\">\n" +
+                        "      <string>WenQuanYi Zen Hei</string>\n" +
+                        "    </edit>\n" +
+                        "  </match>\n" +
+                        "  <match target=\"pattern\">\n" +
+                        "    <test name=\"family\"><string>sans-serif</string></test>\n" +
+                        "    <edit name=\"family\" mode=\"prepend\">\n" +
+                        "      <string>WenQuanYi Zen Hei</string>\n" +
+                        "    </edit>\n" +
+                        "  </match>\n" +
+                        "</fontconfig>";
+
+        // 写入配置文件
+        File configFile = new File(System.getProperty("user.home") + "/.fonts.conf");
+        Files.write(configFile.toPath(), fontConfig.getBytes());
+    }
+
+    private static void checkEnvironment() {
+        // 检查环境变量
+        String[] requiredVars = {"LANG", "LC_ALL", "LANGUAGE"};
+        for (String var : requiredVars) {
+            String value = System.getenv(var);
+            if (value == null || !value.contains("zh_CN")) {
+                System.err.println("警告: " + var + " 环境变量未正确设置");
+            }
+        }
+    }
 
     public static MultipartFile convertToMultipartFile(ByteArrayOutputStream baos, String fileName) throws IOException {
         // 创建一个临时文件
@@ -209,12 +392,12 @@
     }
 
     public String test(String fileName){
-        String url = "file:///E:\\"+fileName;
+//        String url = "file:///usr/local/project/file/"+fileName;
 //        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09";
 //        String fileName = "专业技术工作总结.docx";4
-        String filePath = "E:\\";
+        String filePath = "/usr/local/project/file/";
 
-        String s = wordToPdf(url, filePath, fileName);
+        String s = wordToPdf(filePath, fileName);
         System.err.println(s);
 
         return s;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordPdfGenerator.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordPdfGenerator.java
new file mode 100644
index 0000000..990e621
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordPdfGenerator.java
@@ -0,0 +1,106 @@
+//package com.ruoyi.web.controller.tool;
+//
+//import org.apache.poi.xwpf.usermodel.*;
+//import java.io.*;
+//import java.time.LocalDateTime;
+//import java.time.format.DateTimeFormatter;
+//
+//public class WordPdfGenerator {
+//
+//    // 示例数据类
+//    public static class UserData {
+//        private String name;
+//        private String id;
+//        private String department;
+//        private LocalDateTime createTime;
+//
+//        public UserData(String name, String id, String department) {
+//            this.name = name;
+//            this.id = id;
+//            this.department = department;
+//            this.createTime = LocalDateTime.now();
+//        }
+//
+//        // getter方法省略
+//    }
+//
+//    public static void generateDocument(UserData userData, String outputPath) {
+//        try (XWPFDocument document = new XWPFDocument()) {
+//            // 创建标题
+//            XWPFParagraph title = document.createParagraph();
+//            title.setAlignment(ParagraphAlignment.CENTER);
+//            XWPFRun titleRun = title.createRun();
+//            titleRun.setText("用户信息表");
+//            titleRun.setBold(true);
+//            titleRun.setFontSize(20);
+//            titleRun.setFontFamily("宋体");
+//
+//            // 添加空行
+//            document.createParagraph();
+//
+//            // 创建表格
+//            XWPFTable table = document.createTable(5, 2);
+//            table.setWidth("100%");
+//
+//            // 设置表格数据
+//            setCellText(table, 0, "姓名", userData.name);
+//            setCellText(table, 1, "ID", userData.id);
+//            setCellText(table, 2, "部门", userData.department);
+//            setCellText(table, 3, "创建时间",
+//                userData.createTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+//
+//            // 保存Word文档
+//            String wordFile = outputPath + ".docx";
+//            try (FileOutputStream out = new FileOutputStream(wordFile)) {
+//                document.write(out);
+//            }
+//
+//            // 转换为PDF
+//            convertToPdf(wordFile, outputPath + ".pdf");
+//
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+//
+//    private static void setCellText(XWPFTable table, int row, String label, String value) {
+//        XWPFTableRow tableRow = table.getRow(row);
+//        tableRow.getCell(0).setText(label);
+//        tableRow.getCell(1).setText(value);
+//    }
+//
+//    private static void convertToPdf(String wordPath, String pdfPath) {
+//        try {
+//            // 使用LibreOffice进行转换
+//            ProcessBuilder pb = new ProcessBuilder(
+//                "soffice",
+//                "--headless",
+//                "--convert-to", "pdf",
+//                "--outdir", new File(pdfPath).getParent(),
+//                wordPath
+//            );
+//            Process process = pb.start();
+//
+//            // 等待转换完成
+//            int exitCode = process.waitFor();
+//            if (exitCode == 0) {
+//                System.out.println("PDF转换成功!");
+//            } else {
+//                System.out.println("PDF转换失败!");
+//            }
+//
+//            // 删除临时Word文件
+//            new File(wordPath).delete();
+//
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+//
+//    public static void main(String[] args) {
+//        // 示例使用
+//        UserData userData = new UserData("张三", "EMP001", "技术部");
+//        String outputPath = "E:\\";
+//        generateDocument(userData, outputPath);
+//    }
+//}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java
new file mode 100644
index 0000000..6b32fe3
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordTemplateProcessor.java
@@ -0,0 +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);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
index ce14b96..60d821a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
@@ -6,6 +6,7 @@
 import freemarker.template.TemplateException;
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.poi.xwpf.usermodel.*;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Component;
 import org.springframework.web.multipart.MultipartFile;
@@ -15,7 +16,9 @@
 import java.io.*;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
-import java.util.Map;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @Slf4j
 @Component
@@ -110,35 +113,38 @@
     }
 
 
-    public String generatePdf(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
+    public String generatePdf(String basePackagePath, String templateFileName, Map<String,Object> templateParam, String fileName, String saveDirectory) {
         try {
+
+            fillTemplate(basePackagePath+templateFileName, saveDirectory+fileName+".docx", templateParam);
+
             // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
-            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
-            configuration.setDefaultEncoding("utf-8");
-            // 设置模板加载器,加载模板文件
-            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
-            Template t = configuration.getTemplate(templateFileName, "utf-8");
-
-            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
-//            String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
-            String encodedFileName =fileName ;
-
-            // 定义保存文件的路径
-            File saveDir = new File(saveDirectory);
-            if (!saveDir.exists()) {
-                saveDir.mkdirs();
-            }
-
-            // 定义文件名
-            String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
-
-            // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
-            Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
-
-            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
-            t.process(templateParam, out);
-            out.close();
-
+//            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+//            configuration.setDefaultEncoding("utf-8");
+//            // 设置模板加载器,加载模板文件
+//            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
+//            Template t = configuration.getTemplate(templateFileName, "utf-8");
+//
+//            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
+////            String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
+//            String encodedFileName =fileName ;
+//
+//            // 定义保存文件的路径
+//            File saveDir = new File(saveDirectory);
+//            if (!saveDir.exists()) {
+//                saveDir.mkdirs();
+//            }
+//
+//            // 定义文件名
+//            String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
+//
+//            // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
+//            Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
+//
+//            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
+//            t.process(templateParam, out);
+//            out.close();
+            String filePath = saveDirectory + File.separator + fileName + ".docx";
             File file = new File(filePath);
 
             // 检查文件是否存在
@@ -152,16 +158,263 @@
                 fis.read(fileContent);
             }
 
-            String test = pdfUtils.test(encodedFileName + ".doc");
+            String test = pdfUtils.test(fileName + ".docx");
 //            MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
 //            String s = ObsUploadUtil.obsUpload(mockMultipartFile);
             return test;
-        } catch (IOException | TemplateException e) {
+        } catch (IOException e) {
             log.error("生成pdf异常,异常原因:{}", e.getMessage(), e);
             throw new RuntimeException("生成pdf异常,异常原因:" + e.getMessage());
         }
     }
 
+    public static void fillTemplate(String templatePath, String outputPath,Map<String, Object> dataMap) {
+        try (FileInputStream fis = new FileInputStream(templatePath)) {
+            // 设置默认编码为UTF-8
+            System.setProperty("file.encoding", "UTF-8");
+
+            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);
+                        }
+                    }
+                }
+            }
+
+            // 使用UTF-8编码保存文件
+            try (FileOutputStream fos = new FileOutputStream(outputPath)) {
+                document.write(fos);
+            }
+
+            System.out.println("模板填充完成!文件保存在: " + outputPath);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void replaceParagraph(XWPFParagraph paragraph, Map<String, Object> dataMap) {
+        // 获取段落中所有runs
+        List<XWPFRun> runs = paragraph.getRuns();
+        if (runs == null || runs.isEmpty()) return;
+
+        // 首先合并所有runs的文本,以便正确识别占位符
+        StringBuilder fullText = new StringBuilder();
+        for (XWPFRun run : runs) {
+            String text = run.getText(0);
+            if (text != null) {
+                fullText.append(text);
+            }
+        }
+
+        String paragraphText = fullText.toString();
+
+        // 使用正则表达式查找所有占位符,包括括号内的
+        Pattern pattern = Pattern.compile("\\$\\{[^}]+\\}|\\([^)]*\\$\\{[^}]+\\}[^)]*\\)");
+        Matcher matcher = pattern.matcher(paragraphText);
+
+        List<ReplacementInfo> replacements = new ArrayList<>();
+
+        // 收集所有需要替换的信息
+        while (matcher.find()) {
+            String matched = matcher.group();
+            int start = matcher.start();
+            int end = matcher.end();
+
+            // 找出涉及到的runs
+            int startRun = -1;
+            int endRun = -1;
+            int currentPos = 0;
+
+            for (int i = 0; i < runs.size(); i++) {
+                XWPFRun run = runs.get(i);
+                String runText = run.getText(0);
+                if (runText == null) continue;
+
+                int runLength = runText.length();
+                if (startRun == -1 && currentPos + runLength > start) {
+                    startRun = i;
+                }
+                if (currentPos + runLength >= end) {
+                    endRun = i;
+                    break;
+                }
+                currentPos += runLength;
+            }
+
+            if (startRun != -1 && endRun != -1) {
+                // 处理括号内的占位符
+                String replacement = processPlaceholder(matched, dataMap);
+                replacements.add(new ReplacementInfo(startRun, endRun, matched, replacement));
+            }
+        }
+
+        // 从后向前替换,避免位置变化影响
+        Collections.sort(replacements, (a, b) -> b.startRun - a.startRun);
+
+        for (ReplacementInfo info : replacements) {
+            replaceRunRange(paragraph, info);
+        }
+    }
+
+    private static String processPlaceholder(String text, Map<String, Object> dataMap) {
+        // 处理括号内的占位符
+        Pattern placeholderPattern = Pattern.compile("\\$\\{([^}]+)\\}");
+        Matcher matcher = placeholderPattern.matcher(text);
+
+        StringBuffer result = new StringBuffer();
+        while (matcher.find()) {
+            String placeholder = matcher.group(0); // 完整的占位符
+            String key = matcher.group(1); // 占位符中的键
+            String replacement = Objects.nonNull(dataMap.get("${" + key + "}"))?String.valueOf(dataMap.get("${" + key + "}")):"";
+
+            if (replacement != null) {
+                // 如果在括号内,保留括号
+                if (text.startsWith("(") && text.endsWith(")")) {
+                    matcher.appendReplacement(result, replacement);
+                } else {
+                    matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
+                }
+            }
+        }
+        matcher.appendTail(result);
+
+        return result.toString();
+    }
+
+    private static class ReplacementInfo {
+        int startRun;
+        int endRun;
+        String originalText;
+        String replacementText;
+
+        ReplacementInfo(int startRun, int endRun, String originalText, String replacementText) {
+            this.startRun = startRun;
+            this.endRun = endRun;
+            this.originalText = originalText;
+            this.replacementText = replacementText;
+        }
+    }
+
+    private static void replaceRunRange(XWPFParagraph paragraph, ReplacementInfo info) {
+        List<XWPFRun> runs = paragraph.getRuns();
+
+        // 保存第一个run的样式
+        XWPFRun styleRun = runs.get(info.startRun);
+        RunStyle style = new RunStyle(styleRun);
+
+        // 删除范围内的所有runs
+        for (int i = info.endRun; i >= info.startRun; i--) {
+            paragraph.removeRun(i);
+        }
+
+        // 创建新的run并设置文本
+        XWPFRun newRun = paragraph.insertNewRun(info.startRun);
+        newRun.setText(info.replacementText);
+
+        // 应用样式
+        style.applyStyle(newRun);
+    }
+
+    // 用于保存和恢复运行样式的辅助类
+    private static class RunStyle {
+        String fontFamily;
+        int fontSize;
+        boolean bold;
+        boolean italic;
+        String color;
+        UnderlinePatterns underline;
+
+        RunStyle(XWPFRun run) {
+            this.fontFamily = run.getFontFamily();
+            this.fontSize = run.getFontSize();
+            this.bold = run.isBold();
+            this.italic = run.isItalic();
+            this.color = run.getColor();
+            this.underline = run.getUnderline();
+        }
+
+        void applyStyle(XWPFRun run) {
+            if (fontFamily != null) {
+                run.setFontFamily(fontFamily);
+                run.setFontFamily(fontFamily, XWPFRun.FontCharRange.eastAsia);
+            }
+            if (fontSize != -1) {
+                run.setFontSize(fontSize);
+            }
+            run.setBold(bold);
+            run.setItalic(italic);
+            if (color != null) {
+                run.setColor(color);
+            }
+            if (underline != null) {
+                run.setUnderline(underline);
+            }
+        }
+    }
+
+//    public String generatePdf(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
+//        try {
+//            // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
+//            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+//            configuration.setDefaultEncoding("utf-8");
+//            // 设置模板加载器,加载模板文件
+//            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
+//            Template t = configuration.getTemplate(templateFileName, "utf-8");
+//
+//            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
+////            String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
+//            String encodedFileName =fileName ;
+//
+//            // 定义保存文件的路径
+//            File saveDir = new File(saveDirectory);
+//            if (!saveDir.exists()) {
+//                saveDir.mkdirs();
+//            }
+//
+//            // 定义文件名
+//            String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
+//
+//            // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
+//            Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
+//
+//            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
+//            t.process(templateParam, out);
+//            out.close();
+//
+//            File file = new File(filePath);
+//
+//            // 检查文件是否存在
+//            if (!file.exists()) {
+//                throw new FileNotFoundException("文件不存在: " + filePath);
+//            }
+//
+//            // 读取文件内容
+//            byte[] fileContent = new byte[(int) file.length()];
+//            try (FileInputStream fis = new FileInputStream(file)) {
+//                fis.read(fileContent);
+//            }
+//
+//            String test = pdfUtils.test(encodedFileName + ".doc");
+////            MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
+////            String s = ObsUploadUtil.obsUpload(mockMultipartFile);
+//            return test;
+//        } catch (IOException | TemplateException e) {
+//            log.error("生成pdf异常,异常原因:{}", e.getMessage(), e);
+//            throw new RuntimeException("生成pdf异常,异常原因:" + e.getMessage());
+//        }
+//    }
+
 
 
 
diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml
index e23f3d5..14887f4 100644
--- a/ruoyi-admin/src/main/resources/application-test.yml
+++ b/ruoyi-admin/src/main/resources/application-test.yml
@@ -17,7 +17,7 @@
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为8080
-  port: 8080
+  port: 8081
   servlet:
     # 应用的访问路径
     context-path: /
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
index fdc926c..989234b 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/IndexController.java
@@ -14,12 +14,14 @@
 import com.ruoyi.common.utils.DateUtils;
 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.web.controller.tool.MyFileUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import jdk.nashorn.internal.parser.Token;
@@ -27,9 +29,13 @@
 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.multipart.MultipartFile;
 
+import java.io.File;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -72,6 +78,13 @@
     private ISysUserService sysUserService;
     @Autowired
     private TContractRentTypeService contractRentTypeService;
+    @Autowired
+    private StateProcessTemplateService processTemplateService;
+
+    public static void main(String[] args) throws IOException {
+        File file = new File("D:\\wechatFiles\\WeChat Files\\wxid_25nztsudcon722\\FileStorage\\File\\2025-03\\2.mp3");
+        MultipartFile multipartFile = MyFileUtil.fileToMultipartFile(file, "3333");
+    }
     /**
      * 获取轮播图管理列表
      */
@@ -109,6 +122,8 @@
         return R.ok(myToDoVO);
     }
 
+
+
     @ApiOperation(value = "租户-当前在租房源")
     @PostMapping(value = "/tenant/myHouse")
     public R<List<MyHouseVO>> myHouse() {
@@ -132,7 +147,7 @@
                     myToDoVO.setHouseAddress(tHouse.getHouseAddress());
                     myToDoVO.setMonthRent(contract.getMonthRent());
                     myToDoVO.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE, contract.getPayType()));
-                    myToDoVO.setMonth(bill.getPayFeesTime() == null ? bill.getPayableFeesTime().getMonth() + "月" : bill.getPayFeesTime().getMonth() + "月");
+                    myToDoVO.setMonth(bill.getPayFeesTime() == null ? bill.getPayableFeesTime().getMonth().getValue() + "月" : bill.getPayFeesTime().getMonth().getValue() + "月");
                     myToDoVO.setHouseArea(tHouse.getHouseArea());
                     myToDoVO.setHouseType(tHouse.getHouseType());
                     myToDoVO.setEndTime(DateUtils.localDateTimeToStringYear(contract.getEndTime()));
@@ -180,7 +195,7 @@
                 myToDoVO.setHouseAddress(tHouse.getHouseAddress());
                 myToDoVO.setMonthRent(contract.getMonthRent());
                 myToDoVO.setPayType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CONTRACT_PAY_TYPE, contract.getPayType()));
-                myToDoVO.setMonth(bill.getPayFeesTime() == null ? bill.getPayableFeesTime().getMonth() + "月" : bill.getPayFeesTime().getMonth() + "月");
+                myToDoVO.setMonth(bill.getPayFeesTime() == null ? bill.getPayableFeesTime().getMonth().getValue() + "月" : bill.getPayFeesTime().getMonth().getValue() + "月");
                 myToDoVO.setHouseArea(tHouse.getHouseArea());
                 myToDoVO.setHouseType(tHouse.getHouseType());
                 myToDoVO.setEndTime(DateUtils.localDateTimeToStringYear(contract.getEndTime()));
@@ -211,16 +226,24 @@
     @PostMapping(value = "/admin/myToDo")
     public R<MyToDoVO> adminMyToDo() {
         MyToDoVO myToDoVO = new MyToDoVO();
-        LoginUserApplet loginUserApplet = tokenService.getLoginUserApplet();
-        if (loginUserApplet != null) {
-            long examineCount = contractService.count(new LambdaQueryWrapper<TContract>()
-                    .eq(TContract::getStatus, 2));
-            myToDoVO.setExamineCount((int) examineCount);
+        LoginUser loginUser = tokenService.getLoginUser();
+        if (loginUser != null) {
+//            long examineCount = contractService.count(new LambdaQueryWrapper<TContract>()
+//                    .eq(TContract::getStatus, 2));
+            ProcessTaskListBO processTaskListBO = new ProcessTaskListBO();
+            PageInfo<ProcessTaskListVO> processTaskListVOPageInfo = processTemplateService.waitTaskPage(processTaskListBO);
+            myToDoVO.setExamineCount((int) processTaskListVOPageInfo.getTotal());
             List<String> contractIds = billService.lambdaQuery().eq(TBill::getPayFeesStatus, 4).list()
                     .stream().map(TBill::getContractId).collect(Collectors.toList());
-            int overdueCount = contractService.lambdaQuery().in(TContract::getId, contractIds).list()
-                    .stream().map(TContract::getTenantId).distinct().collect(Collectors.toList()).size();
-            myToDoVO.setOverdueCount(overdueCount);
+            if(contractIds.isEmpty()){
+                myToDoVO.setOverdueCount(0);
+
+            }else{
+                int overdueCount = contractService.lambdaQuery().in(TContract::getId, contractIds).list()
+                        .stream().map(TContract::getTenantId).distinct().collect(Collectors.toList()).size();
+                myToDoVO.setOverdueCount(overdueCount);
+            }
+
         } else {
             myToDoVO.setExamineCount(0);
             myToDoVO.setOverdueCount(0);
@@ -244,10 +267,11 @@
     @GetMapping(value = "/getDetailById")
     public R<TCheckAcceptRecordVO> getDetailById(@RequestParam String id) {
         TCheckAcceptRecord checkAcceptRecord = checkAcceptRecordService.getById(id);
-        checkAcceptRecord.setCleanSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION, checkAcceptRecord.getCleanSituation()));
-        checkAcceptRecord.setOverallSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION, checkAcceptRecord.getOverallSituation()));
-        checkAcceptRecord.setDeviceSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION, checkAcceptRecord.getDeviceSituation()));
-        checkAcceptRecord.setFurnitureSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION, checkAcceptRecord.getFurnitureSituation()));
+//        checkAcceptRecord.setCleanSituation(checkAcceptRecord.getCleanSituation());
+//        checkAcceptRecord.setOverallSituation(StringUtils.hasLength(checkAcceptRecord.getOverallSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,checkAcceptRecord.getOverallSituation())):"");
+//        checkAcceptRecord.setDeviceSituation(StringUtils.hasLength(checkAcceptRecord.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,checkAcceptRecord.getDeviceSituation())):"");
+//        checkAcceptRecord.setFurnitureSituation(StringUtils.hasLength(checkAcceptRecord.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,checkAcceptRecord.getFurnitureSituation())):"");
+
         TCheckAcceptRecordVO checkAcceptRecordVO = new TCheckAcceptRecordVO();
         BeanUtils.copyProperties(checkAcceptRecord, checkAcceptRecordVO);
         // 查询合同信息
@@ -269,6 +293,7 @@
         dto.setCode(replace.substring(2)+String.format("%03d", size+1));
         dto.setStatus(true);
         // 添加验收记录
+        dto.setCheckPerson(tokenService.getLoginUser().getUser().getNickName());
         checkAcceptRecordService.updateById(dto);
         return R.ok();
     }
@@ -350,6 +375,12 @@
         TContract contract = contractService.getById(bill.getContractId());
         THouse tHouse = houseService.getById(contract.getHouseId());
         res.setHouse(tHouse);
+        res.setConcatStartTime(contract.getStartTime());
+        res.setConcatEndTime(contract.getEndTime());
+        res.setPartyOnePhone(contract.getPartyOnePhone());
+        res.setPartyOnePerson(contract.getPartyTwoPerson());
+        res.setMonthRent(bill.getPayableFeesMoney());
+        res.setPayType(contract.getPayType());
         return R.ok(res);
     }
     @ApiOperation(value = "管理员-我的审批分页列表")
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
index b6d843e..2ab98bb 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -1,14 +1,17 @@
 package com.ruoyi.web.controller.api;
 
 
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.common.constant.DictConstants;
 import com.ruoyi.common.core.domain.R;
 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;
 import com.ruoyi.system.dto.TInvoiceDTO;
 import com.ruoyi.system.model.*;
@@ -53,6 +56,8 @@
     TInvoiceToBillService invoiceToBillService;
     @Autowired
     TokenService tokenService;
+    @Autowired
+    TTenantService tenantService;
 
     @ApiOperation(value = "缴费账单查询分页列表")
     @PostMapping("list")
@@ -68,7 +73,6 @@
         LocalDateTime localDateTime2 = LocalDateTime.now().withYear(2025).withMonth(11).withDayOfMonth(28);
         long allDays = ChronoUnit.DAYS.between(localDateTime1, localDateTime2);
         System.err.println(allDays);
-
     }
 
     @ApiOperation(value = "缴费账单查询列表")
@@ -78,6 +82,18 @@
         query.setUserId(userId);
         List<String> billIds = tBillService.getBillIds(query);
         return R.ok(billIds);
+    }
+
+    @ApiOperation(value = "跳转批量缴费")
+    @PostMapping("/batchBill")
+    public R<String> batchBill(@RequestBody BatchBillDTO dto){
+        String userId = tokenService.getLoginUserApplet().getUserId();
+        List<String> billIds = dto.getBillIds();
+        Integer count = tBillService.batchBillCount(userId, billIds);
+        if(count>0){
+            return R.fail("请优先缴纳水电费");
+        }
+        return R.ok();
     }
 
     @ApiOperation(value = "查看缴费账单详情")
@@ -112,6 +128,13 @@
     @ApiOperation(value = "缴费账单开票")
     @PostMapping(value = "/invoice")
     public R<String> invoice(@RequestBody TInvoiceDTO dto) {
+        String userId = tokenService.getLoginUserApplet().getUserId();
+        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());
         // 添加开票信息
         invoiceService.save(dto);
 
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
index cc86304..d53226b 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
@@ -4,6 +4,8 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SmsUtil;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.dto.TFaultRepairMessageDTO;
 import com.ruoyi.system.model.*;
@@ -14,6 +16,7 @@
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDate;
@@ -41,9 +44,13 @@
     private final TokenService tokenService;
     private final TContractService contractService;
     private final THouseService houseService;
+    private final SmsUtil smsUtil;
+    private final ISysUserService sysUserService;
+
 
     @Autowired
-    public TFaultRepairMessageController(TFaultRepairMessageService tFaultRepairMessageService, TItemService itemService, TItemTypeService itemTypeService, TFaultAreaDicService faultAreaDicService, TFaultDescribeDicService faultDescribeDicService, TokenService tokenService, TContractService contractService, THouseService houseService) {
+    public TFaultRepairMessageController(TFaultRepairMessageService tFaultRepairMessageService, TItemService itemService, TItemTypeService itemTypeService, TFaultAreaDicService faultAreaDicService, TFaultDescribeDicService faultDescribeDicService, TokenService tokenService, TContractService contractService, THouseService houseService,SmsUtil smsUtil
+    ,ISysUserService sysUserService) {
         this.tFaultRepairMessageService = tFaultRepairMessageService;
         this.itemService = itemService;
         this.itemTypeService = itemTypeService;
@@ -52,6 +59,8 @@
         this.tokenService = tokenService;
         this.contractService = contractService;
         this.houseService = houseService;
+        this.smsUtil = smsUtil;
+        this.sysUserService = sysUserService;
     }
 
     /**
@@ -63,7 +72,7 @@
         List<TItemTypeVO> itemTypes = itemTypeService.getItemList(itemName);
         List<TItem> items = itemService.list();
         itemTypes.forEach(itemType -> {
-            itemType.setItemList(items.stream().filter(item -> itemType.getId().equals(item.getTypeId())).collect(Collectors.toList()));
+            itemType.setItemList(items.stream().filter(item -> itemType.getId().equals(item.getTypeId()) && item.getItemName().contains(itemName)).collect(Collectors.toList()));
         });
         return R.ok(itemTypes);
     }
@@ -120,6 +129,15 @@
                 .likeRight(TFaultRepairMessage::getCreateTime, LocalDate.now())).size();
         dto.setCode(replace.substring(2)+String.format("%03d", size+1));
         tFaultRepairMessageService.save(dto);
+        List<SysUser> sysUsers = sysUserService.selectList();
+        if (dto.getRepairType()==2){
+            for (SysUser sysUser : sysUsers) {
+                if (StringUtils.hasLength(sysUser.getPhonenumber())){
+                    System.err.println("发送短信");
+                    smsUtil.sendSms(sysUser.getPhonenumber(),"2375194",new String[]{});
+                }
+            }
+        }
         return R.ok();
     }
 
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
index a46014a..72980d2 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
@@ -51,7 +51,9 @@
     public R<TInformation> getDetailById(@RequestParam String id) {
         // 处理查看次数
         redisCache.increment(Constants.INFORMATION_VIEW + id);
-        return R.ok(informationService.getById(id));
+        TInformation information = informationService.getById(id);
+        information.setViewCount(redisCache.getCacheObject(Constants.INFORMATION_VIEW + information.getId()));
+        return R.ok(information);
     }
 
 }
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index c32e796..eda9119 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -9,6 +9,7 @@
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.domain.entity.SysRole;
 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.utils.SmsUtil;
 import com.ruoyi.framework.web.service.TokenService;
@@ -101,16 +102,8 @@
     {
         AjaxResult ajax = AjaxResult.success();
         // 生成令牌
-        LoginUser loginUser = loginService.loginCode(loginBody.getUsername(), loginBody.getCode());
-        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
-        List<SysRole> roles = loginUser.getUser().getRoles();
-        if(CollectionUtils.isEmpty(roles)){
-            return AjaxResult.error("请关联角色!");
-        }
-        List<SysMenu> menus = roleService.roleInfoFromUserId(loginUser.getUserId());
-
-        ajax.put("menus",menus);
-        ajax.put("roleName",roles.get(0).getRoleName());
+        LoginUserApplet loginUser = loginService.loginCodeApplet(loginBody.getUsername(), loginBody.getCode());
+        ajax.put(Constants.TOKEN, tokenService.createTokenApplet(loginUser));
         ajax.put("userInfo",loginUser);
         return ajax;
     }
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MyFileUtil.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MyFileUtil.java
new file mode 100644
index 0000000..40af28a
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MyFileUtil.java
@@ -0,0 +1,128 @@
+package com.ruoyi.web.controller.tool;
+
+import org.springframework.web.multipart.MultipartFile;
+import java.io.*;
+import java.nio.file.Files;
+ 
+ 
+/**
+ * @author RainbowCloud
+ */
+public class MyFileUtil {
+ 
+    /**
+     * 将 File 转换为 MultipartFile。
+     *
+     * @param file      要转换的文件
+     * @param fieldName 字段名,通常用于表单中的文件字段名
+     * @return 转换后的 MultipartFile
+     * @throws IOException 如果发生I/O错误
+     */
+    public static MultipartFile fileToMultipartFile(File file, String fieldName) throws IOException {
+        try {
+            if (file == null || !file.exists()) {
+                throw new FileNotFoundException("文件未找到:" + file);
+            }
+            byte[] content = Files.readAllBytes(file.toPath());
+            return new ByteArrayMultipartFile(content, file.getName(), fieldName, Files.probeContentType(file.toPath()));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            // 删除临时文件
+            file.delete();
+        }
+    }
+ 
+    /**
+     * 将 MultipartFile 转换为 File。
+     *
+     * @param multipartFile 要转换的 MultipartFile
+     * @return 转换后的 File
+     * @throws IOException 如果发生I/O错误
+     */
+    public static File multipartFileToFile(MultipartFile multipartFile) throws IOException {
+        if (multipartFile.isEmpty()) {
+            throw new IOException("传入的MultipartFile为空");
+        }
+        String originalFilename = multipartFile.getOriginalFilename();
+        String tempFileSuffix = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf('.')) : ".tmp";
+        File tempFile = File.createTempFile("temp", tempFileSuffix);
+        try (InputStream ins = multipartFile.getInputStream();
+             OutputStream os = new FileOutputStream(tempFile)) {
+            byte[] buffer = new byte[8192];
+            int bytesRead;
+            while ((bytesRead = ins.read(buffer)) != -1) {
+                os.write(buffer, 0, bytesRead);
+            }
+        }
+        return tempFile;
+    }
+ 
+    /**
+     * 内置一个简单的 MultipartFile 实现类,用于File转换
+     */
+    private static class ByteArrayMultipartFile implements MultipartFile {
+        private final byte[] content;
+        private final String name;
+        private final String originalFilename;
+        private final String contentType;
+ 
+        /**
+         * 构造函数
+         *
+         * @param content         文件内容
+         * @param originalFilename 文件原始名字
+         * @param name            字段名
+         * @param contentType     文件类型
+         */
+        public ByteArrayMultipartFile(byte[] content, String originalFilename, String name, String contentType) {
+            this.content = content;
+            this.originalFilename = originalFilename;
+            this.name = name;
+            this.contentType = contentType;
+        }
+ 
+        @Override
+        public String getName() {
+            return this.name;
+        }
+ 
+        @Override
+        public String getOriginalFilename() {
+            return this.originalFilename;
+        }
+ 
+        @Override
+        public String getContentType() {
+            return this.contentType;
+        }
+ 
+        @Override
+        public boolean isEmpty() {
+            return (this.content == null || this.content.length == 0);
+        }
+ 
+        @Override
+        public long getSize() {
+            return this.content.length;
+        }
+ 
+        @Override
+        public byte[] getBytes() {
+            return this.content;
+        }
+ 
+        @Override
+        public InputStream getInputStream() {
+            return new ByteArrayInputStream(this.content);
+        }
+ 
+        @Override
+        public void transferTo(File dest) throws IOException, IllegalStateException {
+            try (OutputStream os = new FileOutputStream(dest)) {
+                os.write(this.content);
+            }
+        }
+    }
+ 
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
index 9c5491e..95169c0 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
@@ -28,7 +28,7 @@
      */
     public static final String DICT_TYPE_BUSINESS_ATTRIBUTES = "t_business_attributes";
     /**
-     * 合同状态 1=待提交 2=待审批 3=未签订 4=已签订 5=已驳回 6=已终止 7=待结算 8=已结算
+     * 合同状态 1=待提交 2=待审批 3=未签订 4=已签订 5=已驳回 6=已终止 7=待结算 8=已结算 9合同已签订待审
      */
     public static final String DICT_TYPE_CONTRACT_STATUS = "t_contract_status";
     /**
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java
index eb27892..76492bc 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java
@@ -3,6 +3,8 @@
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * @Description
@@ -67,7 +69,7 @@
         dateTime = dateTime.substring(2);
         String timestampPart = "" + (Math.random() * 10000) * (System.currentTimeMillis() / 10000);
         timestampPart = timestampPart.replace(".", "").replace("E", "");
-        timestampPart = timestampPart.substring(0, 5);
+        timestampPart = timestampPart.substring(0, 0);
         return dateTime + timestampPart;
     }
 
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
index eadb4d3..e54ccc2 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -2,8 +2,14 @@
 
 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;
@@ -52,6 +58,8 @@
     
     @Autowired
     private ISysUserService userService;
+    @Autowired
+    private TTenantService tenantService;
 
     @Autowired
     private ISysConfigService configService;
@@ -127,8 +135,6 @@
      */
     public LoginUser loginCode(String username,String code)
     {
-
-
         // 登录前置校验
         if (StringUtils.isEmpty(username)){
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
@@ -163,6 +169,43 @@
         return loginUser;
     }
 
+    /**
+     * 登录验证
+     *
+     * @param username 用户名
+     * @param code 验证码
+     * @return 结果
+     */
+    public LoginUserApplet loginCodeApplet(String username, String code)
+    {
+        // 登录前置校验
+        if (StringUtils.isEmpty(username)){
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+            throw new UserNotExistsException();
+        }
+        // 用户验证
+        TTenant user = tenantService.getOne(Wrappers.<TTenant>lambdaQuery().eq(TTenant::getAccount,username));
+        if (StringUtils.isNull(user)){
+            log.info("登录用户:{} 不存在.", username);
+            throw new ServiceException(MessageUtils.message("user.not.exists"));
+        } else if (user.getDisabled()) {
+            log.info("登录用户:{} 已被删除.", username);
+            throw new ServiceException(MessageUtils.message("user.password.delete"));
+        }
+        // 校验验证码
+        Object cacheObject = redisCache.getCacheObject(user.getAccount());
+        if(!code.equals(String.valueOf(cacheObject))){
+            log.info("登录用户:{} 短信验证码错误{}", username,code);
+            throw new ServiceException("短信验证码错误");
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        TTenantResp tTenantResp = new TTenantResp();
+        BeanUtils.copyProperties(user,tTenantResp);
+        LoginUserApplet loginUser = new LoginUserApplet(user.getId(), null, tTenantResp, null);
+        // 生成token
+        return loginUser;
+    }
+
 
     /**
      * 校验验证码
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/BatchBillDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/BatchBillDTO.java
new file mode 100644
index 0000000..4910ba6
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/BatchBillDTO.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@ApiModel(value = "批量缴费校验")
+public class BatchBillDTO implements Serializable {
+
+    @ApiModelProperty(value = "账单id集合")
+    private List<String> billIds;
+
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
index 2ad934f..357d516 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
@@ -44,4 +44,6 @@
     BigDecimal statisticsPayed();
 
     BigDecimal statisticsOverdue();
+
+    Integer batchBillCount(@Param("userId")String userId, @Param("billIds")List<String> billIds);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
index 42b77b4..cee2df3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
@@ -1,18 +1,16 @@
 package com.ruoyi.system.model;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.*;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+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;
@@ -34,10 +32,43 @@
 @EqualsAndHashCode(callSuper = false)
 @TableName("t_bill")
 @ApiModel(value="TBill对象", description="租金账单")
-public class TBill extends BaseModel {
+public class TBill implements Serializable {
 
     private static final long serialVersionUID = 1L;
+    /**
+     * 新增执行
+     */
+    @ApiModelProperty(value = "记录创建人,前端忽略")
+    @JsonIgnore
+    @TableField(value = "create_by", fill = FieldFill.INSERT)
+    private String createBy;
 
+    /**
+     * 新增和更新执行
+     */
+    @ApiModelProperty(value = "记录修改人,前端忽略")
+    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
+    private String updateBy;
+    /**
+     * 删除  未删除
+     */
+    @JsonIgnore
+    @TableField("`disabled`")
+    @TableLogic
+    private Boolean disabled;
+
+    @ApiModelProperty(value = "记录创建时间,前端忽略")
+    @TableField("create_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 最后修改时间
+     */
+    @ApiModelProperty(value = "记录修改时间,前端忽略")
+    @TableField("update_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
     @TableId(value = "id", type = IdType.ASSIGN_ID)
     private String id;
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
index c2c2834..14257ff 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
@@ -146,7 +146,7 @@
      * 7	待结算
      * 8	已结算
      */
-    @ApiModelProperty(value = "合同状态 1=待提交 2=待审批 3=未签订 4=已签订 5=已驳回 6=已终止 7=待结算 8=已结算")
+    @ApiModelProperty(value = "合同状态 1=待提交 2=待审批 3=未签订 4=已签订 5=已驳回 6=已终止 7=待结算 8=已结算 9 = 签订待审核")
     @TableField("status")
     private String status;
     @ApiModelProperty(value = "内存大小多个文件逗号拼接")
@@ -172,6 +172,6 @@
     private String houseAddress;
     @ApiModelProperty(value = "审批流实例id")
     @TableField(exist = false)
-    private Long instanceId;
+    private String instanceId;
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java
index e5a60cd..1d66290 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/TBillQuery.java
@@ -22,6 +22,11 @@
      */
     @ApiModelProperty("租户ID")
     private String userId;
+    /**
+     * 账单类型
+     */
+    @ApiModelProperty("账单类型 1=租金 2=押金 3=生活费用 4=房屋验收")
+    private Integer billType;
 
 
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
index 19b7f69..0015ee5 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
@@ -85,4 +85,6 @@
     Boolean cashPay(CachPayDto offlinePayDto);
 
     BillStatisticsDto statistics();
+
+    Integer batchBillCount(String userId, List<String> billIds);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java
index 4926b6d..96320ad 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java
@@ -30,15 +30,22 @@
 import com.ruoyi.common.enums.ProcessCategoryEnum;
 import com.ruoyi.common.enums.SubmitStatusEnum;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.system.service.ISysRoleService;
-import com.ruoyi.system.service.TContractService;
+import com.ruoyi.system.mapper.TCheckAcceptRecordMapper;
+import com.ruoyi.system.model.*;
+import com.ruoyi.system.service.*;
 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;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -68,8 +75,20 @@
     private final ISysRoleService sysRoleService;
     private final FlwTaskMapper flwTaskMapper;
     private final TContractService contractService;
+    private final TContractRentTypeService contractRentTypeService;
+    private final TBillService billService;
+    private final TCheckAcceptRecordMapper checkAcceptRecordMapper;
+    private final THouseService houseService;
 
+    public static void main(String[] args) {
+//        LocalDate localDate1 = LocalDate.now().withYear(2025).withMonth(4).withDayOfMonth(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);
 
+        long between = ChronoUnit.DAYS.between(localDate1, localDate2)+1;
+        System.err.println(between);
+    }
     @Override
     public boolean notify(EventType eventType, Supplier<FlwTask> supplier, NodeModel nodeModel, FlowCreator flowCreator) {
         FlwTask flwTask = supplier.get();
@@ -101,7 +120,7 @@
                             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);
 
 
                     //对比发起人和节点审批人
@@ -124,9 +143,9 @@
                     List<String> roleIds = nodeAssigneeList.stream().map(NodeAssignee::getId).collect(Collectors.toList());
                     List<SysRole> actorList = sysRoleService.selectRoleByUserIds(roleIds);
                     List<FlwTaskActor> flwTaskActors = new ArrayList<>();
-                    if(ObjectUtils.isNotEmpty(actorList)) {
+                    if (ObjectUtils.isNotEmpty(actorList)) {
                         for (SysRole sysRole : actorList) {
-                            if(ObjectUtil.isEmpty(sysRole.getRoleName())) {
+                            if (ObjectUtil.isEmpty(sysRole.getRoleName())) {
                                 continue;
                             }
                             NodeAssignee nodeAssignee = new NodeAssignee();
@@ -152,7 +171,7 @@
                             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);
 
 
                     //对比发起人和节点审批人
@@ -185,8 +204,8 @@
                 log.error("节点不存在 TaskName:{} InstanceId:{}", flwTask.getTaskName(), flwTask.getInstanceId());
                 return true;
             }
-            long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId,flwTask.getInstanceId()));
-            if(count > 0){
+            long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId, flwTask.getInstanceId()));
+            if (count > 0) {
                 return true;
             }
             //最后一个节点
@@ -209,7 +228,7 @@
                 System.out.println("流程完成:" + flwTask.getVariable());
                 handlerBusiness(flwTask.getVariable(), 1);
             }
-        } else if(eventType.eq(EventType.autoJump)){
+        } else if (eventType.eq(EventType.autoJump)) {
             // 查询流程模型 自动跳转
             FlwExtInstance flwExtInstance = flwExtInstanceMapper.selectById(flwTask.getInstanceId());
             String modelContent = flwExtInstance.getModelContent();
@@ -219,8 +238,8 @@
                 log.error("节点不存在 TaskName:{} InstanceId:{}", flwTask.getTaskName(), flwTask.getInstanceId());
                 return true;
             }
-            long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId,flwTask.getInstanceId()));
-            if(count > 0){
+            long count = flwTaskMapper.selectCount(new LambdaQueryWrapper<FlwTask>().eq(FlwTask::getInstanceId, flwTask.getInstanceId()));
+            if (count > 0) {
                 return true;
             }
             //最后一个节点
@@ -244,21 +263,435 @@
         switch (categoryEnum) {
             case CATEGORY1: {
                 // 合同新增审批
-                int submitStatus = status==0?2:(status==1?3:5);
+                int submitStatus = status == 0 ? 2 : (status == 1 ? 3 : 1);
                 contractService.updateContractAuditStatus(processParameter.getString("projectId"), submitStatus);
                 // TODO 发短信
                 break;
             }
             case CATEGORY2: {
                 // 合同签订审批
-                int submitStatus = status==0?3:(status==1?4:5);
+                int submitStatus = status == 0 ? 3 : (status == 1 ? 4 : 1);
                 contractService.updateContractAuditStatus(processParameter.getString("projectId"), submitStatus);
+                TContract contract = contractService.getById(processParameter.getString("projectId"));
+                if(contract.getStatus().equals("4")){
+
+                    // 修改房屋状态
+                    THouse house = houseService.getById(contract.getHouseId());
+                    if(Objects.nonNull(house)){
+                        house.setLeaseStatus("2");
+                        houseService.updateById(house);
+                    }
+                    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());
+                    rentBill.setContractNumber(contract.getContractNumber());
+                    rentBill.setPayableFeesTime(firstPayTime.toLocalDate());
+                    rentBill.setPayFeesStatus("1");
+
+                    rentBill.setBillType("1");
+                    rentBill.setStartTime(contract.getStartPayTime());
+                    if (rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).isAfter(contract.getEndTime())) {
+                        if (rentBill.getStartTime().getDayOfMonth() != 1) {
+                            rentBill.setEndTime(rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()));
+                        } else {
+                            rentBill.setEndTime(rentBill.getStartTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).with(TemporalAdjusters.lastDayOfMonth()));
+                        }
+                    } else {
+                        rentBill.setEndTime(rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()));
+                    }
+                    if (tContractRentType != null && rentBill.getEndTime().isAfter(tContractRentType.getChangeTime())) {
+                        long moneyDays = 0;
+                        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;
+                        }
+                        // 不需要涨租金的时间段
+                        long 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));
+                        rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                        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().multiply(new BigDecimal(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12)));
+                        } 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");
+                    contractService.updateById(contract);
+                    billService.save(rentBill);
+                    billService.save(depositBill);
+                    // 生成后续账单
+                    try {
+                        TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getStartTime)
+                                .last("limit 1").one();
+                        if (!beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate())) {
+                            while (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).isBefore(contract.getEndTime())) {
+                                System.err.println("生成后续账单");
+                                TBill tBill = new TBill();
+                                tBill.setContractId(contract.getId());
+                                tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
+                                tBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).with(TemporalAdjusters.lastDayOfMonth()));
+                                tBill.setContractNumber(contract.getContractNumber());
+                                if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).getDayOfMonth() <= 15) {
+                                    tBill.setPayableFeesTime(contract.getEndTime().toLocalDate());
+                                } else {
+                                    tBill.setPayableFeesTime(beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate());
+                                }
+                                tBill.setContractId(contract.getId());
+                                if (contract.getIsIncreasing()) {
+                                    System.err.println("执行递增递减");
+                                    if (tContractRentType != null) {
+                                        // 如果变过 并且时间在递增递减时间段内
+                                        if (contract.getChangeTime() != null) {
+                                            // 下次递增递减时间
+                                            LocalDateTime changeTime = contract.getChangeTime().plusYears(tContractRentType.getCycleTime());
+                                            // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
+                                            if (changeTime.isBefore(tBill.getEndTime()) && changeTime.isAfter(tBill.getStartTime())) {
+                                                contract.setChangeTime(changeTime);
+                                                // 租金递增递减的时长 天
+                                                long moneyDays = Math.abs(ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), tBill.getEndTime()))+1;
+                                                // 递增递减的租金
+                                                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;
+                                                }
+                                                // 不需要涨租金的时间段
+                                                long originalDays = ChronoUnit.DAYS.between(tBill.getStartTime(), tContractRentType.getChangeTime());
+                                                if (originalDays > 0) {
+                                                    originalMoney = originalMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                            .multiply(new BigDecimal(originalDays));
+                                                }
+                                                tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                                contractService.updateById(contract);
+                                            } else {
+                                                // 不涨租金 用上次的
+                                                tBill.setPayableFeesMoney(contract.getChangeRent().multiply(new BigDecimal(contract.getPayType().equals("1")?1:contract.getPayType().equals("2")?3:12)));
+                                                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                            }
+                                        }else{
+                                            if (tContractRentType.getChangeTime().isBefore(tBill.getEndTime()) && tContractRentType.getChangeTime().isAfter(tBill.getStartTime())) {
+                                                System.err.println("首次递增递减");
+                                                contract.setChangeTime(tContractRentType.getChangeTime());
+                                                // 租金递增递减的时长 天
+                                                long moneyDays = Math.abs(ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), tBill.getEndTime()))+1;
+                                                // 递增递减的租金
+
+                                                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;
+                                                }
+                                                // 不需要涨租金的时间段
+                                                long originalDays = ChronoUnit.DAYS.between(tBill.getStartTime(), tContractRentType.getChangeTime());
+                                                System.err.println("不需要长租金时长"+originalDays);
+                                                if (originalDays > 0) {
+                                                    originalMoney = originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                            .multiply(new BigDecimal(originalDays));
+                                                }
+                                                tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                                contractService.updateById(contract);
+                                            }else{
+                                                tBill.setPayableFeesMoney(contract.getChangeRent().multiply(new BigDecimal(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12)));
+                                                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                            }
+                                        }
+                                    } else {
+                                        tBill.setPayableFeesMoney(contract.getChangeRent().multiply(new BigDecimal(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12)));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                    }
+                                }else {
+                                    System.err.println("不执行递增递减");
+                                    tBill.setPayableFeesMoney(contract.getChangeRent().multiply(new BigDecimal(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12)));
+                                    tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                }
+                                tBill.setContractNumber(contract.getContractNumber());
+                                tBill.setPayFeesStatus("1");
+                                tBill.setBillType("1");
+
+                                billService.save(tBill);
+                                beforeBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12).with(TemporalAdjusters.lastDayOfMonth()));
+                            }
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getStartTime)
+                            .last("limit 1").one();
+                    // 生成最后一笔账单
+                    if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
+                            && beforeBill.getEndTime().isBefore(contract.getEndTime())
+                    ) {
+                        TBill tBill = new TBill();
+                        tBill.setContractId(contract.getId());
+                        tBill.setPayFeesStatus("1");
+                        tBill.setBillType("1");
+                        tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
+                        tBill.setEndTime(contract.getEndTime());
+                        tBill.setContractNumber(contract.getContractNumber());
+                        if (contract.getIsIncreasing()) {
+                            if (tContractRentType != null) {
+                                // 如果变过 并且时间在递增递减时间段内
+                                if (contract.getChangeTime() != null) {
+                                    // 下次递增递减时间
+                                    LocalDateTime changeTime = contract.getChangeTime().plusYears(tContractRentType.getCycleTime());
+                                    // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
+                                    if (changeTime.isBefore(tBill.getEndTime()) && changeTime.isAfter(tBill.getStartTime())) {
+                                        contract.setChangeTime(changeTime);
+                                        // 租金递增递减的时长 天
+                                        long moneyDays = Math.abs(ChronoUnit.DAYS.between(changeTime, tBill.getEndTime()))+1;
+                                        // 递增递减的租金
+                                        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;
+                                        }
+                                        // 不需要涨租金的时间段
+                                        long originalDays = ChronoUnit.DAYS.between(tBill.getStartTime(), changeTime);
+                                        if (originalDays > 0) {
+                                            originalMoney = originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                    .multiply(new BigDecimal(originalDays));
+                                        }
+                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                        contractService.updateById(contract);
+                                    } else {
+                                        long finalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
+                                        tBill.setPayableFeesMoney(contract.getChangeRent().divide(new BigDecimal("30"),2,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(finalDays)));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                    }
+                                }else{
+                                    if (tContractRentType.getChangeTime().isBefore(tBill.getEndTime()) && tContractRentType.getChangeTime().isAfter(tBill.getStartTime())) {
+                                        contract.setChangeTime(tContractRentType.getChangeTime());
+                                        // 租金递增递减的时长 天
+                                        long moneyDays = Math.abs(ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), tBill.getEndTime()))+1;
+                                        // 递增递减的租金
+                                        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;
+                                        }
+                                        // 不需要涨租金的时间段
+                                        long originalDays = ChronoUnit.DAYS.between(tBill.getStartTime(), tContractRentType.getChangeTime());
+                                        if (originalDays > 0) {
+                                            originalMoney = originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                    .multiply(new BigDecimal(originalDays)).setScale(2,BigDecimal.ROUND_DOWN);
+                                        }
+                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                        contractService.updateById(contract);
+
+                                    }
+                                }
+                            } else {
+                                if (tBill.getStartTime().getDayOfMonth()==1 && tBill.getEndTime().toLocalDate().equals(tBill.getEndTime().with(TemporalAdjusters.lastDayOfMonth()).toLocalDate())){
+                                    tBill.setPayableFeesMoney(contract.getChangeRent().multiply(new BigDecimal(contract.getPayType().equals("1") ? 1 : contract.getPayType().equals("2") ? 3 : 12)));
+                                    tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                }else{
+                                    // 最后一笔账单时间
+                                    long finalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
+                                    tBill.setPayableFeesMoney(contract.getChangeRent().divide(new BigDecimal("30"),2,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(finalDays)));
+                                    tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                                }
+                            }
+                        }else{
+                            long finalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
+                            tBill.setPayableFeesMoney(contract.getChangeRent().divide(new BigDecimal("30"),2,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(finalDays)));
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                        }
+                        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());
+                        }
+                        billService.save(tBill);
+                    }
+                }
                 break;
             }
             case CATEGORY3: {
                 // 合同提前终止审批
-                int submitStatus = status==0?4:(status==1?6:5);
+                int submitStatus = status == 0 ? 4 : (status == 1 ? 7 : 5);
                 contractService.updateContractAuditStatus(processParameter.getString("projectId"), submitStatus);
+                // 生成验收记录
+                TContract contract = contractService.getById(processParameter.getString("projectId"));
+                TCheckAcceptRecord tCheckAcceptRecord = new TCheckAcceptRecord();
+                tCheckAcceptRecord.setContractId(contract.getId());
+                tCheckAcceptRecord.setHouseId(contract.getHouseId());
+                tCheckAcceptRecord.setLeaseReason("后台终止合同");
+                tCheckAcceptRecord.setAcceptanceTime(LocalDateTime.now());
+                LocalDate now = LocalDate.now();
+                String replace = (now + "").replace("-", "");
+                int size = checkAcceptRecordMapper.selectList(new LambdaQueryWrapper<TCheckAcceptRecord>()
+                        .likeRight(TCheckAcceptRecord::getAcceptanceTime, LocalDate.now())).size();
+                tCheckAcceptRecord.setCode(replace.substring(2) + String.format("%03d", size + 1));
+
+                checkAcceptRecordMapper.insert(tCheckAcceptRecord);
+
                 break;
             }
             default:
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java
index cbefcad..14e744d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StateProcessTemplateServiceImpl.java
@@ -1281,7 +1281,7 @@
 
         // 查询历史任务
         List<FlwHisTask> flwHisTasks = flwHisTaskMapper.selectList(Wrappers.<FlwHisTask>lambdaQuery().eq(FlwHisTask::getInstanceId, instanceId));
-
+        processDetailVO.setInstanceId(String.valueOf(instanceId));
         processDetailVO.setFlwHisTasks(flwHisTasks);
 
         List<StateProcessInstanceAction> list = stateProcessInstanceActionService.list(Wrappers.<StateProcessInstanceAction>lambdaQuery().eq(StateProcessInstanceAction::getInstanceId, instanceId)
@@ -1365,6 +1365,7 @@
             sysUserMap = new HashMap<>();
         }
         for (ProcessTaskListVO processTaskListVO : processTaskListVOS) {
+            processTaskListVO.setStatus(processTaskListVO.getTaskState() == 10 ? "2" : processTaskListVO.getTaskState().toString());
             processTaskListVO.setTaskId(processTaskListVO.getId());
             SysUser sysUser = sysUserMap.get(processTaskListVO.getCreateBy());
             if (Objects.nonNull(sysUser)) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
index b3911bb..0376220 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -547,5 +547,10 @@
         return dto;
     }
 
+    @Override
+    public Integer batchBillCount(String userId, List<String> billIds) {
+        return this.baseMapper.batchBillCount(userId,billIds);
+    }
+
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
index d84a843..7006063 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
@@ -17,6 +17,7 @@
 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;
 
@@ -39,12 +40,11 @@
     public PageInfo<TCheckAcceptRecordVO> pageList(TCheckAcceptRecordQuery query) {
         PageInfo<TCheckAcceptRecordVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
         List<TCheckAcceptRecordVO> list = this.baseMapper.pageList(query,pageInfo);
-
         list.forEach(item -> {
-            item.setCleanSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation()));
-            item.setOverallSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getOverallSituation()));
-            item.setDeviceSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getDeviceSituation()));
-            item.setFurnitureSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getFurnitureSituation()));
+            item.setCleanSituation(StringUtils.hasLength(item.getCleanSituation()) ?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation())):"");
+            item.setOverallSituation(StringUtils.hasLength(item.getOverallSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getOverallSituation())):"");
+            item.setDeviceSituation(StringUtils.hasLength(item.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getDeviceSituation())):"");
+            item.setFurnitureSituation(StringUtils.hasLength(item.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getFurnitureSituation())):"");
 
         });
         pageInfo.setRecords(list);
@@ -58,10 +58,10 @@
         PageInfo<TCheckAcceptRecordVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
         List<TCheckAcceptRecordVO> list = this.baseMapper.pageListApplet(query,pageInfo);
         list.forEach(item -> {
-            item.setCleanSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation()));
-            item.setOverallSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getOverallSituation()));
-            item.setDeviceSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getDeviceSituation()));
-            item.setFurnitureSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getFurnitureSituation()));
+            item.setCleanSituation(StringUtils.hasLength(item.getCleanSituation()) ?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation())):"");
+            item.setOverallSituation(StringUtils.hasLength(item.getOverallSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getOverallSituation())):"");
+            item.setDeviceSituation(StringUtils.hasLength(item.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getDeviceSituation())):"");
+            item.setFurnitureSituation(StringUtils.hasLength(item.getDeviceSituation())?(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getFurnitureSituation())):"");
             item.setContract(tContracts.stream().filter(contract -> contract.getId().equals(item.getContractId())).findFirst().orElse(null));
             item.setHouse(tHouses.stream().filter(house -> house.getId().equals(item.getHouseId())).findFirst().orElse(null));
         });
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
index 63040be..30368c2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
@@ -73,6 +73,12 @@
         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()));
+            FlwHisTask flwHisTask = flwHisTaskMapper.selectOne(new LambdaQueryWrapper<FlwHisTask>()
+                    .like(FlwHisTask::getVariable, tContract.getId())
+                    .last("LIMIT 1"));
+            if (Objects.nonNull(flwHisTask)){
+                tContract.setInstanceId(Objects.nonNull(flwHisTask.getInstanceId())?String.valueOf(flwHisTask.getInstanceId()):"");
+            }
         }
         pageInfo.setRecords(list);
         return pageInfo;
@@ -90,7 +96,7 @@
                     .like(FlwHisTask::getVariable, tContract.getId())
                     .last("LIMIT 1"));
             if (Objects.nonNull(flwHisTask)){
-                tContract.setInstanceId(flwHisTask.getInstanceId());
+                tContract.setInstanceId(Objects.nonNull(flwHisTask.getInstanceId())?String.valueOf(flwHisTask.getInstanceId()):"");
             }
         }
         pageInfo.setRecords(list);
@@ -114,9 +120,7 @@
     public void terminateContract(TerminateContractDTO dto) {
         TContract contract = this.baseMapper.selectById(dto.getId());
         contract.setTerminateRemark(dto.getTerminateRemark());
-        contract.setStatus("4");
         this.baseMapper.updateById(contract);
-
         // 进入合同提前终止审批流程
         ProcessStartBO processStartBO = new ProcessStartBO();
         processStartBO.setCategory(ProcessCategoryEnum.CATEGORY3.getValue().toString());
@@ -128,38 +132,11 @@
         processStartBO.setVariable(variable);
         //开启工作流程
         stateProcessTemplateService.start(processStartBO);
-
-        // 生成验收记录
-        TCheckAcceptRecord tCheckAcceptRecord = new TCheckAcceptRecord();
-        tCheckAcceptRecord.setContractId(dto.getId());
-        tCheckAcceptRecord.setHouseId(contract.getHouseId());
-        tCheckAcceptRecord.setLeaseReason("后台终止合同");
-        tCheckAcceptRecord.setStatus(false);
-        tCheckAcceptRecord.setAcceptanceTime(LocalDateTime.now());
-        LocalDate now = LocalDate.now();
-        String replace = (now + "").replace("-", "");
-        int size = checkAcceptRecordMapper.selectList(new LambdaQueryWrapper<TCheckAcceptRecord>()
-                .likeRight(TCheckAcceptRecord::getAcceptanceTime, LocalDate.now())).size();
-        tCheckAcceptRecord.setCode(replace.substring(2)+String.format("%03d", size+1));
-
-
-        checkAcceptRecordMapper.insert(tCheckAcceptRecord);
-        // 将所有未缴费账单设置未已失效
-        List<TBill> tBills = billMapper.selectList(new LambdaQueryWrapper<TBill>()
-                .in(TBill::getPayFeesStatus, Arrays.asList("1,4"))
-                .eq(TBill::getContractId, dto.getId()));
-        for (TBill tBill : tBills) {
-            tBill.setPayFeesStatus("5");
-        }
-        billService.updateBatchById(tBills);
     }
 
     public static void main(String[] args) {
-//        LocalDate now = LocalDate.now();
-//        String replace = (now + "").replace("-", "");
-//        System.err.println(replace.substring(2));
-//
-//        System.err.println(String.format("%03d",1));
+        String t = "1000438";
+        System.err.println("XN" + String.valueOf(t).substring(1));
     }
     @Override
     public CheckAcceptRecordVO getCheckByContractId(String id) {
@@ -182,8 +159,8 @@
         if (contract==null)return R.fail("合同不存在");
         if (contract.getStatus().equals("4"))return R.fail("该合同已签订");
         contract.setSignature(dto.getSignature());
-        contract.setStatus("4");
         contract.setFirstPayTime(contract.getStartTime().plusDays(10));
+        contract.setStatus("9");
         contractMapper.updateById(contract);
 
         // 进入签订审批流程
@@ -198,462 +175,7 @@
         //开启工作流程
         stateProcessTemplateService.startApplet(processStartBO);
 
-        List<TContractRentType> contractRentTypes = contractRentTypeService.list();
-        // 生成第一笔账单
-        // 第一次应缴费日期
-        LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
-        TBill rentBill = new TBill();
-        rentBill.setContractId(contract.getId());
-        rentBill.setContractNumber(contract.getContractNumber());
-        rentBill.setPayableFeesTime(firstPayTime.toLocalDate());
-        rentBill.setPayFeesStatus("1");
 
-        rentBill.setBillType("1");
-        rentBill.setStartTime(contract.getStartPayTime());
-        TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
-        if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){
-            // 计算租金变动的天数
-            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L;
-            contract.setChangeTime(LocalDateTime.now());
-            // 递增递减的租金
-            BigDecimal contractRentTypeMoney = new BigDecimal("0");
-            // 不递增递减的租金
-            BigDecimal originalMoney = new BigDecimal("0");
-            // 原租金
-            switch (tContractRentType.getIncreasingDecreasingType()){
-                case 1:
-                    switch (tContractRentType.getIncreasingDecreasing()){
-                        case 1:
-                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                            contract.setChangeRent(contractRentTypeMoney);
-                            break;
-                        case 2:
-                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                            contract.setChangeRent(contractRentTypeMoney);
-                            break;
-                    }
-                    break;
-                case 2:
-                    switch (tContractRentType.getIncreasingDecreasing()){
-                        case 1:
-                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                            contract.setChangeRent(contractRentTypeMoney);
-                            break;
-                        case 2:
-                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                            contract.setChangeRent(contractRentTypeMoney);
-
-                            break;
-                    }
-                    break;
-            }
-            // 不需要涨租金的时间段
-            long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime());
-            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                    .multiply(new BigDecimal(originalDays));
-            rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-            rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
-            if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
-                rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
-            }else{
-                rentBill.setEndTime(contract.getEndTime());
-            }
-        }else{
-            if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
-                rentBill.setEndTime(contract.getEndTime());
-
-            }else{
-                LocalDateTime firstPayTime1 = contract.getFirstPayTime();
-                // 将firstPayTime1的日设置为当月最后一天
-                rentBill.setEndTime(firstPayTime1.with(TemporalAdjusters.lastDayOfMonth()));
-            }
-            // 不走递增递减
-            long allDays = ChronoUnit.DAYS.between(contract.getStartPayTime().minusDays(1), rentBill.getEndTime());
-            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");
-        this.updateById(contract);
-        billService.save(rentBill);
-        billService.save(depositBill);
-        // 生成后续账单
-        try {
-            TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
-                    .last("limit 1").one();
-            if (!beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate())){
-
-
-            while(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isBefore(contract.getEndTime())){
-                    TBill tBill = new TBill();
-                    tBill.setContractId(contract.getId());
-                    tBill.setContractNumber(contract.getContractNumber());
-                    // 根据支付方式判断需不需要生成订单
-                    if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
-                            &&
-                            (contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12))
-                                    .with(TemporalAdjusters.lastDayOfMonth()).isBefore(contract.getEndTime())
-                            && beforeBill.getEndTime().isBefore(contract.getEndTime())
-                    ){
-                        tBill.setContractId(contract.getId());
-                        if (contract.getIsIncreasing()){
-                            if (tContractRentType!=null
-                                    && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
-                                    && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
-                                // 如果没变过
-                                if (contract.getChangeTime()==null){
-                                    contract.setChangeTime(LocalDateTime.now());
-                                    // 租金递增递减的时长 天
-                                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                    // 递增递减的租金
-                                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                    // 不递增递减的租金
-                                    BigDecimal originalMoney = new BigDecimal("0");
-                                    // 原租金
-                                    switch (tContractRentType.getIncreasingDecreasingType()){
-                                        case 1:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                                    contract.setChangeRent(contractRentTypeMoney);
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                                    contract.setChangeRent(contractRentTypeMoney);
-                                                    break;
-                                            }
-                                            break;
-                                        case 2:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney);
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney);
-
-                                                    break;
-                                            }
-                                            break;
-                                    }
-                                    // 不需要涨租金的时间段
-                                    long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                            .multiply(new BigDecimal(originalDays));
-                                    tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                    tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                                }else{
-                                    // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
-                                    if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
-                                        contract.setChangeTime(LocalDateTime.now());
-                                        // 租金递增递减的时长 天
-                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                        // 递增递减的租金
-                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                        // 不递增递减的租金
-                                        BigDecimal originalMoney = new BigDecimal("0");
-                                        // 原租金
-                                        switch (tContractRentType.getIncreasingDecreasingType()){
-                                            case 1:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                }
-                                                break;
-                                            case 2:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-
-                                                        break;
-                                                }
-                                                break;
-                                        }
-                                        // 不需要涨租金的时间段
-                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                                .multiply(new BigDecimal(originalDays));
-                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                                    }else{
-                                        // 不涨租金 用上次的
-                                        // 租金递增递减的时长 天
-                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                        // 递增递减的租金
-                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                        // 不递增递减的租金
-                                        BigDecimal originalMoney = new BigDecimal("0");
-                                        // 原租金
-                                        switch (tContractRentType.getIncreasingDecreasingType()){
-                                            case 1:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                }
-                                                break;
-                                            case 2:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney);
-
-                                                        break;
-                                                }
-                                                break;
-                                        }
-                                        // 不需要涨租金的时间段
-                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                                .multiply(new BigDecimal(originalDays));
-                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                                    }
-                                }
-
-                            }
-                        }else{
-
-                            tBill.setPayableFeesMoney(contract.getMonthRent());
-                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                        }
-                        tBill.setContractNumber(contract.getContractNumber());
-                        if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
-                            tBill.setPayableFeesTime(contract.getEndTime().toLocalDate());
-                        }else{
-                            tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).toLocalDate()));
-                        }
-                        tBill.setPayFeesStatus("1");
-                        tBill.setBillType("1");
-                        tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
-                        tBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()));
-                        billMapper.insert(tBill);
-                    }
-                beforeBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()));
-            }
-            }
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getStartTime)
-                .last("limit 1").one();
-        // 生成最后一笔账单
-        if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
-                && beforeBill.getEndTime().isBefore(contract.getEndTime())
-        ){
-            TBill tBill = new TBill();
-            tBill.setContractId(contract.getId());
-
-            if (contract.getIsIncreasing()){
-                if (tContractRentType!=null
-                        && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
-                        && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
-                    // 如果没变过
-                    if (contract.getChangeTime()==null){
-                        contract.setChangeTime(LocalDateTime.now());
-                        // 租金递增递减的时长 天
-                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                        // 递增递减的租金
-                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                        // 不递增递减的租金
-                        BigDecimal originalMoney = new BigDecimal("0");
-                        // 原租金
-                        switch (tContractRentType.getIncreasingDecreasingType()){
-                            case 1:
-                                switch (tContractRentType.getIncreasingDecreasing()){
-                                    case 1:
-                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                        contract.setChangeRent(contractRentTypeMoney);
-                                        break;
-                                    case 2:
-                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                        contract.setChangeRent(contractRentTypeMoney);
-                                        break;
-                                }
-                                break;
-                            case 2:
-                                switch (tContractRentType.getIncreasingDecreasing()){
-                                    case 1:
-                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                        contract.setChangeRent(contractRentTypeMoney);
-                                        break;
-                                    case 2:
-                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                        contract.setChangeRent(contractRentTypeMoney);
-
-                                        break;
-                                }
-                                break;
-                        }
-                        // 不需要涨租金的时间段
-                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-
-                        // 不需要涨租金的时间段
-                        if (contract.getFirstPayTime().isBefore(tContractRentType.getChangeTime())){
-                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                    .multiply(new BigDecimal(originalDays));
-                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-                        }else{
-                            tBill.setPayableFeesMoney(contractRentTypeMoney);
-                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-                        }
-
-                    }else{
-                        // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
-                        if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
-                            contract.setChangeTime(LocalDateTime.now());
-                            // 租金递增递减的时长 天
-                            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                            // 递增递减的租金
-                            BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                            // 不递增递减的租金
-                            BigDecimal originalMoney = new BigDecimal("0");
-                            // 原租金
-                            switch (tContractRentType.getIncreasingDecreasingType()){
-                                case 1:
-                                    switch (tContractRentType.getIncreasingDecreasing()){
-                                        case 1:
-                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                        case 2:
-                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                    }
-                                    break;
-                                case 2:
-                                    switch (tContractRentType.getIncreasingDecreasing()){
-                                        case 1:
-                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                        case 2:
-                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                            contract.setChangeRent(contractRentTypeMoney);
-
-                                            break;
-                                    }
-                                    break;
-                            }
-                            // 不需要涨租金的时间段
-                            long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                    .multiply(new BigDecimal(originalDays));
-                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                        }else{
-                            // 不涨租金 用上次的
-                            // 租金递增递减的时长 天
-                            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                            // 递增递减的租金
-                            BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                            // 不递增递减的租金
-                            BigDecimal originalMoney = new BigDecimal("0");
-                            // 原租金
-                            switch (tContractRentType.getIncreasingDecreasingType()){
-                                case 1:
-                                    switch (tContractRentType.getIncreasingDecreasing()){
-                                        case 1:
-                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                        case 2:
-                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                    }
-                                    break;
-                                case 2:
-                                    switch (tContractRentType.getIncreasingDecreasing()){
-                                        case 1:
-                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                            contract.setChangeRent(contractRentTypeMoney);
-                                            break;
-                                        case 2:
-                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                            contract.setChangeRent(contractRentTypeMoney);
-
-                                            break;
-                                    }
-                                    break;
-                            }
-                            // 不需要涨租金的时间段
-                            long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                    .multiply(new BigDecimal(originalDays));
-                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-                        }
-                    }
-
-                }
-            }else{
-                long allDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
-                tBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
-                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
-
-            }
-            tBill.setContractNumber(contract.getContractNumber());
-            if (contract.getEndTime().getDayOfMonth()<=15){
-                tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0).toLocalDate());
-            }else{
-                tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                        beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")?
-                        beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0).toLocalDate()));
-            }
-            tBill.setPayFeesStatus("1");
-            tBill.setBillType("1");
-            tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
-            tBill.setEndTime(contract.getEndTime());
-            billService.save(tBill);
-        }
 
         return R.ok();
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java
index 9aa06f9..259962e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/THouseServiceImpl.java
@@ -41,12 +41,16 @@
                 .le(TContract::getStartTime, LocalDateTime.now())
                 .ge(TContract::getEndTime, LocalDateTime.now()));
         for (THouse tHouse : list) {
-            tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
             tHouse.setBusinessAttributes(DictUtils.getDictLabel(DictConstants.DICT_TYPE_BUSINESS_ATTRIBUTES,tHouse.getBusinessAttributes()));
             TContract tContract = tContracts.stream().filter(e -> e.getHouseId().equals(tHouse.getId())).findFirst().orElse(null);
             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"));
+            }else{
+//                tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
             }
+                            tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
+
         }
         pageInfo.setRecords(list);
         return pageInfo;
@@ -58,6 +62,7 @@
         List<HouseVO> list = this.baseMapper.userHistoryList(query,pageInfo);
         for (HouseVO houseVO : list) {
             houseVO.setTenantAttributes(StringUtils.isNotEmpty(houseVO.getTenantAttributes())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_ATTRIBUTE,houseVO.getTenantAttributes()):"");
+            houseVO.setProductType(StringUtils.isNotEmpty(houseVO.getTenantType())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_TYPE,houseVO.getTenantType()):"");
         }
         pageInfo.setRecords(list);
         return pageInfo;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/StateProcessJob.java b/ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/StateProcessJob.java
index 73e2ab2..0f2d909 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/StateProcessJob.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/StateProcessJob.java
@@ -40,7 +40,7 @@
 			stateProcessTemplateService.agree(processAgreeBO);
 			// 短信发送
 			SysUser sysUser = sysUserService.selectUserById(Long.valueOf(flwTaskActor.getActorId()));
-			smsUtil.sendSms(sysUser.getPhonenumber(), "2369951", new String[]{""});
+			smsUtil.sendSms(sysUser.getPhonenumber(), "2369951", new String[]{});
 		}catch(Exception e){
 			e.printStackTrace();
 		}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java
new file mode 100644
index 0000000..9766aa8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/task/utils/TaskUtil.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.task.utils;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.system.mapper.TBillMapper;
+import com.ruoyi.system.model.TBill;
+import com.ruoyi.system.model.TContract;
+import com.ruoyi.system.service.TContractService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+
+/**
+ * @author zhibing.pu
+ * @date 2023/7/11 8:39
+ */
+@Component
+public class TaskUtil {
+    @Autowired
+    private TContractService contractService;
+    @Autowired
+    private TBillMapper billMapper;
+    // 用于更新违约金账单
+    // 每分钟执行一次的定时任务
+
+    @Scheduled(cron = "0 0 0 * * ?")
+//    @Scheduled(cron = "0 * * * * ?")
+    public void dayOfProportionBill() {
+        try {
+            // 查询所有未缴费账单
+            List<TBill> list = billMapper.selectList(new LambdaQueryWrapper<TBill>().eq(TBill::getPayFeesStatus, 1)
+                    .le(TBill::getPayableFeesTime,LocalDate.now()));
+            for (TBill tBill : list) {
+                tBill.setPayFeesStatus("4");
+                TContract contract = contractService.getById(tBill.getContractId());
+                LocalDate payableFeesTime = tBill.getPayableFeesTime();
+                // 将LocalDate转化为LocalDateTime
+                LocalDateTime payableFeesTime1 = LocalDateTime.of(payableFeesTime, LocalTime.of(0, 0, 0));
+                LocalDateTime now = LocalDateTime.now();
+                // 计算两个时间相差多少个小时
+                long hours = ChronoUnit.HOURS.between(payableFeesTime1, now);
+                long l = hours / 24;
+                if (l>=3){
+                    // 违约金比例
+                    BigDecimal proportion = contract.getProportion();
+                    // 按每天 待缴费金额 * XX% 增加违约金费用
+                    if (tBill.getOutstandingMoney().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);
+
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) {
+
+//        LocalDateTime now = LocalDateTime.now().minusMonths(1).withDayOfMonth(31);
+//        System.err.println(now);
+//        LocalDateTime now2 = now.plusMonths(1);
+//        System.err.println(now2);
+//
+//        LocalDateTime now1 = LocalDateTime.now();
+//        long days = ChronoUnit.DAYS.between(now, now1);
+//        long days2 = ChronoUnit.DAYS.between(now.plusDays(1), now1);
+//
+//        System.err.println(days);
+//        System.err.println(days2);
+//        LocalDateTime endTime = now.with(TemporalAdjusters.lastDayOfMonth()).withSecond(59).withHour(23).withMinute(59);
+//
+//        System.err.println(endTime);
+
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseVO.java
index 4e74bbb..a12cadc 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/HouseVO.java
@@ -30,6 +30,8 @@
     private String tenantAttributes;
     @ApiModelProperty(value = "类型")
     private String productType;
+    @ApiModelProperty(value = "类型")
+    private String tenantType;
     @ApiModelProperty(value = "入住日期")
     @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
     private LocalDateTime startTime;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java
index cada03f..097518b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/ProcessTaskListVO.java
@@ -36,6 +36,7 @@
     private Date createTime;
 
     private String status;
+    private Integer taskState;
 
     private String taskId;
 
@@ -148,4 +149,8 @@
     @ApiModelProperty(value = "合计年租金")
     private BigDecimal totalYear;
 
+    @ApiModelProperty(value = "合同时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime contractTime;
+
 }
diff --git a/ruoyi-system/src/main/resources/mapper/system/StateTaskCenterMapper.xml b/ruoyi-system/src/main/resources/mapper/system/StateTaskCenterMapper.xml
index 6d4fd63..de92a68 100644
--- a/ruoyi-system/src/main/resources/mapper/system/StateTaskCenterMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/StateTaskCenterMapper.xml
@@ -23,7 +23,7 @@
                tc.id AS contractId, tc.contract_number, tc.contract_name, tc.start_time, tc.end_time,tc.deposit, tc.pay_type,
                tc.first_pay_time, tc.isIncreasing,tc.isIncreasing_deposit,tc.proportion, tc.house_id, tc.party_one_name, tc.party_one_person,
                tc.party_one_phone, tc.tenant_id, tc.party_two_name,tc.party_two_person, tc.party_two_phone,tc.memory, tc.contract_file_name,
-               tc.signature, tc.terminate_remark, tc.total_year,tc.status AS contractStatus
+               tc.signature, tc.terminate_remark, tc.total_year,tc.status AS contractStatus,tc.create_time AS contractTime
         from state_task_center stc
         LEFT JOIN t_contract tc ON stc.project_id = tc.id
         <where>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
index 5415d26..81d281c 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
@@ -93,6 +93,9 @@
             <if test="query.userId != null and query.userId !=''">
                 and t.id = #{query.userId}
             </if>
+            <if test="query.billType != null">
+                and b.bill_type = #{query.billType}
+            </if>
             and b.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
         </where>
         order by b.bill_type,b.payable_fees_time
@@ -162,4 +165,25 @@
     <select id="statisticsOverdue" resultType="java.math.BigDecimal">
         SELECT ifnull(sum(outstanding_money),0) as amount FROM t_bill where pay_fees_status=4
     </select>
+    <select id="batchBillCount" resultType="java.lang.Integer">
+        SELECT
+            count(b.id)
+        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>
+            <if test="userId != null and userId !=''">
+                AND t.id = #{userId}
+            </if>
+            <if test="billIds != null and billIds.size() > 0">
+                AND b.id NOT IN
+                <foreach collection="billIds" item="item" index="index" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            AND b.bill_type = 3
+        </where>
+    </select>
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
index d1b8b4b..f0f1693 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
@@ -90,8 +90,11 @@
         left join t_house h on t.house_id = h.id
         <where>
 
-            <if test="query.status != null">
-                AND t.status = #{query.status}
+            <if test="query.status != null and query.status != '' and query.status == 1">
+                AND t.status = 0
+            </if>
+            <if test="query.status != null and query.status != '' and query.status == 2">
+                AND t.status = 1
             </if>
             <if test="query.houseNameOrAddress != null and query.houseNameOrAddress != ''">
                 AND (h.house_name LIKE concat('%', #{query.houseNameOrAddress}, '%') or h.house_address LIKE concat('%', #{query.houseNameOrAddress}, '%'))
diff --git a/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
index 217157a..ba2c3f1 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
@@ -61,6 +61,7 @@
         t.attachment,
         t.attachment_name,
         t.status,
+        t.code,
         t.create_time,
         t.update_time,
         t.create_by,
@@ -103,6 +104,7 @@
             t.create_by,
             t.update_by,
             t.disabled,
+            t.code,
             i.item_name AS itemName,
             it.type_name AS itemTypeName,
             tnt.resident_name AS residentName
@@ -158,6 +160,7 @@
         t.create_by,
         t.update_by,
         t.disabled,
+        t.code,
         i.item_name AS itemName,
         it.type_name AS itemTypeName,
         tnt.resident_name AS residentName
diff --git a/ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml b/ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml
index 0eefc41..d5450f9 100644
--- a/ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/THouseMapper.xml
@@ -29,8 +29,16 @@
         id, house_picture, house_name, house_address, house_area, house_type, business_attributes, product_type, property_right_person, property_right_number, property_right_start_time, property_right_duration, lease_status, create_time, update_time, create_by, update_by, disabled
     </sql>
     <select id="houseList" resultType="com.ruoyi.system.model.THouse">
-        select t1.* from
-            t_house t1
+        select t1.*,t2.start_time as startTime
+        from t_house t1
+        left join t_contract t2
+        on (t2.house_id = t1.id
+        and t2.status != 1
+        and t2.status != 2
+        and t2.status != 3
+        and t2.status != 5
+        and t2.status != 8
+        and NOW() between t2.start_time and t2.end_time)
         <where>
             <if test="req.houseName != null and req.houseName != ''">
                 and t1.house_name like concat('%', #{req.houseName}, '%')
@@ -38,8 +46,14 @@
             <if test="req.propertyRightPerson != null and req.propertyRightPerson != ''">
                 and t1.property_right_person like concat('%', #{req.propertyRightPerson}, '%')
             </if>
-            <if test="req.leaseStatus != null">
+            <if test="req.leaseStatus == 3">
                 and t1.lease_status = #{req.leaseStatus}
+            </if>
+            <if test="req.leaseStatus == 2">
+                and (t2.start_time is not null)
+            </if>
+            <if test="req.leaseStatus == 1">
+                and (t2.start_time is null) and t1.lease_status = 1
             </if>
             AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
         </where>
@@ -56,6 +70,7 @@
             t3.room_number as roomNumber,
             t3.house_area as houseArea,
             t2.phone as loginAccount,
+            t2.tenant_type as tenantType,
             t2.id as tenantId,
             t2.id_card as idCard,
             t2.bank_number as bankNumber,

--
Gitblit v1.7.1