Răsfoiți Sursa

2026/1/25 功能基本实现(到消息推送,还差合同签订正式版)

25057 2 luni în urmă
părinte
comite
06c24b106b
100 a modificat fișierele cu 3077 adăugiri și 1304 ștergeri
  1. 18 10
      src/main/java/com/loan/system/LoanSystemApplication.java
  2. 27 0
      src/main/java/com/loan/system/config/AsyncConfig.java
  3. 55 0
      src/main/java/com/loan/system/config/LifecycleConfig.java
  4. 2 0
      src/main/java/com/loan/system/constant/MessageConstant.java
  5. 32 19
      src/main/java/com/loan/system/controller/admin/AdminController.java
  6. 44 0
      src/main/java/com/loan/system/controller/admin/CollateralController.java
  7. 41 0
      src/main/java/com/loan/system/controller/admin/ContractController.java
  8. 24 2
      src/main/java/com/loan/system/controller/admin/CustomerController.java
  9. 36 335
      src/main/java/com/loan/system/controller/admin/DetailsController.java
  10. 31 4
      src/main/java/com/loan/system/controller/admin/DictionaryController.java
  11. 52 0
      src/main/java/com/loan/system/controller/admin/LoanCaseController.java
  12. 54 6
      src/main/java/com/loan/system/controller/admin/MaterialsController.java
  13. 8 1
      src/main/java/com/loan/system/controller/admin/RecommenderController.java
  14. 19 168
      src/main/java/com/loan/system/controller/wechat/ApprovalController.java
  15. 9 6
      src/main/java/com/loan/system/controller/wechat/CollateralController.java
  16. 5 4
      src/main/java/com/loan/system/controller/wechat/ContractController.java
  17. 1 2
      src/main/java/com/loan/system/controller/wechat/CustomerController.java
  18. 35 51
      src/main/java/com/loan/system/controller/wechat/DisbursementController.java
  19. 36 15
      src/main/java/com/loan/system/controller/wechat/LoanController.java
  20. 5 2
      src/main/java/com/loan/system/controller/wechat/MessageController.java
  21. 12 76
      src/main/java/com/loan/system/controller/wechat/MessageSendController.java
  22. 9 90
      src/main/java/com/loan/system/controller/wechat/OssFileController.java
  23. 22 29
      src/main/java/com/loan/system/controller/wechat/RepaymentController.java
  24. 1 8
      src/main/java/com/loan/system/controller/wechat/StatisticsController.java
  25. 5 5
      src/main/java/com/loan/system/controller/wechat/UploadController.java
  26. 2 26
      src/main/java/com/loan/system/controller/wechat/UserController.java
  27. 1 0
      src/main/java/com/loan/system/domain/dto/ApprovalRecordDTO.java
  28. 14 0
      src/main/java/com/loan/system/domain/dto/BatchDownloadDTO.java
  29. 15 0
      src/main/java/com/loan/system/domain/dto/DetailDTO.java
  30. 0 1
      src/main/java/com/loan/system/domain/dto/DictTypeDTO.java
  31. 2 2
      src/main/java/com/loan/system/domain/dto/DisbursementRecordDTO.java
  32. 1 0
      src/main/java/com/loan/system/domain/dto/DocumentDTO.java
  33. 1 0
      src/main/java/com/loan/system/domain/dto/LoanCaseDTO.java
  34. 1 1
      src/main/java/com/loan/system/domain/dto/RepaymentRecordDTO.java
  35. 16 0
      src/main/java/com/loan/system/domain/dto/query/CollateralQueryDTO.java
  36. 20 0
      src/main/java/com/loan/system/domain/dto/query/ContractQueryDTO.java
  37. 15 0
      src/main/java/com/loan/system/domain/dto/query/CustomerQueryDTO.java
  38. 13 0
      src/main/java/com/loan/system/domain/dto/query/DictDataQueryDTO.java
  39. 15 0
      src/main/java/com/loan/system/domain/dto/query/DocumentQueryDTO.java
  40. 19 0
      src/main/java/com/loan/system/domain/dto/query/LoanCaseQueryDTO.java
  41. 18 0
      src/main/java/com/loan/system/domain/dto/query/RecommenderQueryDTO.java
  42. 15 0
      src/main/java/com/loan/system/domain/dto/query/UserQueryDTO.java
  43. 3 0
      src/main/java/com/loan/system/domain/entity/LoanCase.java
  44. 7 4
      src/main/java/com/loan/system/domain/enums/ExceptionEnum.java
  45. 6 3
      src/main/java/com/loan/system/domain/enums/StepPropertyEnum.java
  46. 1 1
      src/main/java/com/loan/system/domain/pojo/ContractInformation.java
  47. 1 1
      src/main/java/com/loan/system/domain/vo/CollateralVO.java
  48. 5 5
      src/main/java/com/loan/system/domain/vo/CustomerVO.java
  49. 3 2
      src/main/java/com/loan/system/domain/vo/DisbursementDetailVO.java
  50. 1 1
      src/main/java/com/loan/system/domain/vo/DisbursementRecordVO.java
  51. 1 0
      src/main/java/com/loan/system/domain/vo/DisbursementVO.java
  52. 6 2
      src/main/java/com/loan/system/domain/vo/DocumentVO.java
  53. 26 0
      src/main/java/com/loan/system/domain/vo/LoanCaseAdminVO.java
  54. 1 0
      src/main/java/com/loan/system/domain/vo/LoanCaseCompleteVO.java
  55. 1 0
      src/main/java/com/loan/system/domain/vo/LoanCaseSimpleVO.java
  56. 3 0
      src/main/java/com/loan/system/domain/vo/LoanCaseVO.java
  57. 1 0
      src/main/java/com/loan/system/domain/vo/UserVO.java
  58. 39 15
      src/main/java/com/loan/system/exception/GlobalExceptionHandler.java
  59. 17 1
      src/main/java/com/loan/system/repository/CollateralRepository.java
  60. 3 0
      src/main/java/com/loan/system/repository/ContractAndCollateralRepository.java
  61. 24 0
      src/main/java/com/loan/system/repository/ContractRepository.java
  62. 11 0
      src/main/java/com/loan/system/repository/CustomerRepository.java
  63. 12 0
      src/main/java/com/loan/system/repository/DictDataRepository.java
  64. 6 0
      src/main/java/com/loan/system/repository/DictTypeRepository.java
  65. 19 0
      src/main/java/com/loan/system/repository/DocumentRepository.java
  66. 15 4
      src/main/java/com/loan/system/repository/LoanRepository.java
  67. 2 2
      src/main/java/com/loan/system/repository/PawnTicketRepository.java
  68. 14 0
      src/main/java/com/loan/system/repository/RecommenderRepository.java
  69. 8 0
      src/main/java/com/loan/system/repository/StepRepository.java
  70. 13 1
      src/main/java/com/loan/system/repository/UserRepository.java
  71. 9 6
      src/main/java/com/loan/system/service/ApprovalService.java
  72. 11 4
      src/main/java/com/loan/system/service/CollateralPlanService.java
  73. 6 0
      src/main/java/com/loan/system/service/CollateralService.java
  74. 2 0
      src/main/java/com/loan/system/service/ContractAndCollateralService.java
  75. 13 2
      src/main/java/com/loan/system/service/ContractService.java
  76. 7 1
      src/main/java/com/loan/system/service/CustomerService.java
  77. 33 0
      src/main/java/com/loan/system/service/DetailService.java
  78. 8 0
      src/main/java/com/loan/system/service/DictionaryService.java
  79. 9 6
      src/main/java/com/loan/system/service/DisbursementService.java
  80. 19 1
      src/main/java/com/loan/system/service/DocumentService.java
  81. 82 36
      src/main/java/com/loan/system/service/Impl/ApprovalServiceImpl.java
  82. 84 12
      src/main/java/com/loan/system/service/Impl/CollateralPlanServiceImpl.java
  83. 29 0
      src/main/java/com/loan/system/service/Impl/CollateralServiceImpl.java
  84. 5 0
      src/main/java/com/loan/system/service/Impl/ContractAndCollateralServiceImpl.java
  85. 177 73
      src/main/java/com/loan/system/service/Impl/ContractServiceImpl.java
  86. 21 2
      src/main/java/com/loan/system/service/Impl/CustomerServiceImpl.java
  87. 756 0
      src/main/java/com/loan/system/service/Impl/DetailServiceImpl.java
  88. 28 0
      src/main/java/com/loan/system/service/Impl/DictionaryServiceImpl.java
  89. 221 55
      src/main/java/com/loan/system/service/Impl/DisbursementServiceImpl.java
  90. 236 8
      src/main/java/com/loan/system/service/Impl/DocumentServiceImpl.java
  91. 90 39
      src/main/java/com/loan/system/service/Impl/LoanServiceImpl.java
  92. 1 1
      src/main/java/com/loan/system/service/Impl/PawnTicketServiceImpl.java
  93. 14 4
      src/main/java/com/loan/system/service/Impl/RecommenderServiceImpl.java
  94. 150 70
      src/main/java/com/loan/system/service/Impl/RepaymentServiceImpl.java
  95. 18 9
      src/main/java/com/loan/system/service/Impl/StepServiceImpl.java
  96. 21 52
      src/main/java/com/loan/system/service/Impl/UserServiceImpl.java
  97. 2 2
      src/main/java/com/loan/system/service/Impl/WxServiceImpl.java
  98. 12 8
      src/main/java/com/loan/system/service/LoanService.java
  99. 5 1
      src/main/java/com/loan/system/service/RecommenderService.java
  100. 8 7
      src/main/java/com/loan/system/service/RepaymentService.java

+ 18 - 10
src/main/java/com/loan/system/LoanSystemApplication.java

@@ -2,18 +2,19 @@ package com.loan.system;
 
 import com.loan.system.utils.LibreOfficePdfUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
 import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
 import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 
-import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 //@MapperScan(value = {"com/hdu/maintenance/mapper"})
 @SpringBootApplication(exclude = SecurityAutoConfiguration.class)
@@ -21,17 +22,24 @@ import javax.annotation.PreDestroy;
 @EnableJpaAuditing
 @Slf4j
 @EnableGlobalMethodSecurity(prePostEnabled = true)
-public class LoanSystemApplication {
+public class LoanSystemApplication implements ApplicationListener<ContextClosedEvent> {
 
-    public static void main(String[] args) {
-        SpringApplication.run(LoanSystemApplication.class, args);
+    private final AtomicBoolean isShuttingDown = new AtomicBoolean(false);
 
+    @Override
+    public void onApplicationEvent(ContextClosedEvent event) {
+        isShuttingDown.set(true);
+        log.info("Application is shutting down...");
     }
 
+    public static void main(String[] args) {
+        ConfigurableApplicationContext context = SpringApplication.run(LoanSystemApplication.class, args);
+    }
 
     @PreDestroy
     public void stopLibreOffice() throws Exception {
-        LibreOfficePdfUtil.stopOffice();
+        if (!isShuttingDown.get()) {
+            LibreOfficePdfUtil.stopOffice();
+        }
     }
-
-}
+}

+ 27 - 0
src/main/java/com/loan/system/config/AsyncConfig.java

@@ -0,0 +1,27 @@
+package com.loan.system.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+
+    @Bean(name = "customAsyncExecutor")
+    public Executor customAsyncExecutor() {
+        return new ThreadPoolExecutor(
+                2,  // 核心线程数
+                4,  // 最大线程数
+                60L, // 空闲线程存活时间
+                TimeUnit.SECONDS, // 时间单位
+                new LinkedBlockingQueue<>(100), // 工作队列
+                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
+        );
+    }
+}

+ 55 - 0
src/main/java/com/loan/system/config/LifecycleConfig.java

@@ -0,0 +1,55 @@
+package com.loan.system.config;
+
+import org.springframework.context.SmartLifecycle;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+import javax.annotation.PreDestroy;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@Configuration
+public class LifecycleConfig implements SmartLifecycle {
+
+    private final AtomicBoolean running = new AtomicBoolean(false);
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Override
+    public void start() {
+        running.set(true);
+    }
+
+    @Override
+    public void stop() {
+        running.set(false);
+    }
+
+    @Override
+    public void stop(Runnable callback) {
+        running.set(false);
+        callback.run();
+    }
+
+    @Override
+    public boolean isRunning() {
+        return running.get();
+    }
+
+    @PreDestroy
+    public void onDestroy() {
+        // 在bean销毁前执行清理工作
+        // 避免在销毁过程中尝试获取其他bean
+    }
+
+    @Override
+    public boolean isAutoStartup() {
+        return true;
+    }
+
+    @Override
+    public int getPhase() {
+        return 0;
+    }
+}

+ 2 - 0
src/main/java/com/loan/system/constant/MessageConstant.java

@@ -7,4 +7,6 @@ public class MessageConstant {
 
     public static final String TEMPLATE_ID_ONE = "XyQm6-LgN2k3uJLlldCH9ipaaeNJXP7e3yb_QebIMJ8";
     public static final String TEMPLATE_ID_TWO = "XyQm6-LgN2k3uJLlldCH9rxFDKchGQBIvpCioPSCSJo";
+    public static final String TEMPLATE_ID_THREE = "XyQm6-LgN2k3uJLlldCH9sx--1YN0aLssVSqEom9Wbo";
+    public static final String pageUrl = "pages/business/business";
 }

+ 32 - 19
src/main/java/com/loan/system/controller/admin/AdminController.java

@@ -1,13 +1,17 @@
 package com.loan.system.controller.admin;
 
+import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.constant.JwtClaimsConstant;
+import com.loan.system.context.BaseContext;
 import com.loan.system.domain.dto.UserDTO;
 import com.loan.system.domain.dto.UserLoginDTO;
+import com.loan.system.domain.dto.query.UserQueryDTO;
 import com.loan.system.domain.entity.Role;
 import com.loan.system.domain.entity.User;
 import com.loan.system.domain.enums.ExceptionEnum;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.UserLoginVO;
+import com.loan.system.domain.vo.UserVO;
 import com.loan.system.exception.DescribeException;
 import com.loan.system.properties.JwtProperties;
 import com.loan.system.repository.RoleRepository;
@@ -42,8 +46,6 @@ public class AdminController {//包含内部人员、外部人员
     private UserService userService;
     @Autowired
     private RecommenderService recommenderService;
-    @Autowired
-    private CustomerService customerService;
 
     /*
     1.先查询user查看是否为内部人员
@@ -64,19 +66,33 @@ public class AdminController {//包含内部人员、外部人员
         else
             userLoginVO=userService.codeLogin(userLoginDTO.getTel(),userLoginDTO.getValidCode());
 
-
         return ResultUtil.success("success", userLoginVO);
     }
 
+    @GetMapping("/individual")
+    @ApiOperation("查询个人用户信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findIndividual(){
+        return ResultUtil.success("success", BeanUtil.copyProperties(userService.findByIdAndIsDelete(BaseContext.getCurrentId()), UserVO.class));
+    }
+
     @GetMapping("/users")
     @ApiOperation("查询所有用户")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
     public Result findAllUsers(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize,@RequestParam(required = false) Boolean isDelete){
-        return ResultUtil.success("success", userService.getAllUsers(pageNum,pageSize,isDelete));
+        return userService.getAllUsers(pageNum,pageSize,isDelete);
+    }
+
+    @PostMapping("/users/query")
+    @ApiOperation("按条件查询所有用户")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findByQuery(@RequestBody UserQueryDTO userQueryDTO,@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize){
+        return userService.getAllUsersByQuery(userQueryDTO,pageNum,pageSize);
     }
 
     @PostMapping
     @ApiOperation("新增用户")
-    @PreAuthorize("@pms.hasRole('SYSTEM_ADMIN')")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
     public Result addUser(@RequestBody UserDTO user){
         userService.addUser(user);
 
@@ -85,7 +101,7 @@ public class AdminController {//包含内部人员、外部人员
 
     @PutMapping("/role/{id}")
     @ApiOperation("更新用户角色")
-    @PreAuthorize("@pms.hasRole('SYSTEM_ADMIN')")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result updateRole(@PathVariable("id") Long id,@RequestBody String role){
         User user1 = userService.findByIdAndIsDelete(id);
         if(ObjectUtils.isEmpty(user1)){
@@ -97,15 +113,23 @@ public class AdminController {//包含内部人员、外部人员
 
     @PutMapping("/{id}")
     @ApiOperation("更新用户信息")
-    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN,APPROVER,BACK_OFFICE,LEAD_SALES,ASSIST_SALES,FINANCE')")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result updateUser(@PathVariable("id") Long id,@RequestBody UserDTO user){
         userService.updateUserById(id,user);
         return ResultUtil.success("success");
     }
 
+    @PutMapping("/individual")
+    @ApiOperation("更新用户信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result updateIndividual(@RequestBody UserDTO user){
+        userService.updateUserById(BaseContext.getCurrentId(),user);
+        return ResultUtil.success("success");
+    }
+
     @PutMapping("/delete/{id}")
     @ApiOperation("删除用户")
-    @PreAuthorize("@pms.hasRole('SYSTEM_ADMIN')")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result deleteUser(@PathVariable Long id){
         User user = userService.findByIdAndIsDelete(id);
         if(ObjectUtils.isEmpty(user)){
@@ -138,17 +162,6 @@ public class AdminController {//包含内部人员、外部人员
 //        return ResultUtil.success("success");
 //    }
 
-    @GetMapping("/customers")
-    @ApiOperation("查询所有客户")
-    public Result findAllCustomers(Integer pageNum, Integer pageSize){
-        return ResultUtil.success("success", customerService.getAllCustomers(pageNum, pageSize,false));
-    }
-
-    @GetMapping("/customers/{id}")
-    @ApiOperation("按id选择客户")
-    public Result findCustomerById(@PathVariable Long id){
-        return ResultUtil.success("success", customerService.findByCustomerIdAndIsDelete( id, false));
-    }
 
 //    @GetMapping("/customers/{key}")
 //    @ApiOperation("按关键字(姓名/手机号)选择客户")

+ 44 - 0
src/main/java/com/loan/system/controller/admin/CollateralController.java

@@ -0,0 +1,44 @@
+package com.loan.system.controller.admin;
+
+import com.loan.system.domain.dto.query.CollateralQueryDTO;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.service.CollateralService;
+import com.loan.system.utils.ResultUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController("AdminCollateralController")
+@RequestMapping("/admin/collateral")
+@Api(tags = "押品管理")
+public class CollateralController {
+
+    @Autowired
+    private CollateralService collateralService;
+
+    @GetMapping
+    @ApiOperation("分页查询所有押品信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getCollaterals(Integer pageNum, Integer pageSize){
+        return collateralService.getCollaterals(pageNum, pageSize);
+    }
+
+    @PostMapping("/query")
+    @ApiOperation("按条件查询押品信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getCollateralsByKey(@RequestBody CollateralQueryDTO collateralQueryDTO, 
+                                      @RequestParam(defaultValue = "1") Integer pageNum, 
+                                      @RequestParam(defaultValue = "10") Integer pageSize){
+        return collateralService.getCollateralsByKey(collateralQueryDTO, pageNum, pageSize);
+    }
+
+    @DeleteMapping("/{id}")
+    @ApiOperation("删除押品信息(逻辑删除,设置isDelete=1)")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
+    public Result deleteCollateral(@PathVariable("id") Long id){
+        collateralService.logic_delete(id);
+        return ResultUtil.success("success");
+    }
+}

+ 41 - 0
src/main/java/com/loan/system/controller/admin/ContractController.java

@@ -0,0 +1,41 @@
+package com.loan.system.controller.admin;
+
+import com.loan.system.domain.dto.query.ContractQueryDTO;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.service.ContractService;
+import com.loan.system.utils.ResultUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController("AdminContractController")
+@RequestMapping("/admin/contract")
+@Api(tags = "合同管理")
+public class ContractController {
+    @Autowired
+    private ContractService contractService;
+
+    @GetMapping
+    @ApiOperation("查询所有合同")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findAllContract(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10")Integer pageSize) {
+        return contractService.findAllContract(pageNum, pageSize);
+    }
+
+    @PostMapping("/query")
+    @ApiOperation("按条件查询所有合同")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findAllContractByQuery(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10")Integer pageSize, @RequestBody ContractQueryDTO contractQueryDTO) {
+        return contractService.findAllContractByQuery(pageNum, pageSize, contractQueryDTO);
+    }
+
+    @PutMapping("/delete/{id}")
+    @ApiOperation("删除合同")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
+    public Result deleteContract(@PathVariable Long id) {
+        contractService.deleteContractById(id);
+        return ResultUtil.success("删除成功");
+    }
+}

+ 24 - 2
src/main/java/com/loan/system/controller/admin/CustomerController.java

@@ -1,15 +1,20 @@
 package com.loan.system.controller.admin;
 
+import com.loan.system.domain.dto.CustomerDTO;
+import com.loan.system.domain.dto.query.CustomerQueryDTO;
 import com.loan.system.domain.entity.Customer;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.service.CustomerService;
+import com.loan.system.utils.ResultUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
-@RestController
+@RestController("AdminCustomerController")
 @RequestMapping("/admin/customer")
 @Api(tags = "客户管理")
 public class CustomerController {
@@ -18,12 +23,29 @@ public class CustomerController {
 
     @GetMapping
     @ApiOperation("获取所有客户信息")
-    public List<Customer> getAllCustomer(Integer pageNum, Integer pageSize) {
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getAllCustomer(Integer pageNum, Integer pageSize) {
         return customerService.getAllCustomersByAdmin(pageNum, pageSize);
     }
 
+    @PostMapping("/query")
+    @ApiOperation("按关键字查询客户")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getCustomerByKey(@RequestBody CustomerQueryDTO queryDTO, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize){
+        return customerService.listCustomersByQuery(queryDTO, pageNum, pageSize);
+    }
+
+    @PostMapping("/update")
+    @ApiOperation("补充客户信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'BACK_OFFICE')")
+    public Result addInfo(@RequestBody CustomerDTO customerDTO){
+        customerService.updateInfoByOpenId(customerDTO);
+        return ResultUtil.success("success");
+    }
+
     @PutMapping("{id}")
     @ApiOperation("删除客户")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'BACK_OFFICE')")
     public void deleteCustomer(@PathVariable Long id) {
         customerService.deleteCustomerByLogic(id);
     }

+ 36 - 335
src/main/java/com/loan/system/controller/admin/DetailsController.java

@@ -1,7 +1,9 @@
 package com.loan.system.controller.admin;
 
 import com.loan.system.config.FileUploadConfig;
+import com.loan.system.domain.dto.DetailDTO;
 import com.loan.system.domain.entity.*;
+import com.loan.system.domain.enums.DecisionEnum;
 import com.loan.system.domain.enums.StepEnum;
 import com.loan.system.domain.enums.StepPropertyEnum;
 import com.loan.system.domain.pojo.Result;
@@ -14,384 +16,83 @@ import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @RestController
 @RequestMapping("/admin/details")
 @Api(tags = "业务明细")
 public class DetailsController {
-    @Autowired
-    private LoanService loanService;
-    @Autowired
-    private RepaymentService repaymentService;
-    @Autowired
-    private RepaymentRecordService repaymentRecordService;
-    @Autowired
-    private FileUploadConfig fileUploadConfig;
-    @Autowired
-    private ContractService contractService;
-    @Autowired
-    private ContractRepaymentService contractRepaymentService;
-    @Autowired
-    private CustomerService customerService;
-    @Autowired
-    private CustomerOtherService customerOtherService;
-    @Autowired
-    private RecommenderService recommenderService;
-    @Autowired
-    private StepService stepService;
-    @Autowired
-    private UserService userService;
-    @Autowired
-    private PawnTicketService pawnTicketService;
-    @Autowired
-    private DisbursementService disbursementService;
-    @Autowired
-    private CollateralService collateralService;
-    @Autowired
-    private ContractAndCollateralService contractAndCollateralService;
+   @Autowired
+   private DetailService detailService;
 
-    @GetMapping("/accountReport")
-    @ApiOperation("获取台账")
-    public Result accountReport(@RequestParam Long caseId, @RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
-        int begin = pageNum * pageSize;
-        List<LoanCaseDetails> loanCaseDetails = new ArrayList<>();
-        //获取业务信息
-        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
-
-        //获取客户与其它客户信息
-        Customer customer = customerService.findByIdAndIsDelete(loanCase.getCustomerId());
-        List<CustomersOtherVO> customersOtherVOS = customerOtherService.findByCaseId(caseId);
-
-        //获取回款记录信息(核心)
-        List<RepaymentRecord> repaymentRecords = repaymentRecordService.findByRepaymentIdAndIsInterestAndIsDelete(repaymentService.findByCaseIdAndIsDelete(caseId, false).getId(), false);
-        List<Long> recordIds = repaymentRecords.stream().map(RepaymentRecord::getId).collect(Collectors.toList());
-        List<ContractRepayment> contractRepayments = contractRepaymentService.findByRepaymentRecordIdsAndIsDelete(recordIds);
-
-        List<Long> contractIds = contractRepayments.stream().map(ContractRepayment::getContractId).collect(Collectors.toList());
-        for (Long contractId : contractIds) {
-            double amount = 0.0;//累计回款
-            Contract contract = contractService.findContractById(contractId);
-            for (ContractRepayment contractRepayment : contractRepayments) {
-                if (contractRepayment.getContractId().equals(contractId)) {
-                    LoanCaseDetails loanCaseDetail = new LoanCaseDetails();
-
-                    loanCaseDetail.setContractNo(contract.getContractNo());//1
-//                    PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractId);
-//                    if(pawnTicketInfo!=null){
-//                        loanCaseDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
-//                        loanCaseDetail.setRedeemTime(pawnTicketInfo.getEndTime());//16.
-//                        loanCaseDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//17.
-//                    }
-                    loanCaseDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
-                    loanCaseDetail.setCustomerName(customer.getName());//4.
-                    loanCaseDetail.setCustomerName2(customersOtherVOS.get(0).getName());//5.
-                    loanCaseDetail.setPhoneNumber(customer.getMobile());//6.
-                    loanCaseDetail.setPawnAmount(loanCase.getTotalLoanAmount());//7.
-                    List<String> attributes = new ArrayList<>();
-                    List<String> locations = new ArrayList<>();
-                    List<ContractAndCollateral> contractAndCollaterals = contractAndCollateralService.listByContractId(contractId);
-                    for (ContractAndCollateral contractAndCollateral : contractAndCollaterals) {
-                        if (contractAndCollateral.getContractId().equals(contractId)){
-                            Collateral collateral = collateralService.findCollateralById(contractAndCollateral.getCollateralId());
-                            attributes.add(contract.getBusinessAttr());
-                            locations.add(collateral.getAddress());
-                        }
-                    }
-                    loanCaseDetail.setLocations( locations);
-                    loanCaseDetail.setAttributes(attributes);
-
-                    loanCaseDetail.setChannelName(loanCase.getChannelName());//9.
-                    List<String> userNames=new ArrayList<>();
-                    StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
-                    StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
-                    if(stepVO!=null){
-                        userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
-                    }
-                    if(stepVO1!=null){
-                        userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
-                    }
-                    loanCaseDetail.setUserName(userNames);//10.
-
-                    amount += contractRepayment.getAmount();
-                    loanCaseDetail.setRepayTime(contractRepayment.getCreateTime());//11.
-                    loanCaseDetail.setRepayTotalAmount(amount);//12
-                    loanCaseDetail.setLastRepayAmount(contractRepayment.getAmount());//13.
-                    loanCaseDetail.setBalance(loanCase.getTotalLoanAmount() - amount);//14.
-                    if(Math.abs(loanCase.getTotalLoanAmount() - amount)<Double.MIN_VALUE)
-                        loanCaseDetail.setInterestAmount(contract.getInterestAmount());//15.
+    @GetMapping("/arrangeReport")
+    @ApiOperation("获取排期统计表")
+    public Result arrangeReport(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin) {
+        return detailService.getArrangeReport(begin);
+    }
 
-                    loanCaseDetails.add(loanCaseDetail);
-                }
+    @GetMapping("/loanCaseReport")
+    @ApiOperation("获取业务统计表")
+    public Result loanCaseReport(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
+                                 @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
+       return detailService.getLoanCaseReport(begin, end);
+    }
 
-            }
-        }
+    @PostMapping("/loanCaseReport/export")
+    @ApiOperation("导出业务统计表")
+    public void exportLaonCaseReport(@RequestBody DetailDTO<LoanCaseStatistic> detailDTO, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
+                                     @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, HttpServletResponse response) {
+        detailService.exportLoanCaseReport(detailDTO, begin, end, response);
+    }
 
-        return ResultUtil.success("success", loanCaseDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+    @GetMapping("/accountReport")
+    @ApiOperation("获取台账")
+    public Result accountReport(@RequestParam Long caseId, @RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
+        return detailService.getAccountReport(caseId, pageNum, pageSize);
     }
 
     @GetMapping("/accountReport/export")
     @ApiOperation("导出台账")//begin从1开始
     public void exportAccountReport(@RequestBody List<LoanCaseDetails> loanCaseDetails, @RequestParam Integer begin, @RequestParam Integer end, HttpServletResponse response) {
-        //查询概览运营数据,提供给Excel模板文件
-        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "业务台账.xlsx");
-        try {
-            //基于提供好的模板文件创建一个新的Excel表格对象
-            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
-
-            //获得Excel文件中的一个Sheet页
-            XSSFSheet sheet = excel.getSheet("Sheet1");
-            //TODO:row(从0开始)行,cell(从0开始)获取单元格
-            //获得第1行
-            XSSFRow row = sheet.getRow(1);
-            //获取单元格
-            for (int i = begin; i < end; i++) {
-                LoanCaseDetails loanCaseDetail = loanCaseDetails.get(i);
-                row = sheet.getRow(i);
-                row.getCell(0).setCellValue(loanCaseDetail.getContractNo());
-                row.getCell(1).setCellValue(loanCaseDetail.getPawnTicketNo());
-                row.getCell(2).setCellValue(loanCaseDetail.getLoanTime());
-                row.getCell(3).setCellValue(loanCaseDetail.getCustomerName());
-                row.getCell(4).setCellValue(loanCaseDetail.getCustomerName2());
-                row.getCell(5).setCellValue(loanCaseDetail.getPhoneNumber());
-                row.getCell(6).setCellValue(loanCaseDetail.getPawnAmount());
-                row.getCell(7).setCellValue(loanCaseDetail.getLocations().toString());
-                row.getCell(8).setCellValue(loanCaseDetail.getAttributes().toString());
-                row.getCell(9).setCellValue(loanCaseDetail.getChannelName());
-                row.getCell(10).setCellValue(loanCaseDetail.getUserName().toString());
-                row.getCell(11).setCellValue(loanCaseDetail.getRepayTime());
-                row.getCell(12).setCellValue(loanCaseDetail.getRepayTotalAmount());
-                row.getCell(13).setCellValue(loanCaseDetail.getLastRepayAmount());
-                row.getCell(14).setCellValue(loanCaseDetail.getBalance());
-                row.getCell(15).setCellValue(loanCaseDetail.getInterestAmount());
-                row.getCell(16).setCellValue(loanCaseDetail.getRedeemTime());
-                row.getCell(17).setCellValue(loanCaseDetail.getRedeemTicketNo());
-                row.getCell(18).setCellValue(loanCaseDetail.getComment());
-
-            }
-
-            //通过输出流将文件下载到客户端浏览器中
-            ServletOutputStream out = response.getOutputStream();
-            excel.write(out);
-
-            //关闭资源
-            out.flush();
-            out.close();
-            excel.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        detailService.exportAccountReport(loanCaseDetails, begin, end, response);
     }
 
     @GetMapping("/disbursementReport")
     @ApiOperation("获取出款报表")
     public Result disbursementReport(@RequestParam Long caseId,@RequestParam(defaultValue = "0") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize) {
-        int begin = pageNum * pageSize;
-        List<DisbursementDetails> disbursementDetails = new ArrayList<>();
-
-        //获取业务信息
-        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
-        //获取合同信息
-        List<ContractVO> contractVOS = contractService.findContractByCaseId(caseId);
-        for(ContractVO contractVO : contractVOS){
-            DisbursementDetails disbursementDetail = new DisbursementDetails();
-
-            disbursementDetail.setContractNo(contractVO.getContractNo());//1.
-//            PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractVO.getId());
-//            if(pawnTicketInfo!=null){
-//                disbursementDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
-//                disbursementDetail.setRedeemTime(pawnTicketInfo.getEndTime());//9.
-//                disbursementDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//10.
-//            }
-//            disbursementDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
-
-            disbursementDetail.setCustomerName(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false).getName());//4.
-            disbursementDetail.setPawnAmount(contractVO.getContractAmount());//5.
-            List<String> userNames=new ArrayList<>();
-            StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
-            StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
-            if(stepVO!=null){
-                userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
-            }
-            if(stepVO1!=null){
-                userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
-            }
-            disbursementDetail.setUserName(userNames);//6.
-            disbursementDetail.setRecommenderName(recommenderService.getRecommenderById(loanCase.getRecommenderId()).getRecommenderName());//7.
-            disbursementDetail.setChannelName(loanCase.getChannelName());//8.
-
-            disbursementDetails.add(disbursementDetail);
-        }
-
-        //获取当票
-        return ResultUtil.success("success", disbursementDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+        return detailService.getDisbursementReport(caseId, pageNum, pageSize);
     }
 
     @GetMapping("/disbursementReport/export")
     @ApiOperation("导出出款报表")
     public void exportDisbursementReport(@RequestBody List<DisbursementDetails> disbursementDetails, @RequestParam Integer begin, @RequestParam Integer end, HttpServletResponse response) {
-        //查询概览运营数据,提供给Excel模板文件
-        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "出账明细.xlsx");
-        try {
-            //基于提供好的模板文件创建一个新的Excel表格对象
-            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
-
-            //获得Excel文件中的一个Sheet页
-            XSSFSheet sheet = excel.getSheet("Sheet1");
-            //TODO:row(从0开始)行,cell(从0开始)获取单元格
-            //获得第1行
-            XSSFRow row = sheet.getRow(1);
-            //获取单元格
-            for (int i = begin; i < end; i++) {
-                DisbursementDetails disbursementDetail = disbursementDetails.get(i);
-                row = sheet.getRow(i);
-                row.getCell(0).setCellValue(disbursementDetail.getContractNo());
-                row.getCell(1).setCellValue(disbursementDetail.getLoanTime());
-                row.getCell(2).setCellValue(disbursementDetail.getPawnTicketNo());
-                row.getCell(3).setCellValue(disbursementDetail.getCustomerName());
-                row.getCell(4).setCellValue(disbursementDetail.getPawnAmount());
-                row.getCell(5).setCellValue(disbursementDetail.getUserName().toString());
-                row.getCell(6).setCellValue(disbursementDetail.getRecommenderName());
-                row.getCell(7).setCellValue(disbursementDetail.getChannelName());
-                row.getCell(8).setCellValue(disbursementDetail.getRedeemTime());
-                row.getCell(9).setCellValue(disbursementDetail.getRedeemTicketNo());
-
-            }
-
-            //通过输出流将文件下载到客户端浏览器中
-            ServletOutputStream out = response.getOutputStream();
-            excel.write(out);
-
-            //关闭资源
-            out.flush();
-            out.close();
-            excel.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        detailService.exportDisbursementReport(disbursementDetails, begin, end, response);
     }
 
     @GetMapping("/repaymentReport")
     @ApiOperation("获取回款报表")
     public Result repaymentReport(@RequestParam Long caseId,@RequestParam(defaultValue = "0") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize) {
         int begin = pageNum * pageSize;
-        List<RepaymentDetails> repaymentDetails = new ArrayList<>();
-        //获取当票信息
-
-        //获取业务信息
-        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
 
-        //获取客户与其它客户信息
-        Customer customer = customerService.findByIdAndIsDelete(loanCase.getCustomerId());
-
-        //获取回款记录信息(核心)
-        List<RepaymentRecord> repaymentRecords = repaymentRecordService.findByRepaymentIdAndIsInterestAndIsDelete(repaymentService.findByCaseIdAndIsDelete(caseId, false).getId(), false);
-        List<Long> recordIds = repaymentRecords.stream().map(RepaymentRecord::getId).collect(Collectors.toList());
-        List<ContractRepayment> contractRepayments = contractRepaymentService.findByRepaymentRecordIdsAndIsDelete(recordIds);
-
-        List<Long> contractIds = contractRepayments.stream().map(ContractRepayment::getContractId).collect(Collectors.toList());
-        for (Long contractId : contractIds) {
-            double amount = 0.0;//累计回款
-            Contract contract = contractService.findContractById(contractId);
-            for (ContractRepayment contractRepayment : contractRepayments) {
-                if (contractRepayment.getContractId().equals(contractId)) {
-                    RepaymentDetails repaymentDetail = new RepaymentDetails();
-
-                    repaymentDetail.setContractNo(contract.getContractNo());//1
-//                    PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractId);
-//                    if(pawnTicketInfo!=null){
-//                        repaymentDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
-//                        repaymentDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//10.
-//                    }
-                    repaymentDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
-                    repaymentDetail.setCustomerName(customer.getName());//4.
-                    repaymentDetail.setPawnAmount(loanCase.getTotalLoanAmount());//5.
-                    repaymentDetail.setRepayTime(contractRepayment.getCreateTime());//6.
-                    repaymentDetail.setRepayAmount(contractRepayment.getAmount());//7.
-                    amount += contractRepayment.getAmount();
-                    repaymentDetail.setBalance(loanCase.getTotalLoanAmount() - amount);//8.
-                    if(Math.abs(loanCase.getTotalLoanAmount() - amount)<Double.MIN_VALUE)
-                        repaymentDetail.setInterestAmount(contract.getInterestAmount());//9.
-                    List<String> userNames=new ArrayList<>();
-                    StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
-                    StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
-                    if(stepVO!=null){
-                        userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
-                    }
-                    if(stepVO1!=null){
-                        userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
-                    }
-                    repaymentDetail.setUserName(userNames);//11.
-                    repaymentDetail.setRecommenderName(recommenderService.getRecommenderById(loanCase.getRecommenderId()).getRecommenderName());//12.
-                    repaymentDetail.setChannelName(loanCase.getChannelName());//13.
-
-                    repaymentDetails.add(repaymentDetail);
-                }
-
-            }
-        }
-
-        return ResultUtil.success("success", repaymentDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+        return detailService.repaymentReport(caseId, begin, pageSize);
     }
 
     @GetMapping("/repaymentReport/export")
     @ApiOperation("导出回款报表")
     public void exportRepaymentReport(@RequestBody List<RepaymentDetails> repaymentDetails, @RequestParam Integer begin, @RequestParam Integer end, HttpServletResponse response) {
-        //查询概览运营数据,提供给Excel模板文件
-        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "出账明细.xlsx");
-        try {
-            //基于提供好的模板文件创建一个新的Excel表格对象
-            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
-
-            //获得Excel文件中的一个Sheet页
-            XSSFSheet sheet = excel.getSheet("Sheet1");
-            //TODO:row(从0开始)行,cell(从0开始)获取单元格
-            //获得第1行
-            XSSFRow row = sheet.getRow(1);
-            int index=1;
-            //获取单元格
-            for (int i = begin; i < end; i++) {
-                RepaymentDetails repaymentDetail = repaymentDetails.get(i);
-                row = sheet.getRow(index);
-                row.getCell(0).setCellValue(repaymentDetail.getContractNo());
-                row.getCell(1).setCellValue(repaymentDetail.getPawnTicketNo());
-                row.getCell(2).setCellValue(repaymentDetail.getLoanTime());
-                row.getCell(3).setCellValue(repaymentDetail.getCustomerName());
-                row.getCell(4).setCellValue(repaymentDetail.getPawnAmount());
-                row.getCell(5).setCellValue(repaymentDetail.getRepayTime());
-                row.getCell(6).setCellValue(repaymentDetail.getRepayAmount());
-                row.getCell(7).setCellValue(repaymentDetail.getBalance());
-                row.getCell(8).setCellValue(repaymentDetail.getInterestAmount());
-                row.getCell(9).setCellValue(repaymentDetail.getRedeemTicketNo());
-                row.getCell(10).setCellValue(repaymentDetail.getUserName().toString());
-                row.getCell(11).setCellValue(repaymentDetail.getRecommenderName());
-                row.getCell(12).setCellValue(repaymentDetail.getChannelName());
-                row.getCell(13).setCellValue(repaymentDetail.getComment());
-
-                index++;
-            }
-
-            //通过输出流将文件下载到客户端浏览器中
-            ServletOutputStream out = response.getOutputStream();
-            excel.write(out);
-
-            //关闭资源
-            out.flush();
-            out.close();
-            excel.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        detailService.exportRepaymentReport(repaymentDetails, begin, end, response);
     }
 
 

+ 31 - 4
src/main/java/com/loan/system/controller/admin/DictionaryController.java

@@ -2,6 +2,7 @@ package com.loan.system.controller.admin;
 
 import com.loan.system.domain.dto.DictDataDTO;
 import com.loan.system.domain.dto.DictTypeDTO;
+import com.loan.system.domain.dto.query.DictDataQueryDTO;
 import com.loan.system.domain.enums.ExceptionEnum;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.DictionarysVO;
@@ -11,6 +12,7 @@ import com.loan.system.utils.ResultUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 @RestController("AdminDictionaryController")
@@ -22,12 +24,22 @@ public class DictionaryController {
 
     @GetMapping
     @ApiOperation("查询所有字典数据")
-    public Result getDictionarys(){
-        return ResultUtil.success("success",dictionaryService.listDictData());
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getDictionarys(@RequestParam(defaultValue = "1")Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize){
+        return dictionaryService.listDictData(pageNum,pageSize);
+    }
+
+    @PostMapping("/query")
+    @ApiOperation("查询字典数据")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result queryDictionarys(@RequestParam(defaultValue = "1")Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize,
+                                  @RequestBody DictDataQueryDTO query){
+        return dictionaryService.listDictDataByQuery(pageNum,pageSize,query);
     }
 
     @PostMapping
     @ApiOperation("添加字典数据")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result addDictionary(@RequestBody DictDataDTO dataDTO){
         if (dataDTO==null || dataDTO.getDictLabel()==null || dataDTO.getDictValue()==null || dataDTO.getDictType()==null)
             throw  new DescribeException(ExceptionEnum.INPUT_ERROR);
@@ -37,6 +49,7 @@ public class DictionaryController {
 
     @PutMapping("/{id}")
     @ApiOperation("修改字典数据")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result updateDictionary(@PathVariable Long id,@RequestBody DictDataDTO dataDTO){
         dictionaryService.updateDictData(dataDTO,id);
         return ResultUtil.success("success");
@@ -44,12 +57,14 @@ public class DictionaryController {
 
     @GetMapping("/types")
     @ApiOperation("查询所有字典类型")
-    public Result getAllTypes(){
-        return ResultUtil.success("success",dictionaryService.listDictType());
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getAllTypes(@RequestParam(defaultValue = "1")Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize){
+        return dictionaryService.listDictType(pageNum,pageSize);
     }
 
     @PutMapping("/types/{id}")
     @ApiOperation("修改字典类型")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
     public Result updateType(@PathVariable Long id, @RequestBody DictTypeDTO dictTypeDTO){
         dictionaryService.updateDictType(dictTypeDTO,id);
         return ResultUtil.success("success");
@@ -57,6 +72,7 @@ public class DictionaryController {
 
     @PostMapping("/types")
     @ApiOperation("添加字典类型")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
     public Result addType(@RequestBody DictTypeDTO dictTypeDTO){
         if (dictTypeDTO==null || dictTypeDTO.getDictName()==null || dictTypeDTO.getDictType()==null)
             throw  new DescribeException(ExceptionEnum.INPUT_ERROR);
@@ -64,5 +80,16 @@ public class DictionaryController {
         return ResultUtil.success("success");
     }
 
+    @GetMapping("/data")
+    @ApiOperation("查询所有字典数据")
+    public Result getDictionarys(){
+        return ResultUtil.success("success",dictionaryService.listDictData());
+    }
+    @GetMapping("/data/types")
+    @ApiOperation("查询所有字典类型")
+    public Result getAllTypes(){
+        return ResultUtil.success("success",dictionaryService.listDictType());
+    }
+
 
 }

+ 52 - 0
src/main/java/com/loan/system/controller/admin/LoanCaseController.java

@@ -0,0 +1,52 @@
+package com.loan.system.controller.admin;
+
+import com.loan.system.domain.dto.query.LoanCaseQueryDTO;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.service.LoanService;
+import com.loan.system.utils.ResultUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+
+@RestController
+@RequestMapping("/admin/case")
+@Api(tags = "业务管理")
+public class LoanCaseController {
+    @Autowired
+    private LoanService loanCaseService;
+
+    @GetMapping
+    @ApiOperation("显示所有业务")//pc
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findLoanCaseAll(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "20") Integer pageSize, @RequestParam(required = false) String isComplete) {
+        return loanCaseService.listLoanCaseInfo(pageNum, pageSize, isComplete);
+    }
+    
+    @PostMapping("/query")
+    @ApiOperation("按条件查询业务信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findLoanCasesByQuery(@RequestBody LoanCaseQueryDTO queryDTO,
+                                      @RequestParam(defaultValue = "1") Integer pageNum,
+                                      @RequestParam(defaultValue = "20") Integer pageSize) {
+        return loanCaseService.findLoanCasesByQuery(queryDTO, pageNum, pageSize);
+    }
+
+    @PutMapping("/delete/{id}")
+    @ApiOperation("逻辑删除业务信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
+    private Result deleteLoanCase(@PathVariable Long id) {
+        loanCaseService.logic_delete(id);
+        return ResultUtil.success("删除成功");
+    }
+
+    @GetMapping("/file/{id}")
+    @ApiOperation("显示文件详细信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result findLoanCaseById(@PathVariable Long id) {
+        return loanCaseService.findLoanCaseAndFileDetail(id);
+    }
+
+}

+ 54 - 6
src/main/java/com/loan/system/controller/admin/MaterialsController.java

@@ -1,17 +1,26 @@
 package com.loan.system.controller.admin;
 
+import com.loan.system.domain.dto.BatchDownloadDTO;
+import com.loan.system.domain.dto.query.DocumentQueryDTO;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.service.DocumentService;
 import com.loan.system.utils.ResultUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.util.List;
 
-@RestController
 @RequestMapping("/admin/materials")
+@RestController
 @Api(tags = "资料归档管理")
 public class MaterialsController {
     @Autowired
@@ -19,7 +28,46 @@ public class MaterialsController {
 
     @GetMapping
     @ApiOperation("所有附件信息")
-    private Result getAllFiles(){
-        return ResultUtil.success("success",documentService.findAll());
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result getAllFiles(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize){
+        return documentService.findAll(pageNum, pageSize);
     }
+
+    @PostMapping("/query")
+    @ApiOperation("查询附件信息")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public Result queryFiles(@RequestParam(defaultValue = "1") Integer pageNum,
+                             @RequestParam(defaultValue = "10") Integer pageSize,
+                             @RequestBody DocumentQueryDTO documentQueryDTO){
+
+        return documentService.queryFiles(pageNum, pageSize, documentQueryDTO);
+    }
+
+    @PutMapping("/deleteBatch")
+    @ApiOperation("OSS文件删除")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER', 'BACK_OFFICE')")
+    public Result deleteFileFromOss(@RequestParam List<Long> ids) {
+        // 仅逻辑删除数据库即可
+        documentService.deleteFileByIds( ids);
+        return ResultUtil.success("文件删除成功");
+    }
+
+    /**
+     * 批量下载OSS文件 - 将多个文件打包成zip下载
+     */
+    @PostMapping("/batchDownload")
+    @ApiOperation("OSS批量文件下载")
+    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES', 'FINANCE', 'BACK_OFFICE')")
+    public void batchDownloadFilesFromOss(@RequestBody BatchDownloadDTO batchDownloadDTO,
+                                          HttpServletResponse response) throws IOException {
+        documentService.batchDownloadFilesFromOss(batchDownloadDTO, response);
+    }
+
+    /** 从OSS下载文件 */
+    @GetMapping("/download/{caseId}/{fileType}/{filename:.+}")
+    @ApiOperation("获取OSS文件")
+    public void getFile(@PathVariable("caseId")Long caseId, @PathVariable("fileType") String fileType,@PathVariable("filename") String filename, HttpServletResponse response) {
+        documentService.downloadFileFromOss(caseId, fileType,filename, response);
+    }
+
 }

+ 8 - 1
src/main/java/com/loan/system/controller/admin/RecommenderController.java

@@ -1,6 +1,7 @@
 package com.loan.system.controller.admin;
 
 import com.loan.system.domain.dto.BizRecommenderDTO;
+import com.loan.system.domain.dto.query.RecommenderQueryDTO;
 import com.loan.system.domain.entity.BizRecommender;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.service.RecommenderService;
@@ -26,7 +27,13 @@ public class RecommenderController {
     @GetMapping
     @ApiOperation("查询所有推荐人")
     public Result getRecommenders(Integer pageNum, Integer pageSize){
-        return ResultUtil.success("success",recommenderService.getRecommenders(pageNum, pageSize));
+        return recommenderService.getRecommenders(pageNum, pageSize);
+    }
+
+    @PostMapping("/query")
+    @ApiOperation("按关键字查询推荐人")
+    public Result findByKey(@RequestBody RecommenderQueryDTO  recommenderQueryDTO,@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10")Integer pageSize){
+        return recommenderService.getRecommendersByKey(recommenderQueryDTO, pageNum, pageSize);
     }
     @GetMapping("/group")
     @ApiOperation("按组别查询所有推荐人")

+ 19 - 168
src/main/java/com/loan/system/controller/wechat/ApprovalController.java

@@ -44,8 +44,6 @@ public class ApprovalController {
     private ApprovalService approvalService;
     @Autowired
     private StepService stepService;
-    @Autowired
-   private UserService userService;
 
     @GetMapping("preApproval/detail")
     @ApiOperation("获取预审审详情")
@@ -66,7 +64,8 @@ public class ApprovalController {
 
         Long userId = BaseContext.getCurrentId();
         Long caseId = preApprovalDTO.getCaseId();
-        if (!loanCaseService.existsByIdAndIsDelete(caseId)) {
+        LoanCaseSimpleVO loanCase = loanCaseService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCase == null) {
             throw new DescribeException(PROJECT_NOT_EXIST);
         }
 
@@ -79,7 +78,7 @@ public class ApprovalController {
         if ((preStep.getUserId1() != null && preStep.getUserId1().equals(userId)) || (step.getUserId1() != null && userId != step.getUserId1()))
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
 
-        approvalService.preApprovalSavePrimary(userId, caseId, preApprovalDTO);
+        approvalService.preApprovalSavePrimary(userId, loanCase, preApprovalDTO,step);
 
         return ResultUtil.success("success", "预审通过");
     }
@@ -103,11 +102,12 @@ public class ApprovalController {
         if ((preStep.getUserId1() != null && preStep.getUserId1().equals(userId)) || (step.getUserId1() != null && userId != step.getUserId1()))
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
 
-        if (!loanCaseService.existsByIdAndIsDelete(caseId)) {
+        LoanCaseSimpleVO loanCase = loanCaseService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCase == null) {
             throw new DescribeException(PROJECT_NOT_EXIST);
         }
 
-        approvalService.preApprovalReject(caseId, userId, preApprovalDTO);
+        approvalService.preApprovalReject(loanCase, userId, preApprovalDTO);
 
         return ResultUtil.success("success", "预审拒绝");
     }
@@ -126,9 +126,9 @@ public class ApprovalController {
     @PreAuthorize("@pms.hasRole('APPROVER')")
     @ApiOperation("业务审批通过")
     public Result approvalPass1(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL.getCode());
+        LoanCaseSimpleVO loanCaseSimpleVO = validateApprovalDTO(approvalDTO, StepPropertyEnum.APPROVAL.getCode());
 
-        approvalService.approvalPass1(approvalDTO);
+        approvalService.approvalPass1(loanCaseSimpleVO, approvalDTO);
 
         return ResultUtil.success("success", "审批通过");
 
@@ -138,9 +138,9 @@ public class ApprovalController {
     @PreAuthorize("@pms.hasRole('APPROVER')")
     @ApiOperation("业务审批拒绝")
     public Result approvalReject1(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL.getCode());
+        LoanCaseSimpleVO loanCaseSimpleVO = validateApprovalDTO(approvalDTO, StepPropertyEnum.APPROVAL.getCode());
 
-        approvalService.approvalReject1( approvalDTO);
+        approvalService.approvalReject1( loanCaseSimpleVO,approvalDTO);
 
         return ResultUtil.success("success", "审批驳回");
     }
@@ -149,9 +149,9 @@ public class ApprovalController {
     @PreAuthorize("@pms.hasRole('APPROVER')")
     @ApiOperation("业务审批通过")
     public Result approvalPass2(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL_2.getCode());
+        LoanCaseSimpleVO loanCaseSimpleVO = validateApprovalDTO(approvalDTO, StepPropertyEnum.APPROVAL_2.getCode());
 
-        approvalService.approvalPass2( approvalDTO);
+        approvalService.approvalPass2(loanCaseSimpleVO, approvalDTO);
 
         return ResultUtil.success("success", "审批通过");
 
@@ -161,54 +161,22 @@ public class ApprovalController {
     @PreAuthorize("@pms.hasRole('APPROVER')")
     @ApiOperation("业务审批拒绝")
     public Result approvalReject2(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL_2.getCode());
+        LoanCaseSimpleVO loanCaseSimpleVO = validateApprovalDTO(approvalDTO, StepPropertyEnum.APPROVAL_2.getCode());
 
-        approvalService.approvalReject2(approvalDTO);
+        approvalService.approvalReject2(loanCaseSimpleVO, approvalDTO);
 
         return ResultUtil.success("success", "审批驳回");
     }
 
-    @PostMapping("/approval1/terminate")
-    @PreAuthorize("@pms.hasRole('APPROVER')")
-    @ApiOperation("业务审批终结")
-    public Result approvalEnd(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL.getCode());
-
-        Long caseId = approvalDTO.getCaseId();
-        approvalService.addApprovalRecord(caseId, StepPropertyEnum.APPROVAL.getCode(), DecisionEnum.TERMINATE.getMsg(), approvalDTO.getComments());
-
-        //项目终结
-        loanCaseService.updateIsCompleteByCaseId(DecisionEnum.TERMINATE.getMsg(), caseId);
 
-        //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
-
-        return ResultUtil.success("success", "审批终结");
-    }
-
-    @PostMapping("/approval2/terminate")
-    @PreAuthorize("@pms.hasRole('APPROVER')")
-    @ApiOperation("业务审批终结")
-    public Result approvalEnd2(@RequestBody ApprovalDTO approvalDTO) {
-        validateApprovalDTO(approvalDTO,StepPropertyEnum.APPROVAL_2.getCode());
-
-        Long caseId = approvalDTO.getCaseId();
-        approvalService.addApprovalRecord(caseId, StepPropertyEnum.APPROVAL_2.getCode(), DecisionEnum.TERMINATE.getMsg(), approvalDTO.getComments());
-
-        //项目终结
-        loanCaseService.updateIsCompleteByCaseId(DecisionEnum.TERMINATE.getMsg(), caseId);
-
-        //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
-
-        return ResultUtil.success("success", "审批终结");
-    }
-
-    private void validateApprovalDTO(ApprovalDTO approvalDTO,Integer stepCode) {
+    private LoanCaseSimpleVO validateApprovalDTO(ApprovalDTO approvalDTO,Integer stepCode) {
         if (ObjectUtils.isEmpty(approvalDTO) || approvalDTO.getCaseId() == null)
             throw new DescribeException(INPUT_ERROR);
 
         Long userId = BaseContext.getCurrentId();
         Long caseId = approvalDTO.getCaseId();
-        if (!loanCaseService.existsByIdAndIsDelete(caseId)) {
+        LoanCaseSimpleVO loanCase = loanCaseService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCase == null) {
             throw new DescribeException(PROJECT_NOT_EXIST);
         }
 
@@ -225,126 +193,9 @@ public class ApprovalController {
         if (step.getUserId1() != null && userId != step.getUserId1())
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
 
+        return loanCase;
+
     }
 
-//    @PostMapping("/approval/pass")
-//    @PreAuthorize("@pms.hasRole('APPROVER')")
-//    @ApiOperation("业务审批通过")
-//    public Result approval_pass(@RequestBody ApprovalDTO approvalDTO) {
-//        if(ObjectUtils.isEmpty(approvalDTO)||approvalDTO.getCaseId() == null)
-//            throw new DescribeException(INPUT_ERROR);
-//
-//        Long userId= BaseContext.getCurrentId();
-//        Long caseId = approvalDTO.getCaseId();
-//        //审批业务逻辑
-//        LoanCase loanCase = loanCaseService.findLoanCaseByIdAndIsDelete(caseId, false);
-//        StepVO step = stepService.findByStepCodeAndCaseId(StepPropertyEnum.APPROVAL.getCode(),caseId);
-//        //判断过去处理人与目前处理人是否一致
-//        if(ObjectUtils.isEmpty(step)||!step.getStatus().equals(StepEnum.PROCESS.getMsg()))
-//            throw new DescribeException(STEP_HAS_NOT_PROCESS);
-//
-//        if(step.getUserId1()!=null&&step.getUserId2()!=null&&userId != step.getUserId2()&&userId!=step.getUserId1())
-//            throw new DescribeException(STEP_USER_NOT_EXPECTED);
-//
-//        if(loanCase == null || loanCase.getIsDelete()){
-//            throw  new DescribeException(PROJECT_NOT_EXIST);
-//        }
-//
-//        List<ApprovalRecordVO> records = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), userId);
-//        ApprovalRecordVO record = ObjectUtils.isEmpty(records)?null:records.get(records.size()-1);//获取当前审批人上次的记录
-//        if(step.getUserId1()== null){
-//            stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.APPROVAL.getCode(),userId,caseId);
-//        }else if(step.getUserId2()== null ){
-//            //如果用户1审批过且通过,无法重复审批
-//            if(step.getUserId1() == userId && record!=null && record.getDecision().equals(DecisionEnum.PASS.getMsg()))
-//                throw new DescribeException(APPROVAL_USER_IS_COMPLETED);
-//            else if(step.getUserId1()!= userId)
-//                stepService.updateUserId2ByCaseIdAndStepCode(StepPropertyEnum.APPROVAL.getCode(),userId,caseId);
-//        }else {
-//            List<ApprovalRecordVO> approvalRecords1 = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), step.getUserId1());
-//            ApprovalRecordVO approvalRecord1 = approvalRecords1.get(approvalRecords1.size()-1);
-//            List<ApprovalRecordVO> approvalRecords2 = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), step.getUserId2());
-//            ApprovalRecordVO approvalRecord2 = approvalRecords2.get(approvalRecords2.size()-1);
-//            if(step.getUserId1()== userId){//仅版本一样或版本小于可新增
-//                if(approvalRecord1.getVersion()> approvalRecord2.getVersion() && approvalRecord1.getDecision().equals(DecisionEnum.PASS.getMsg()))
-//                    throw new DescribeException(APPROVAL_USER_IS_COMPLETED);
-//            }else{
-//                if(approvalRecord1.getVersion()< approvalRecord2.getVersion() && approvalRecord2.getDecision().equals(DecisionEnum.PASS.getMsg()))
-//                    throw new DescribeException(APPROVAL_USER_IS_COMPLETED);
-//            }
-//        }
-//
-//        approvalService.addApprovalRecord(caseId,StepPropertyEnum.APPROVAL.getCode(),DecisionEnum.PASS.getMsg(),approvalDTO.getComments());
-//
-//        step=stepService.findByStepCodeAndCaseId(StepPropertyEnum.APPROVAL.getCode(), caseId);
-//        if(step.getUserId1()!=null&&step.getUserId2()!=null){
-//            List<ApprovalRecordVO> records1 = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), step.getUserId1());
-//            ApprovalRecordVO record1 = records1.get(records1.size()-1);//获取当前审批人上次的记录
-//            List<ApprovalRecordVO> records2 = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), step.getUserId2());
-//            ApprovalRecordVO record2 = records2.get(records2.size()-1);//获取当前审批人上次的记录
-//
-//            //TODO:同一阶段双人审批通过,才结束
-//            if(record1.getVersion()==record2.getVersion() && record1.getDecision().equals(DecisionEnum.PASS.getMsg()) && record2.getDecision().equals(DecisionEnum.PASS.getMsg())){
-//                stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(),StepPropertyEnum.APPROVAL_PARENT.getCode(),caseId);
-//                stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(),StepPropertyEnum.APPROVAL.getCode(),caseId);
-//
-//                stepService.tryStartStep(StepPropertyEnum.APPROVAL.getCode(), caseId);
-//                //TODO微信推送审批通过消息和通知下一环节
-//            }
-//        }else{
-//            //TODO微信推送另一个审批人审批
-//        }
-//
-//        return ResultUtil.success("success","审批通过");
-//
-//    }
-//
-//    @PostMapping("/approval/reject")
-//    @PreAuthorize("@pms.hasRole('APPROVER')")
-//    @ApiOperation("业务审批拒绝")
-//    public Result approval_reject(@RequestBody ApprovalDTO approvalDTO) {
-//        if(ObjectUtils.isEmpty(approvalDTO)||approvalDTO.getCaseId() == null)
-//            throw new DescribeException(INPUT_ERROR);
-//        Long userId= BaseContext.getCurrentId();
-//        Long caseId = approvalDTO.getCaseId();
-//        //审批业务逻辑
-//        LoanCase loanCase = loanCaseService.findLoanCaseByIdAndIsDelete(approvalDTO.getCaseId(),false);
-//        if(loanCase == null||loanCase.getIsDelete()){
-//            return ResultUtil.error(PROJECT_NOT_EXIST.getCode(), PROJECT_NOT_EXIST.getMsg());
-//        }
-//        StepVO step = stepService.findByStepCodeAndCaseId(StepPropertyEnum.APPROVAL.getCode(), approvalDTO.getCaseId());
-//        if(ObjectUtils.isEmpty(step)||!step.getStatus().equals(StepEnum.PROCESS.getMsg()))
-//            throw new DescribeException(STEP_HAS_NOT_PROCESS);
-//
-//        //判断过去处理人与目前处理人是否一致
-//        if(step.getUserId1()!=null&&step.getUserId2()!=null&&userId!=step.getUserId2()&&userId!=step.getUserId1())
-//            throw new DescribeException(STEP_USER_NOT_EXPECTED);
-//
-//        List<ApprovalRecordVO> records = approvalService.findByCaseIdAndStepCodeAndApproverIdAndIsDelete(caseId, StepPropertyEnum.APPROVAL.getCode(), userId);
-//        ApprovalRecordVO record = ObjectUtils.isEmpty(records)?null:records.get(records.size()-1);//获取当前审批人上次的记录
-//        if(step.getUserId1()== null){
-//            stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.APPROVAL.getCode(),userId,caseId);
-//        }else if(step.getUserId2()== null ){
-//            //如果用户1审批过且通过,无法重复审批
-//            if(step.getUserId1() == userId && record!=null && record.getDecision().equals(DecisionEnum.PASS.getMsg()))
-//                throw new DescribeException(APPROVAL_USER_IS_COMPLETED);
-//            else if(step.getUserId1()!= userId)
-//                stepService.updateUserId2ByCaseIdAndStepCode(StepPropertyEnum.APPROVAL.getCode(),userId,caseId);
-//        }
-//        approvalService.addApprovalRecord(caseId,StepPropertyEnum.APPROVAL.getCode(),DecisionEnum.REJECT.getMsg(),approvalDTO.getComments());
-//        RedisData redisData = new RedisData(stringRedisTemplate);
-//        redisData.setRejectApprovalRecord(caseId,StepPropertyEnum.BUSINESS_ACCEPT.getCode(),approvalDTO.getComments());
-//
-//        //更新环节状态
-//        stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(),StepPropertyEnum.BUSINESS_ACCEPT_PARENT.getCode(),caseId);
-//        stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(),StepPropertyEnum.BUSINESS_ACCEPT.getCode(),caseId);
-//        stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.PRE_TRIAL_PARENT.getCode(),caseId);
-//        stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.PRE_TRIAL.getCode(),caseId);
-//        stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.APPROVAL_PARENT.getCode(),caseId);
-//        stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.APPROVAL.getCode(),caseId);
-//        //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
-//
-//        return ResultUtil.success("success","审批驳回");
-//    }
 }
 

+ 9 - 6
src/main/java/com/loan/system/controller/wechat/CollateralController.java

@@ -78,7 +78,8 @@ public class CollateralController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = collateralPlanDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PLAN_SUBMISSION.getCode(), caseId);
@@ -97,7 +98,7 @@ public class CollateralController {
         if (!info.isEmpty())
             throw new DescribeException(COLLATERAL_NOT_EXIST.getCode(),COLLATERAL_NOT_EXIST.getMsg()+ "{"+info+"}");
 
-        collateralPlanService.createCollateralPlan(collateralPlanDTO,planId,isComplete);
+        collateralPlanService.createCollateralPlan(loanCaseSimpleVO,collateralPlanDTO,planId,isComplete);
 
         return ResultUtil.success( "计划上报成功");
     }
@@ -118,12 +119,13 @@ public class CollateralController {
         }
 
         Long caseId = collateralPlanApprovalDTO.getCaseId();
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
         Integer stepCode = collateralPlan.getFlag() .equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.APPROVAL_ASSIGNMENT.getCode() : StepPropertyEnum.APPROVAL_ASSIGNMENT_2.getCode();
         StepVO stepVO = stepService.findByStepCodeAndCaseId(stepCode, caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        return collateralPlanService.approvalCollateralPlan(collateralPlan,collateralPlanApprovalDTO,recordId);
+        return collateralPlanService.approvalCollateralPlan(loanCaseSimpleVO,collateralPlan,collateralPlanApprovalDTO,recordId);
 
     }
 
@@ -149,8 +151,8 @@ public class CollateralController {
         if(collateralPlan.getOperatorId()!= BaseContext.getCurrentId())
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
 
-
-        collateralPlanService.warehouseCollateral(collateralPlan, comments);
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(collateralPlan.getCaseId(), false);
+        collateralPlanService.warehouseCollateral(loanCaseSimpleVO,collateralPlan, comments);
 
         return ResultUtil.success("success","抵押物入库成功");
     }
@@ -176,7 +178,8 @@ public class CollateralController {
         if(collateralPlan.getOperatorId()!= BaseContext.getCurrentId())
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
 
-        collateralPlanService.outboundCollateral(collateralPlan, comments);
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(collateralPlan.getCaseId(), false);
+        collateralPlanService.outboundCollateral(loanCaseSimpleVO,collateralPlan, comments);
 
         return ResultUtil.success("success","抵押物出库成功");
     }

+ 5 - 4
src/main/java/com/loan/system/controller/wechat/ContractController.java

@@ -68,7 +68,7 @@ public class ContractController {
         if(ObjectUtils.isEmpty(contractById))
             throw new DescribeException(ExceptionEnum.CONTRACT_NOT_EXIST);
 
-        contractService.getContractInformation(response,caseId,BeanUtil.copyProperties(contractById,ContractVO.class));
+        contractService.getContractInformation(response,caseId,contractId);
 
     }
 
@@ -134,7 +134,7 @@ public class ContractController {
         if (!contractById.getIsPush())
             throw new DescribeException(ExceptionEnum.CONTRACT_NOT_PUSH);
 
-        contractService.getContractInformation(response,caseId,BeanUtil.copyProperties(contractById,ContractVO.class));
+        contractService.getContractInformation(response,caseId,contractId);
     }
 
     //签署的电子信息先以附件上传
@@ -188,7 +188,8 @@ public class ContractController {
     @ApiOperation("合同签订完成")
     @PreAuthorize("@pms.hasAnyRoles('LEAD_SALES', 'ASSIST_SALES')")
     public Result completeContract(@PathVariable("caseId")Long caseId, @RequestBody ContractWrapperDTO contractWrapper){
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         if(ObjectUtils.isEmpty(contractWrapper) || ObjectUtils.isEmpty(contractWrapper.getContractDTOS()))
@@ -203,7 +204,7 @@ public class ContractController {
             throw new DescribeException(STEP_USER_NOT_EXPECTED);
         }
 
-        contractService.completeContract(caseId,contractWrapper);
+        contractService.completeContract(loanCaseSimpleVO,contractWrapper);
 
         return ResultUtil.success("success");
     }

+ 1 - 2
src/main/java/com/loan/system/controller/wechat/CustomerController.java

@@ -1,7 +1,6 @@
 package com.loan.system.controller.wechat;
 
 import com.loan.system.domain.dto.CustomerDTO;
-import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.service.CustomerService;
 import com.loan.system.utils.ResultUtil;
@@ -11,7 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
-@RestController("AdminCustomerController")
+@RestController
 @RequestMapping("/wechat/customers")
 @Api(tags = "微信客户接口")
 public class CustomerController {

+ 35 - 51
src/main/java/com/loan/system/controller/wechat/DisbursementController.java

@@ -55,14 +55,15 @@ public class DisbursementController {
         if(ObjectUtils.isEmpty(disbursementDTO)||disbursementDTO.getCaseId()==null)
             throw new DescribeException(INPUT_ERROR);
 
-        if(!loanService.existsByIdAndIsDelete(disbursementDTO.getCaseId()))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(disbursementDTO.getCaseId(), false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PLAN_REPORT.getCode(),disbursementDTO.getCaseId());
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.addDisbursementPlan(disbursementDTO);
+        disbursementService.addDisbursementPlan(loanCaseSimpleVO,disbursementDTO);
 
         return ResultUtil.success("success");
     }
@@ -77,7 +78,8 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PLAN_AUDIT.getCode(),caseId);
@@ -91,7 +93,7 @@ public class DisbursementController {
         if (assistantId != null && !userService.existsByIdAndIsDelete(assistantId))
             throw new DescribeException(ASSISTANT__NOT_EXIST);
 
-        disbursementService.disbursementPlanApproval(approvalRecordDTO,chargeId,assistantId);
+        disbursementService.disbursementPlanApproval(loanCaseSimpleVO,approvalRecordDTO,chargeId,assistantId);
 
         return ResultUtil.success("success");
     }
@@ -104,14 +106,15 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PLAN_AUDIT.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.disbursementPlanApprovalReject(approvalRecordDTO);
+        disbursementService.disbursementPlanApprovalReject(loanCaseSimpleVO,approvalRecordDTO);
 
         return ResultUtil.success("success");
     }
@@ -123,31 +126,28 @@ public class DisbursementController {
         if (ObjectUtils.isEmpty(disbursementStartDTO)||ObjectUtils.isEmpty(disbursementStartDTO.getDisbursementRecordDTO())||
         disbursementStartDTO.getDisbursementRecordDTO().getCaseId()== null)
             throw new DescribeException(INPUT_ERROR);
+
         Long caseId = disbursementStartDTO.getDisbursementRecordDTO().getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.DISBURSE_START.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        if (stepVO.getUserIds() != null){
-            boolean flag = false;//是否存在
-            String[] userIds = stepVO.getUserIds().split(",");//分主办与辅办,但仅需任意一人操作即可
-            for (String userId : userIds){
-                Long currentId = Long.valueOf(userId);
-                if(BaseContext.getCurrentId().equals(currentId)){
-                    flag = true;
-                    break;
-                }
-            }
-            if(!flag)
-                //全部遍历结束未break,表示不是预期用户
-                throw new DescribeException(STEP_USER_NOT_EXPECTED);
-        }
-
-        disbursementService.commitDisbursement(disbursementStartDTO,isComplete);
+        disbursementService.commitDisbursement(loanCaseSimpleVO,disbursementStartDTO,isComplete);
+
+        return ResultUtil.success("success");
+    }
 
+    @PostMapping("/completeDisburse")
+    @ApiOperation(value = "手动完成出款")
+    @PreAuthorize("@pms.hasAnyRoles('ASSIST_SALES','LEAD_SALES')")
+    public Result completeDisburse(@RequestParam Long caseId) {
+        if (caseId == null || !loanService.existsByIdAndIsDelete(caseId))
+            return ResultUtil.error(PROJECT_NOT_EXIST);
+        disbursementService.completeDisburse(caseId);
         return ResultUtil.success("success");
     }
 
@@ -159,14 +159,15 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.DISBURSE_AUDIT.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.disbursementApproval(approvalRecordDTO,DecisionEnum.PASS.getMsg());
+        disbursementService.disbursementApproval(loanCaseSimpleVO,approvalRecordDTO,DecisionEnum.PASS.getMsg());
 
         return ResultUtil.success("success");
     }
@@ -179,38 +180,19 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.DISBURSE_AUDIT.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.disbursementApproval(approvalRecordDTO,DecisionEnum.REJECT.getMsg());
+        disbursementService.disbursementApproval(loanCaseSimpleVO,approvalRecordDTO,DecisionEnum.REJECT.getMsg());
 
         return ResultUtil.success("success");
     }
 
-//    @PostMapping("/amount")
-//    @ApiOperation(value = "财务出款")
-//    @PreAuthorize("@pms.hasRole('FINANCE')")//TODO:多次出款,负责人可能不一样
-//    public Result financeDisbursement(@RequestBody DisbursementRecordListWrapper disbursementRecordListWrapper, @RequestParam Long caseId, @RequestParam Double currentAmount) {
-//        List<DisbursementRecordDTO> disbursementRecordDTOs = disbursementRecordListWrapper.getDisbursementRecordDTOs();
-//        if (ObjectUtils.isEmpty(disbursementRecordDTOs)||disbursementRecordDTOs.get(0).getDisbursementId() == null)
-//            throw new DescribeException(INPUT_ERROR);
-//
-//        if(!loanService.existsByIdAndIsDelete(caseId))
-//            throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
-//
-//        StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.FINANCE_DISBURSE.getCode(),caseId);
-//        if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
-//            throw new DescribeException(STEP_HAS_NOT_PROCESS);
-//
-//        disbursementService.financeDisbursement(disbursementRecordDTOs,caseId,currentAmount);
-//
-//        return ResultUtil.success("success");
-//    }
-
     @PostMapping("/amount/pass")
     @ApiOperation(value = "财务复核通过")
     @PreAuthorize("@pms.hasRole('FINANCE')")//TODO:多次出款,负责人可能不一样
@@ -219,14 +201,15 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.FINANCE_DISBURSE.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.financeApproval(approvalRecordDTO,DecisionEnum.PASS.getMsg());
+        disbursementService.financeApproval(loanCaseSimpleVO,approvalRecordDTO,DecisionEnum.PASS.getMsg());
 
         return ResultUtil.success("success");
     }
@@ -239,14 +222,15 @@ public class DisbursementController {
             throw new DescribeException(INPUT_ERROR);
 
         Long caseId = approvalRecordDTO.getCaseId();
-        if(!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if(loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.FINANCE_DISBURSE.getCode(),caseId);
         if(ObjectUtils.isEmpty(stepVO)||!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        disbursementService.financeApproval(approvalRecordDTO,DecisionEnum.REJECT.getMsg());
+        disbursementService.financeApproval(loanCaseSimpleVO,approvalRecordDTO,DecisionEnum.REJECT.getMsg());
 
         return ResultUtil.success("success");
     }

+ 36 - 15
src/main/java/com/loan/system/controller/wechat/LoanController.java

@@ -48,8 +48,8 @@ public class LoanController {
     }
 
     @GetMapping("/customer")
-    @ApiOperation("显示客户的所有业务")//x
-    @PreAuthorize("@pms.hasAnyRoles('EXTERNAL')")
+    @ApiOperation("显示客户的所有业务")
+    @PreAuthorize("@pms.hasAnyRoles('CUSTOMER')")
     public Result findLoanCaseByCustomerId(@RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "20") Integer pageSize) {
         List<LoanCaseVO> loanCases = loanService.findLoanCaseByCustomerId(BaseContext.getCurrentId(), pageNum, pageSize, false);
         return ResultUtil.success("success", loanCases);
@@ -76,10 +76,10 @@ public class LoanController {
     @GetMapping("/stepCode/dealings")
     @ApiOperation("按环节名称查询业务")
     @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','LEAD_SALES','ASSIST_SALES','APPROVER','FINANCE','BACK_OFFICE','EXTERNAL')")
-    public Result findLoanCaseByStepCodeAndIsComplete(@RequestParam Integer stepCode) {
+    public Result findLoanCaseByStepCodeAndIsComplete(@RequestParam Integer stepCode, @RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "20") Integer pageSize) {
         if (stepCode == null)
             throw new DescribeException(INPUT_ERROR);
-        return ResultUtil.success("success", loanService.listLoanCaseByStepCode(stepCode));
+        return ResultUtil.success("success", loanService.listLoanCaseByStepCode(stepCode,pageNum,pageSize));
     }
 
     @GetMapping("/{role}/dealings")
@@ -183,7 +183,7 @@ public class LoanController {
 
     @GetMapping("/{id}/details")
     @ApiOperation("显示业务详情")
-    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES','FINANCE','BACK_OFFICE','EXTERNAL')")
+//    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','LEAD_SALES', 'ASSIST_SALES','FINANCE','BACK_OFFICE','EXTERNAL')")
     public Result findLoanCaseDetails(@PathVariable("id") Long caseId) {
         return ResultUtil.success("success", loanService.findLoanCaseDetailsById(caseId));
     }
@@ -245,26 +245,47 @@ public class LoanController {
         if ((!ObjectUtils.isEmpty(step1)) && step1.getStatus().equals(StepEnum.COMPLETED.getMsg()))
             throw new DescribeException(PRE_TRAIL_HAS_COMPLETE);
 
-
         loanService.cancelLoanCase(caseId);
 
         return ResultUtil.success("success");
     }
 
+    @PostMapping("/terminate")
+    @PreAuthorize("@pms.hasAnyRoles('APPROVER','LEAD_SALES', 'ASSIST_SALES')")
+    @ApiOperation("业务终结")
+    public Result approvalEnd(@RequestParam Long caseId,@RequestParam Integer stepCode) {
+        Long userId = BaseContext.getCurrentId();
+        if (caseId == null || !loanService.existsByIdAndIsDelete(caseId)) {
+            throw new DescribeException(PROJECT_NOT_EXIST);
+        }
+
+        StepVO step = stepService.findByStepCodeAndCaseId(stepCode, caseId);
+        //判断过去处理人与目前处理人是否一致
+        if (step.getUserId1() != null && userId != step.getUserId1())
+            throw new DescribeException(STEP_USER_NOT_EXPECTED);
+
+        //项目终结
+        loanService.updateIsCompleteByCaseId(DecisionEnum.COMPLETE.getMsg(), stepCode,caseId);
+
+        //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
+
+        return ResultUtil.success("success", "审批终结");
+    }
+
 
     @PutMapping("/{id}/complete")
     @ApiOperation("完成业务")//x
     @PreAuthorize("@pms.hasAnyRoles('LEAD_SALES', 'ASSIST_SALES')")
     public Result completeLoanCase(@PathVariable("id") Long caseId) {
-        if (!loanService.existsByIdAndIsDelete(caseId))
-            throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
-
-        List<StepVO> steps = stepService.getStepByCaseId(caseId);
-        for (StepVO step : steps) {
-            if (!step.getStatus().equals(StepEnum.COMPLETED.getMsg()))
-                throw new DescribeException(PROJECT_HAS_NOT_COMPLETED);
-        }
-        loanService.updateIsCompleteByCaseId(StepEnum.COMPLETED.getMsg(), caseId);
+//        if (!loanService.existsByIdAndIsDelete(caseId))
+//            throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
+//
+//        List<StepVO> steps = stepService.getStepByCaseId(caseId);
+//        for (StepVO step : steps) {
+//            if (!step.getStatus().equals(StepEnum.COMPLETED.getMsg()))
+//                throw new DescribeException(PROJECT_HAS_NOT_COMPLETED);
+//        }
+//        loanService.updateIsCompleteByCaseId(StepEnum.COMPLETED.getMsg(), caseId);
         return ResultUtil.success("success");
     }
 

+ 5 - 2
src/main/java/com/loan/system/controller/wechat/MessageController.java

@@ -3,11 +3,13 @@ package com.loan.system.controller.wechat;
 import com.loan.system.context.BaseContext;
 import com.loan.system.domain.entity.User;
 import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.pojo.TemplateMessage;
 import com.loan.system.domain.vo.SysMessageVO;
 import com.loan.system.domain.vo.UserVO;
 import com.loan.system.service.CustomerService;
 import com.loan.system.service.MessageService;
 import com.loan.system.service.UserService;
+import com.loan.system.service.WxService;
 import com.loan.system.utils.ResultUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -16,8 +18,7 @@ import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
 
 @RestController
 @RequestMapping("/wechat/message")
@@ -29,6 +30,8 @@ public class MessageController {
     private CustomerService customerService;
     @Autowired
     private MessageService messageService;
+    @Autowired
+    private WxService wxService;
 
 
     @GetMapping

+ 12 - 76
src/main/java/com/loan/system/controller/wechat/MessageSendController.java

@@ -18,6 +18,9 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * 微信模板消息发送控制器
@@ -36,16 +39,16 @@ public class MessageSendController {
 
     @PostMapping("/send/test")
     @ApiOperation(value = "发送微信订阅模板消息", notes = "向指定用户发送微信小程序订阅模板消息")
-    public Result sendTemplateMessageTest() {
-
-        // 转换为 TemplateMessage 对象
+    private Result sendTestMessage(){
         TemplateMessage message = new TemplateMessage();
-
-
-        // 发送消息
-        boolean success = wxService.sendTemplateMessage("oln6A10gAGkHE0TciZCUd67Cxapg", message);
-
-        return success ? ResultUtil.success("消息发送成功") : ResultUtil.error(-500, "消息发送失败");
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("thing1", Collections.singletonMap("value", "1"));
+        data.put("thing3", Collections.singletonMap("value", "www"));
+        data.put("amount4", Collections.singletonMap("value", "1000"));
+        data.put("thing5", Collections.singletonMap("value", "stepName"));
+        message.setData(data);
+        wxService.sendTemplateMessage("oln6A10gAGkHE0TciZCUd67Cxapg", message);
+        return ResultUtil.success("success");
     }
 
     /**
@@ -95,72 +98,5 @@ public class MessageSendController {
         }
     }
 
-    /**
-     * 批量发送微信订阅模板消息
-     *
-     * @param dto     模板消息发送请求DTO(openid 可以为空,通过其他方式获取)
-     * @param openids 接收者 openid 列表
-     * @return 发送结果统计
-     */
-    @PostMapping("/send/batch")
-    @ApiOperation(value = "批量发送微信订阅模板消息", notes = "向多个用户批量发送微信小程序订阅模板消息")
-    public Result sendBatchTemplateMessage(
-            @Valid @RequestBody TemplateMessageSendDTO dto,
-            @ApiParam(value = "接收者 openid 列表", required = true)
-            @RequestParam @NotBlank(message = "openids 不能为空") String[] openids) {
-        try {
-            log.info("收到批量发送模板消息请求: templateId={}, count={}", dto.getTemplateId(), openids.length);
-
-            if (dto.getData() == null || dto.getData().isEmpty()) {
-                throw new DescribeException(ExceptionEnum.INPUT_ERROR.getCode(), "模板数据不能为空");
-            }
-
-            int successCount = 0;
-            int failCount = 0;
-            StringBuilder failDetails = new StringBuilder();
-
-            // 转换为 TemplateMessage 对象
-            TemplateMessage message = new TemplateMessage();
-            message.setTemplate_id(dto.getTemplateId());
-            message.setPage(dto.getPage());
-            message.setUrl(dto.getUrl());
-            message.setMiniprogram(dto.getMiniprogram());
-            message.setData(dto.getData());
-            message.setClient_msg_id(dto.getClientMsgId());
-
-            // 批量发送
-            for (String openid : openids) {
-                try {
-                    message.setTouser(openid);
-                    boolean success = wxService.sendTemplateMessage(openid, message);
-                    if (success) {
-                        successCount++;
-                    } else {
-                        failCount++;
-                        failDetails.append(openid).append("; ");
-                    }
-                } catch (Exception e) {
-                    failCount++;
-                    failDetails.append(openid).append("(").append(e.getMessage()).append("); ");
-                    log.error("发送消息失败: openid={}, error={}", openid, e.getMessage());
-                }
-            }
-
-            log.info("批量发送完成: 成功={}, 失败={}", successCount, failCount);
-
-            java.util.Map<String, Object> result = new java.util.HashMap<>();
-            result.put("total", openids.length);
-            result.put("successCount", successCount);
-            result.put("failCount", failCount);
-            if (failCount > 0) {
-                result.put("failDetails", failDetails.toString());
-            }
-
-            return ResultUtil.success("批量发送完成", result);
-        } catch (Exception e) {
-            log.error("批量发送模板消息异常: {}", e.getMessage(), e);
-            return ResultUtil.error(-500, "批量发送消息异常: " + e.getMessage());
-        }
-    }
 }
 

+ 9 - 90
src/main/java/com/loan/system/controller/wechat/OssFileController.java

@@ -1,11 +1,14 @@
 package com.loan.system.controller.wechat;
 
 import cn.hutool.core.util.StrUtil;
+import com.aliyun.oss.model.OSSObject;
+import com.loan.system.domain.dto.BatchDownloadDTO;
 import com.loan.system.domain.dto.CompleteMultipartUploadDTO;
 import com.loan.system.domain.entity.Document;
 import com.loan.system.domain.enums.ExceptionEnum;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.DocumentVO;
+import com.loan.system.exception.DescribeException;
 import com.loan.system.service.DocumentService;
 import com.loan.system.service.Impl.OssService;
 import com.loan.system.utils.ResultUtil;
@@ -26,6 +29,8 @@ import java.net.URLEncoder;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 @Slf4j
 @RestController
@@ -43,55 +48,10 @@ public class OssFileController {
     public Result uploadFileToOss(@PathVariable("caseId") Long caseId, 
                                   @PathVariable("type") String fileType, 
                                   @RequestParam(required = false) MultipartFile file, 
-                                  @RequestParam Map<String, String> isDelete) throws IOException {
-        // 处理待删除的文件
-        Iterator<Map.Entry<String, String>> iterator = isDelete.entrySet().iterator();
-        while (iterator.hasNext()) {
-            Map.Entry<String, String> entry = iterator.next();
-            Long id = Long.parseLong(entry.getKey());
-            Integer value = Integer.parseInt(entry.getValue());
-            Document document = fileService.findById(id);
-            if (ObjectUtils.isEmpty(document))
-                break;
-
-            if (value != 0) {
-                log.info("删除文件: {}", id);
-                fileService.deleteFileById(id);
-                // 从OSS删除文件
-                ossService.deleteFile(document.getFileName());
-            }
-        }
-
-        if (file == null)
-            return ResultUtil.success("success");
-
-        String originalName = file.getOriginalFilename();
-        String ext = FilenameUtils.getExtension(originalName).toLowerCase(Locale.ROOT);
-
-        // 生成新的文件名
-        String randomUUID = UUID.randomUUID().toString();
-        String newFileName = String.format("%d/%s/%s.%s", caseId, fileType, randomUUID, ext);
-
-        // 上传到OSS
-        String fileUrl = ossService.uploadFile(file.getInputStream(), newFileName);
-        if (fileUrl == null) {
-            return ResultUtil.error(ExceptionEnum.DIRECTORY_CREATE_ERROR);
-        }
-
-        Document document = new Document();
-        document.setCaseId(caseId);
-        document.setFileName(randomUUID+"."+ext);
-        document.setOriginName(originalName);
-        document.setFilePath(fileUrl); // 存储OSS文件URL
-        document.setFileSize(file.getSize());
-        document.setDocType(ext);
-        document.setDictType(fileType);
-        document.setIsDelete(false);
-        document.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        document.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        DocumentVO documentVO = fileService.uploadFile(document);
-
-        return ResultUtil.success("上传成功", documentVO);
+                                  @RequestParam Map<String, String> isDelete)  {
+        if (file !=  null && file.getSize()> 20 * 1024 * 1024)
+            throw new DescribeException(ExceptionEnum.FILE_SIZE_IS_EXCEED);
+        return fileService.uploadFileToOss(file, caseId, fileType, isDelete);
     }
 
     @GetMapping("/download/{caseId}/{fileType}/{filename:.+}")
@@ -137,47 +97,6 @@ public class OssFileController {
         }
     }
 
-    /** 从OSS下载文件 */
-    @GetMapping("/download/{fileName}")
-    @ApiOperation("OSS文件下载")
-    public void downloadFileFromOss(@PathVariable String fileName, 
-                                    @RequestParam String caseId, 
-                                    @RequestParam String fileType, 
-                                    HttpServletResponse response) throws IOException {
-        // 从OSS下载文件
-        com.aliyun.oss.model.OSSObject ossObject = ossService.downloadFile(fileName);
-        if (ossObject == null) {
-            response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在");
-            return;
-        }
-
-        log.info("文件获取成功: {}, 大小: {}", fileName, ossObject.getObjectMetadata().getContentLength());
-
-        response.setContentType(ossObject.getObjectMetadata().getContentType());
-        response.setHeader("Content-Disposition",
-                "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
-
-        try (InputStream in = ossObject.getObjectContent();
-             OutputStream out = response.getOutputStream()) {
-            byte[] buffer = new byte[8192];
-            int len;
-            while ((len = in.read(buffer)) != -1) {
-                out.write(buffer, 0, len);
-            }
-        }
-    }
-
-    /** 从OSS删除文件 */
-    @DeleteMapping("/delete/{caseId}/{type}")
-    @ApiOperation("OSS文件删除")
-    public Result deleteFileFromOss(@RequestParam String fileName,
-                                    @PathVariable Long caseId, 
-                                    @PathVariable String fileType) {
-        // 从OSS删除文件
-        ossService.deleteFile(fileName);
-        return ResultUtil.success("文件删除成功");
-    }
-
     /** 获取文件列表 */
     @GetMapping("/{caseId}")
     @ApiOperation("获取文件列表")

+ 22 - 29
src/main/java/com/loan/system/controller/wechat/RepaymentController.java

@@ -62,14 +62,15 @@ public class RepaymentController {
         if (ObjectUtils.isEmpty(repaymentRecordDTO) || isAllFieldsNull(repaymentRecordDTO))
             throw new DescribeException(INPUT_ERROR);
 
-        if (caseId == null || !loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.REPAY_START.getCode(), caseId);
         if (ObjectUtils.isEmpty(stepVO) || !stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        repaymentService.addDisbursement(repaymentRecordDTO, caseId, recordId);
+        repaymentService.addDisbursement(repaymentRecordDTO, loanCaseSimpleVO, recordId);
 
         return ResultUtil.success("success");
     }
@@ -92,7 +93,8 @@ public class RepaymentController {
         if (ObjectUtils.isEmpty(approvalDTO) || approvalDTO.getCaseId() == null || approvalDTO.getRecordId() == null)
             throw new DescribeException(INPUT_ERROR);
 
-        if (!loanService.existsByIdAndIsDelete(approvalDTO.getCaseId()))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(approvalDTO.getCaseId(), false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         Long caseId = approvalDTO.getCaseId();
@@ -101,7 +103,7 @@ public class RepaymentController {
         if (!stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        repaymentService.repaymentApproval(approvalDTO, chargeId, assistantId);
+        repaymentService.repaymentApproval(loanCaseSimpleVO,approvalDTO, chargeId, assistantId);
 
         return ResultUtil.success("success");
     }
@@ -113,7 +115,8 @@ public class RepaymentController {
         if (ObjectUtils.isEmpty(approvalDTO) || approvalDTO.getCaseId() == null || approvalDTO.getRecordId() == null)
             throw new DescribeException(INPUT_ERROR);
 
-        if (!loanService.existsByIdAndIsDelete(approvalDTO.getCaseId()))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(approvalDTO.getCaseId(), false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         Long caseId = approvalDTO.getCaseId();
@@ -122,7 +125,7 @@ public class RepaymentController {
         if (stepVO.getStatus().equals(StepEnum.COMPLETED.getMsg()))
             throw new DescribeException(ExceptionEnum.STEP_HAS_COMPLETEED);
 
-        repaymentService.repaymentCancel(approvalDTO);
+        repaymentService.repaymentCancel(loanCaseSimpleVO,approvalDTO);
 
         return ResultUtil.success("success");
     }
@@ -180,29 +183,16 @@ public class RepaymentController {
     public Result balanceRepay(@RequestParam Long caseId, @RequestBody RepaymentRecordDTO repaymentRecordDTO) {
         if (ObjectUtils.isEmpty(repaymentRecordDTO) || caseId == null)
             throw new DescribeException(INPUT_ERROR);
-        if (!loanService.existsByIdAndIsDelete(caseId))
+
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BALANCE_REPAY.getCode(), caseId);
         if (ObjectUtils.isEmpty(stepVO) || !stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        if (stepVO.getUserIds() != null) {
-            boolean flag = false;//是否存在
-            String[] userIds = stepVO.getUserIds().split(",");//分主办与辅办,但仅需任意一人操作即可
-            for (String userId : userIds) {
-                Long currentId = Long.valueOf(userId);
-                if (BaseContext.getCurrentId().equals(currentId)) {
-                    flag = true;
-                    break;
-                }
-            }
-            if (!flag)
-                //全部遍历结束未break,表示不是预期用户
-                throw new DescribeException(STEP_USER_NOT_EXPECTED);
-        }
-
-        repaymentService.balanceRepay(repaymentRecordDTO, caseId);
+        repaymentService.balanceRepay(loanCaseSimpleVO,repaymentRecordDTO);
 
         return ResultUtil.success("success");
     }
@@ -213,14 +203,15 @@ public class RepaymentController {
     public Result AutoRepay(@RequestParam Long caseId, @RequestBody RepaymentRecordDTO repaymentRecordDTO) {
         if (ObjectUtils.isEmpty(repaymentRecordDTO) || caseId == null)
             throw new DescribeException(INPUT_ERROR);
-        if (!loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BALANCE_REPAY.getCode(), caseId);
         if (ObjectUtils.isEmpty(stepVO) || !stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        repaymentService.autoRepay(repaymentRecordDTO, caseId);
+        repaymentService.autoRepay(repaymentRecordDTO, loanCaseSimpleVO);
 
         return ResultUtil.success("success");
     }
@@ -232,14 +223,15 @@ public class RepaymentController {
     @ApiOperation(value = "财务确认")
     @PreAuthorize("@pms.hasRole('FINANCE')")
     public Result financeConfirm(@RequestParam List<Long> recordIds, @RequestParam Long caseId, @RequestParam String comment) {//TODO:一下子可以确认多笔
-        if (caseId == null || !loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.FINANCE_CONFIRM.getCode(), caseId);
         if (ObjectUtils.isEmpty(stepVO) || !stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
             throw new DescribeException(STEP_HAS_NOT_PROCESS);
 
-        repaymentService.financeConfirm(recordIds, caseId, comment);
+        repaymentService.financeConfirm(recordIds,loanCaseSimpleVO, comment);
 
         return ResultUtil.success("success");
     }
@@ -248,7 +240,8 @@ public class RepaymentController {
     @ApiOperation(value = "回款完成")
     @PreAuthorize("@pms.hasAnyRoles('LEAD_SALES', 'ASSIST_SALES')")
     public Result repayComplete(@RequestParam Long caseId) {
-        if (caseId == null || !loanService.existsByIdAndIsDelete(caseId))
+        LoanCaseSimpleVO loanCaseSimpleVO = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        if (loanCaseSimpleVO == null)
             throw new DescribeException(ExceptionEnum.PROJECT_NOT_EXIST);
 
         StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.REPAYMENT_COMPLETE.getCode(), caseId);
@@ -259,7 +252,7 @@ public class RepaymentController {
         if (ObjectUtils.isEmpty(stepVO1) || !stepVO1.getStatus().equals(StepEnum.COMPLETED.getMsg()))
             throw new DescribeException(PRE_STEP_NOT_COMPLETE);
 
-        repaymentService.repayComplete(caseId);
+        repaymentService.repayComplete(loanCaseSimpleVO);
 
         return ResultUtil.success("success");
     }

+ 1 - 8
src/main/java/com/loan/system/controller/wechat/StatisticsController.java

@@ -273,13 +273,6 @@ public class StatisticsController {
                 loanCaseStatistic.setBusinessType(loanCase.getBusinessType());//4.
                 loanCaseStatistic.setAmount(loanCase.getTotalLoanAmount());//5.
 
-//                String stepName = "";
-//                if(step.getCode()==StepPropertyEnum.CHANNEL_PUSH.getCode())
-//                    stepName += "(取证)";
-//                else if (step.getCode()==StepPropertyEnum.CHANNEL_PUSH_2.getCode())
-//                    stepName += "(送证)";
-//                else
-//                    stepName = step.getStepName();
                 loanCaseStatistic.setStepName(step.getStepName());//6.
 
                 if (step.getCode().equals(StepPropertyEnum.BALANCE_REPAY.getCode())||step.getCode().equals(StepPropertyEnum.DISBURSE_START.getCode())){
@@ -443,7 +436,7 @@ public class StatisticsController {
                 })
                 .collect(Collectors.toList());
         //查询概览运营数据,提供给Excel模板文件
-        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "工作计划排期&业务统计表.xlsx");
+        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "loanStatistics.xlsx");
         try {
             //基于提供好的模板文件创建一个新的Excel表格对象
             XSSFWorkbook excel = new XSSFWorkbook(inputStream);

+ 5 - 5
src/main/java/com/loan/system/controller/wechat/UploadController.java

@@ -14,6 +14,7 @@ import com.loan.system.service.StepService;
 import com.loan.system.utils.ResultUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -37,13 +38,12 @@ import static com.loan.system.domain.enums.ExceptionEnum.STEP_HAS_NOT_PROCESS;
 @RestController
 @RequestMapping("/wechat/ossfile")
 @Api(tags = "文件处理接口")
+@Slf4j
 public class UploadController {
     @Autowired
     private DocumentService fileService;
     @Autowired
     private FileUploadConfig config;
-    @Autowired
-    private StepService stepService;
 
     /** 上传文件(支持任意类型,只要在白名单内) */
     @PostMapping("/upload/{caseId}/{type}")
@@ -119,12 +119,12 @@ public class UploadController {
             Path path = Paths.get(filePath);
             boolean deleted = Files.deleteIfExists(path);
             if (deleted) {
-                System.out.println("文件删除成功: " + filePath);
+                log.info("文件删除成功:{} " , filePath);
             } else {
-                System.out.println("文件不存在或已被删除: " + filePath);
+                log.error("文件不存在或已被删除:{}", filePath);
             }
         } catch (IOException e) {
-            System.err.println("删除文件时发生错误: " + e.getMessage());
+            log.error("删除文件时发生错误:{}" , e.getMessage());
             e.printStackTrace();
         }
     }

+ 2 - 26
src/main/java/com/loan/system/controller/wechat/UserController.java

@@ -169,6 +169,7 @@ public class UserController {//包含内部人员、外部人员
         }else if(user_is_exist){   //存在用户
             UserLoginDTO userLoginDTO = new UserLoginDTO();
             userLoginDTO.setTel(phoneNumber);
+            userLoginDTO.setOpenId(openId);
             return this.user_login(userLoginDTO);
         }else { //存在客户
             Customer customer=customerService.findBymobileAndIsDelete(phoneNumber);
@@ -198,25 +199,6 @@ public class UserController {//包含内部人员、外部人员
             return this.customer_login(customer);
         }
     }
-//    @PostMapping("/login")
-//    @ApiOperation("账号登陆")
-//    public Result login(@RequestBody UserLoginDTO userLoginDTO){
-//        String phoneNumber=userLoginDTO.getTel();
-//        boolean user_is_exist = userService.existsByMobileAndIsDelete(phoneNumber);
-//        boolean customer_is_exist=customerService.existsBymobileAndIsDelete(phoneNumber);
-//        if(!customer_is_exist&&!user_is_exist){
-//            Customer customer = new Customer();
-//            customer.setMobile(phoneNumber);
-//            customer.setOpenid(userLoginDTO.getOpenid());
-//            return this.register(customer);
-//        }else if(customer_is_exist){
-//            Customer customer=customerService.findBymobileAndIsDelete(phoneNumber);
-//            return this.customer_login(customer);
-//        }else{
-//            return this.user_login(userLoginDTO);
-//        }
-//    }
-
 
     @PostMapping("/role")
     @ApiOperation("添加用户角色")
@@ -258,12 +240,6 @@ public class UserController {//包含内部人员、外部人员
             throw new DescribeException(ExceptionEnum.INPUT_ERROR);
         return ResultUtil.success("success", userService.listSales(stepCode));
     }
-//    @GetMapping("/finances")
-//    @ApiOperation("查询所有财务")
-//    @PreAuthorize("@pms.hasAnyRoles('SYSTEM_ADMIN','APPROVER','BACK_OFFICE')")
-//    public Result findAllFinances(){
-//
-//        return ResultUtil.success("success", userService.findAllFinances());
-//    }
+
 
 }

+ 1 - 0
src/main/java/com/loan/system/domain/dto/ApprovalRecordDTO.java

@@ -14,6 +14,7 @@ import java.io.Serializable;
 public class ApprovalRecordDTO implements Serializable {
     private Long caseId;//业务ID
     private Long recordId;
+    private String disbursementTime;//实际出款时间
     private Integer stepCode;//环节名称
     private Long approverId;//审批人ID
     private String decision;//审批结果

+ 14 - 0
src/main/java/com/loan/system/domain/dto/BatchDownloadDTO.java

@@ -0,0 +1,14 @@
+package com.loan.system.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(description = "批量下载请求DTO")
+public class BatchDownloadDTO {
+
+    private List<DocumentDTO> documentDTOList;
+}

+ 15 - 0
src/main/java/com/loan/system/domain/dto/DetailDTO.java

@@ -0,0 +1,15 @@
+package com.loan.system.domain.dto;
+
+import com.loan.system.domain.vo.ApprovalRecordVO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DetailDTO<T>{
+    private List<T> data;
+}

+ 0 - 1
src/main/java/com/loan/system/domain/dto/DictTypeDTO.java

@@ -14,7 +14,6 @@ import javax.validation.constraints.Size;
 @AllArgsConstructor
 @NoArgsConstructor
 public class DictTypeDTO extends BaseEntity {
-    private static final long serialVersionUID = 34L;
     private String dictName;
     private String dictType;
     private Boolean status;

+ 2 - 2
src/main/java/com/loan/system/domain/dto/DisbursementRecordDTO.java

@@ -25,8 +25,8 @@ public class DisbursementRecordDTO implements Serializable {
     private List<DisburseBankInfoDTO> disburseBankInfos;
     private String comment;
     private Map<Long,Double> contractIdAndAmount;//每个合同对应的出款金额
-    private Map<Long,Boolean> contractIdAndIsComplete;
-    private String createTime;
+    private Map<Long,Boolean> contractIdAndIsComplete;//每个合同是否已出款完成
+    private String createTime;//出款时间
     private String approvalIds;
     private String financeApprovalIds;
 

+ 1 - 0
src/main/java/com/loan/system/domain/dto/DocumentDTO.java

@@ -17,5 +17,6 @@ public class DocumentDTO implements Serializable {
     private String docType;//文档类型
     private String filePath;//文件路径
     private String fileName;//文件名
+    private String originName;//原始文件名
     private Long fileSize;//文件大小
 }

+ 1 - 0
src/main/java/com/loan/system/domain/dto/LoanCaseDTO.java

@@ -22,6 +22,7 @@ public class LoanCaseDTO implements Serializable {
     private List<ContractDTO> contracts;//合同
     //private String address;//房产实际地点
     private CustomerDTO customer;
+    private String businessUsage;
     private List<Map<String,List<Integer>> > collateralAndContract;
     private Map<Integer,List<Integer>> contractSeqAndCollateralSeq;
     private List<CollateralDTO> collateral;//押品

+ 1 - 1
src/main/java/com/loan/system/domain/dto/RepaymentRecordDTO.java

@@ -30,7 +30,7 @@ public class RepaymentRecordDTO implements Serializable {
     private Long mainUserId;
     private Double interestAmount;//单次利息
     private String repayComment;
-    private String repayWay;
+    private String repayWay;//回款时间
     private String repayTime;
     private Boolean isInterest;
     private List<ClearDetailDTO> clearDetailList;

+ 16 - 0
src/main/java/com/loan/system/domain/dto/query/CollateralQueryDTO.java

@@ -0,0 +1,16 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CollateralQueryDTO {
+    private Long caseId;//业务id
+    private String collateralName;//押品名称
+    private String collateralType;//押品类型/业务属性
+    private Boolean isMortgaged;
+    private String staus;//押品状态
+}

+ 20 - 0
src/main/java/com/loan/system/domain/dto/query/ContractQueryDTO.java

@@ -0,0 +1,20 @@
+package com.loan.system.domain.dto.query;
+
+import com.loan.system.domain.dto.ContractBankInfoDTO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ContractQueryDTO{
+    private String businessAttr;//业务属性
+    private Long caseId;//业务id
+    private Long customerId;//客户id
+    private String contractNo;// 合同编号
+    private String contractName;//合同名称
+}

+ 15 - 0
src/main/java/com/loan/system/domain/dto/query/CustomerQueryDTO.java

@@ -0,0 +1,15 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CustomerQueryDTO {
+    private Long id;
+    private String name;
+    private String mobile;
+    private String marriedStatus;
+}

+ 13 - 0
src/main/java/com/loan/system/domain/dto/query/DictDataQueryDTO.java

@@ -0,0 +1,13 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DictDataQueryDTO {
+    private String dictLabel;//标签
+    private String dictType;//类型
+}

+ 15 - 0
src/main/java/com/loan/system/domain/dto/query/DocumentQueryDTO.java

@@ -0,0 +1,15 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DocumentQueryDTO {
+    private Long caseId;//业务ID
+    private String originName;
+    private String dictType;//资料类型
+    private String docType;//文档类型
+}

+ 19 - 0
src/main/java/com/loan/system/domain/dto/query/LoanCaseQueryDTO.java

@@ -0,0 +1,19 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class LoanCaseQueryDTO {
+    private Long id;
+    private Long customerId;
+    private String businessType;
+    private String businessAttrs;
+    private String channelName;
+    private String isComplete;
+    private Boolean isDelete;
+}

+ 18 - 0
src/main/java/com/loan/system/domain/dto/query/RecommenderQueryDTO.java

@@ -0,0 +1,18 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RecommenderQueryDTO {
+    private String recommenderName;
+    private String mobile;
+    private String channelName;
+    private String group;
+}

+ 15 - 0
src/main/java/com/loan/system/domain/dto/query/UserQueryDTO.java

@@ -0,0 +1,15 @@
+package com.loan.system.domain.dto.query;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserQueryDTO {
+    private Long id;
+    private String realName;
+    private String mobile;
+    private String role;
+}

+ 3 - 0
src/main/java/com/loan/system/domain/entity/LoanCase.java

@@ -28,6 +28,9 @@ public class LoanCase extends BaseEntity{
     @Column(name = "other_id2")
     private Long otherId2;
 
+    @Column(name = "business_usage" )
+    private String businessUsage;
+
     @Column(name = "business_type" , length = 20)
     private String businessType;
 

+ 7 - 4
src/main/java/com/loan/system/domain/enums/ExceptionEnum.java

@@ -47,7 +47,7 @@ public enum ExceptionEnum {
     FILE_MERGE_FAILED(-49,"文件合并失败"),
     FILE_CHECK_FAILED(-50,"文件校验错误"),
     IO_CLOSE_ERROR(-51,"读写错误"),
-    FILE_NOT_IMAGE(-52,"文件不是图片类型"),
+    FILE_SIZE_IS_EXCEED(-52,"文件大小超过20MB,请重新上传"),
     VERSION_CONTROLLER_FAILED(-53,"启用版本控制失败"),
 
     // -45 文件类型限制
@@ -92,7 +92,7 @@ public enum ExceptionEnum {
     CONTRACT_NOT_EXIST(-251, "合同不存在"),
     CONTRACT_MATERIAL_EXIST(-255, "合同材料已存在"),
     CONTRACT_MATERIAL_NOT_EXIST(-256, "合同材料不存在"),
-    CONTRACT_SIGN_NOT_COMPLETE(-257,"合同未全部签署"),
+    CONTRACT_SIGN_NOT_COMPLETE(-257,"合同未全部签署,无法终结"),
     CONTRACT_TYPE_EXIST(-260, "合同类型已存在"),
     CONTRACT_TYPE_NOT_EXIST(-261, "合同类型不存在"),
     CONTRACT_TYPE_ERROR(-263,"合同类型超出限制"),
@@ -143,8 +143,11 @@ public enum ExceptionEnum {
     FUND_OUTPUT_EXIST(-402,"支出表已存在"),
     FUND_OUTPUT_NOT_EXIST(-403,"支出表不存在"),
     FUND_OUTPUT_HAS_NOT_EXIST(-404,"存在支出表不存在"),
-    FUND_SHOULD_NOT_BE_NULL(-405,"经费来源不能为空"),
-    INSUFFICIENT_BALANCE_OF_FUND(-410,"经费余额不足"),
+    ILLEGAL_OPERATION(-405,"非法操作,未进行出帐,无法结束"),
+    ILLEGAL_OPERATION_1(-406,"非法操作,出帐申报未审批通过,无法结束"),
+    ILLEGAL_OPERATION_2(-407,"非法操作,出帐操作有计划待出帐,无法结束"),
+    ILLEGAL_OPERATION_3(-408,"非法操作,出帐操作未审批通过,无法结束"),
+    ILLEGAL_OPERATION_4(-409,"非法操作,出帐操作未财务复核通过,无法结束"),
     FUND_OUTPUT_EXCESSIVE(-411,"经费使用超出所需"),
     ACCOUNT_IS_LOCK(-412, "账户已经被锁定请15分钟后再试"),
     WEAK_PASSWORD_ACCOUNT_IS_LOCK(-413, "账户因弱密码被锁定请联系管理员解锁"),

+ 6 - 3
src/main/java/com/loan/system/domain/enums/StepPropertyEnum.java

@@ -55,7 +55,8 @@ public enum StepPropertyEnum {
     FINANCE_CONFIRM(576, "财务确认", false),
     REPAYMENT_COMPLETE(577, "完成回款", false),
     CASE_COMPLETE(578, "业务终结", false),
-    CASE_ARCHIVE(579, "业务归档", false);
+    CASE_ARCHIVE_PARENT(580, "业务归档", true),
+    CASE_ARCHIVE(581, "归档列表", false);
 
 
     /* ========== 字段 & 构造 ========== */
@@ -201,6 +202,7 @@ public enum StepPropertyEnum {
         /* 回款环节 */
         bizRoleMap.put(REPAY_START.getCode(), Arrays.asList(LEAD_SALES.getMsg(), ASSIST_SALES.getMsg()));
         bizRoleMap.put(BALANCE_REPAY.getCode(), Arrays.asList(LEAD_SALES.getMsg(), ASSIST_SALES.getMsg()));
+        bizRoleMap.put(AUTO_REPAY.getCode(), Arrays.asList(LEAD_SALES.getMsg(), ASSIST_SALES.getMsg()));
         bizRoleMap.put(REPAYMENT_COMPLETE.getCode(), Arrays.asList(LEAD_SALES.getMsg(), ASSIST_SALES.getMsg()));
 
         /* 回款派单/财务核算/确认 —— 审批人/财务人员 */
@@ -249,8 +251,9 @@ public enum StepPropertyEnum {
                 Arrays.asList(30),
                 Arrays.asList(31),
                 Arrays.asList(32),
-                Arrays.asList(33),
-                 Arrays.asList()
+                Arrays.asList(34),
+                Arrays.asList(),//业务归档
+                Arrays.asList()
         ));
 
         return list;

+ 1 - 1
src/main/java/com/loan/system/domain/pojo/ContractInformation.java

@@ -12,7 +12,7 @@ import javax.persistence.Column;
 public class ContractInformation {
     //合同信息
     private String contractNo;
-    private Double contractAmount;//合同金额
+    private String contractAmount;//合同金额
     private Double amountRate;//当金利率
     private Double serviceCost;//综合服务费
     private Double loanRate;//借款利率

+ 1 - 1
src/main/java/com/loan/system/domain/vo/CollateralVO.java

@@ -20,7 +20,7 @@ public class CollateralVO implements Serializable {
     private String mobile;
     private String collateralType;//押品类型/业务属性
     private Long ownerCustomerId;//押品所属客户id
-    private BigDecimal allocatedAmount;//押品分配金额
+    private Double allocatedAmount;//押品分配金额
     private String address;//押品信息地址
     private String currentAddress;//押品实际地址
     private String collateralNo;

+ 5 - 5
src/main/java/com/loan/system/domain/vo/CustomerVO.java

@@ -21,10 +21,10 @@ public class CustomerVO implements Serializable {
     private String marriedStatus;
     private String bankAccount;
     private String bankName;
-    private Boolean isIllegal;
-    private Boolean faceAuth;
+    private Boolean isIllegal;//是否实名认证
+    private Boolean faceAuth;//是否人脸识别
     private String contactAddress;
-    private String businessLicense;
-    private Boolean isRegister;
-
+    private String businessLicense;//营业执照
+    private Boolean isRegister;//是否注册
+    private String isDelete;
 }

+ 3 - 2
src/main/java/com/loan/system/domain/vo/DisbursementDetailVO.java

@@ -30,11 +30,12 @@ public class DisbursementDetailVO implements Serializable {
     //每个合同的出款时间
     private Map<Long , List<DateAndAmountPOJO>> contractAndDateAndAmount;
 
-    private Map<Long,Double> contractAndCurrentAmount;//目前合同对应的出款金额
+    private Map<Long,Double> contractAndCurrentAmount;//目前合同对应的出款总金额
+    private Map<Long,Double> contractAndCurrentAmount1;//目前合同对应的财务确认后的出款总金额
 
     private List<String> collateralStatus;//押品状态
     private Double currentPlanAmount;//已申报的金额
-    private Double currentPlanAmount1;//出账派单的申报金额
+    private Double currentPlanAmount1;//出账派单的申报金额
     private Double currentAmount;//出账操作的目前金额
     private Double currentAmount1;//目前金额
     private Double totalAmount;//实际总金额

+ 1 - 1
src/main/java/com/loan/system/domain/vo/DisbursementRecordVO.java

@@ -38,6 +38,6 @@ public class DisbursementRecordVO implements Serializable {
 
     private Map<Long ,String> contractAndPawn;//当票信息
 
-    private Map<Long,Double> contractIdAndAmount;//每个合同对应的金额
+    private Map<Long,Double> contractIdAndAmount;//每个合同对应的金额(每次记录对应的出款金额)
 
 }

+ 1 - 0
src/main/java/com/loan/system/domain/vo/DisbursementVO.java

@@ -26,5 +26,6 @@ public class DisbursementVO extends BaseEntity {
     private UserVO mainUser;
     private UserVO assistUser;
     private Map<Long , Double> contractAndPlanAmount;//每个合同的计划金额
+    private Map<Long , Double> contractAndPlanAmount1;//每个合同的审批过后计划金额
 
 }

+ 6 - 2
src/main/java/com/loan/system/domain/vo/DocumentVO.java

@@ -1,21 +1,25 @@
 package com.loan.system.domain.vo;
 
+import com.loan.system.domain.entity.LoanCase;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
+import java.util.List;
 
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 public class DocumentVO implements Serializable {
     private Long id;//文档ID
-    private Long caseId;//业务ID
-    private Long ownerId;//客户id
+    private Long caseId;
+    private LoanCaseVO loanCaseVO;
     private String dictType;//资料类型
     private String docType;//文档类型
     private String filePath;//文件路径
     private String fileName;//文件名
+    private String originName;
     private Long fileSize;//文件大小
+    private String createTime;
 }

+ 26 - 0
src/main/java/com/loan/system/domain/vo/LoanCaseAdminVO.java

@@ -0,0 +1,26 @@
+package com.loan.system.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class LoanCaseAdminVO implements Serializable {
+    private Long id;
+    private CustomerVO customer;
+    private String businessUsage;
+    private String businessAttrs;//业务属性
+    private String businessType;//业务类型
+    private String channelName;
+    private String group;
+    private BizRecommenderVO recommender;
+    private Double totalLoanAmount;//总借款金额
+    private Boolean IsDelete;
+    private String createTime;
+    private String updateTime;
+    private String isComplete;
+}

+ 1 - 0
src/main/java/com/loan/system/domain/vo/LoanCaseCompleteVO.java

@@ -16,6 +16,7 @@ public class LoanCaseCompleteVO {
     private String customerName;//客户名称、
     private String mobile;//联系方式
     private String customersName;//共同借款人名称
+    private String businessUsage;
     private String businessType;// 业务类型、
     private String businessChannel;// 业务渠道、
     private String collateralNames;//房产地址

+ 1 - 0
src/main/java/com/loan/system/domain/vo/LoanCaseSimpleVO.java

@@ -16,6 +16,7 @@ public class LoanCaseSimpleVO implements Serializable {
     private Long customerId;
     private Long otherId1;
     private Long otherId2;
+    private String businessUsage;
     private String businessType;
     private String businessAttrs;
     private String channelName;

+ 3 - 0
src/main/java/com/loan/system/domain/vo/LoanCaseVO.java

@@ -23,6 +23,7 @@ public class LoanCaseVO implements Serializable {
     private CustomerVO customer;
     //private Long caseId;
     private String userName;
+    private String businessUsage;
     private String businessAttrs;//业务属性
     private List<ContractVO> contracts;
     private String address;//房产实际地点
@@ -45,3 +46,5 @@ public class LoanCaseVO implements Serializable {
     private String createTime;
     private String isComplete;
 }
+
+

+ 1 - 0
src/main/java/com/loan/system/domain/vo/UserVO.java

@@ -20,5 +20,6 @@ public class UserVO implements Serializable {
     private String sex;
     private String mobile;
     private String role;
+    private Boolean isDelete;
 
 }

+ 39 - 15
src/main/java/com/loan/system/exception/GlobalExceptionHandler.java

@@ -10,14 +10,20 @@ import com.loan.system.utils.logUtils.IPUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import javax.annotation.Resource;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.servlet.http.HttpServletRequest;
 import java.nio.file.AccessDeniedException;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  *  统一异常处理
@@ -26,26 +32,44 @@ import java.util.concurrent.CompletableFuture;
  */
 @ControllerAdvice
 @ResponseBody
-public class GlobalExceptionHandler {
+public class GlobalExceptionHandler implements ApplicationListener<ContextClosedEvent> {
     private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
     @Autowired
     private ExceptionLogService exceptionLogService;
+    
+    private final AtomicBoolean isShuttingDown = new AtomicBoolean(false);
+
+    @Override
+    public void onApplicationEvent(ContextClosedEvent event) {
+        isShuttingDown.set(true);
+    }
+
     @ExceptionHandler(value = Exception.class)
     public Result exceptionGet(Exception e , HttpServletRequest req) {
 
-        CompletableFuture.runAsync(() -> {
-            ExceptionLog logPo = ExceptionLog.build(
-                    e,
-                    req.getRequestURI(),
-                    req.getMethod(),
-                    IPUtils.getIpAddr(req),
-                    req.getHeader("User-Agent"),
-                    BaseContext.getCurrentId(),
-                    null
-            );
-            exceptionLogService.save(logPo);
-        });
+        // 检查应用是否正在关闭,如果是则不同步记录日志
+        if (!isShuttingDown.get()) {
+            try {
+                CompletableFuture.runAsync(() -> {
+                    if (!isShuttingDown.get()) { // 双重检查
+                        ExceptionLog logPo = ExceptionLog.build(
+                                e,
+                                req.getRequestURI(),
+                                req.getMethod(),
+                                IPUtils.getIpAddr(req),
+                                req.getHeader("User-Agent"),
+                                BaseContext.getCurrentId(),
+                                null
+                        );
+                        exceptionLogService.save(logPo);
+                    }
+                });
+            } catch (Exception asyncException) {
+                // 如果异步执行失败,记录但不影响主要响应
+                logger.error("Failed to save exception log asynchronously", asyncException);
+            }
+        }
 
         if (e instanceof DescribeException) {
             DescribeException myException = (DescribeException) e;
@@ -67,4 +91,4 @@ public class GlobalExceptionHandler {
             return ResultUtil.error(ExceptionEnum.UNKNOWN_ERROR);
         }
     }
-}
+}

+ 17 - 1
src/main/java/com/loan/system/repository/CollateralRepository.java

@@ -1,7 +1,11 @@
 package com.loan.system.repository;
 
+import com.loan.system.domain.dto.query.CollateralQueryDTO;
 import com.loan.system.domain.entity.Collateral;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.transaction.annotation.Transactional;
@@ -14,7 +18,7 @@ import java.util.List;
  * @date 2020/9/2 - 15:35
  * @Description
  */
-public interface CollateralRepository extends JpaRepository<Collateral,Long> {
+public interface CollateralRepository extends JpaRepository<Collateral,Long>, JpaSpecificationExecutor<Collateral> {
 
     List<Collateral> findByCaseIdAndIsDelete(Long caseId, boolean isDelete);
 
@@ -74,4 +78,16 @@ public interface CollateralRepository extends JpaRepository<Collateral,Long> {
     @Transactional
     @Query("UPDATE Collateral c SET c.operateStatus = ?2 , c.updateTime = CURRENT_TIMESTAMP WHERE c.id in ?1 And c.isDelete= false ")
     void updateCollateralOperateStatusByIds(List<Long> collateralIds, String msg);
+
+    @Query("SELECT c FROM Collateral c WHERE c.isDelete = ?1")
+    Page<Collateral> findAllAndIsDelete(boolean b,Pageable pageable);
+
+    @Query("SELECT lc FROM Collateral lc WHERE " +
+            "(:#{#query.collateralName} IS NULL OR lc.collateralName like %:#{#query.collateralName}%) AND " +
+            "(:#{#query.collateralType} IS NULL OR lc.collateralType = :#{#query.collateralType}) AND " +
+            "(:#{#query.caseId} IS NULL OR lc.caseId = :#{#query.caseId}) AND " +
+            "(:#{#query.staus} IS NULL OR lc.staus = :#{#query.staus}) AND " +
+            "(:#{#query.isMortgaged} IS NULL OR lc.isMortgaged = :#{#query.isMortgaged}) AND " +
+            "lc.isDelete = false")
+    Page<Collateral> findByQueryAndIsDelete(CollateralQueryDTO query, Pageable pageable);
 }

+ 3 - 0
src/main/java/com/loan/system/repository/ContractAndCollateralRepository.java

@@ -24,4 +24,7 @@ public interface ContractAndCollateralRepository extends JpaRepository<ContractA
     List<ContractAndCollateral> findByCaseIdAndIsDelete(Long caseId, Boolean isDelete);
 
     List<ContractAndCollateral> findByContractIdAndIsDelete(Long contractId, boolean b);
+
+    @Query("select c.collateralId from ContractAndCollateral c where c.contractId = ?1 and c.isDelete = ?2")
+    List<Long> findCollateralIdsByContractIdsAndIsDelete(Long id, boolean b);
 }

+ 24 - 0
src/main/java/com/loan/system/repository/ContractRepository.java

@@ -1,9 +1,12 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.ContractBankInfoDTO;
+import com.loan.system.domain.dto.query.ContractQueryDTO;
 import com.loan.system.domain.entity.Contract;
 import com.loan.system.domain.vo.ContractVO;
 import io.swagger.models.Contact;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -116,4 +119,25 @@ public interface ContractRepository extends JpaRepository<Contract,Long> {
     @Modifying
     @Query("update Contract c set c.isDisbursementComplete = ?2  where c.id = ?1")
     void updateISCompleteById(Long contractId, boolean isDisbursement );
+
+    @Query("select c from Contract c where c.isDelete = ?1")
+    Page<Contract> findAllByIsDelete(boolean b, Pageable pageable);
+
+    @Transactional
+    @Modifying
+    @Query("update Contract c set c.isDelete =?2 where c.id = ?1 ")
+    void deleteByIdAndIsDelete(Long id, boolean b);
+
+    @Query("SELECT lc FROM Contract lc WHERE " +
+            "(:#{#query.businessAttr} IS NULL OR lc.businessAttr = :#{#query.businessAttr}) AND " +
+            "(:#{#query.caseId} IS NULL OR lc.caseId = :#{#query.caseId}) AND " +
+            "(:#{#query.customerId} IS NULL OR lc.customerId = :#{#query.customerId}) AND " +
+            "(:#{#query.contractName} IS NULL OR lc.contractName like %:#{#query.contractName}%) AND " +
+            "(:#{#query.contractNo} IS NULL OR lc.contractNo like %:#{#query.contractNo}%) " )
+    Page<Contract> findAllByQuery(ContractQueryDTO query, Pageable pageable);
+
+    @Transactional
+    @Modifying
+    @Query("update Contract c set c.isDisbursementComplete = true where c.caseId = ?1 and c.isDelete = ?2")
+    void updateIsDisbursementByCaseIdAndIsDelete(Long caseId, boolean b);
 }

+ 11 - 0
src/main/java/com/loan/system/repository/CustomerRepository.java

@@ -1,6 +1,7 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.CustomerDTO;
+import com.loan.system.domain.dto.query.CustomerQueryDTO;
 import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.User;
 import org.springframework.data.domain.Page;
@@ -96,4 +97,14 @@ public interface CustomerRepository extends JpaRepository<Customer,Long> {
 
     @Query("select c from Customer c where c.name = ?1 and c.isDelete = ?2")
     List<Customer> findByNameAndIsDelete(String name, Boolean isDelete);
+
+    @Query("SELECT lc FROM Customer lc WHERE " +
+            "(:#{#query.id} IS NULL OR lc.id = :#{#query.id}) AND "+
+            "(:#{#query.name} IS NULL OR lc.name like %:#{#query.name}%) AND " +
+            "(:#{#query.mobile} IS NULL OR lc.mobile like %:#{#query.mobile}%) AND " +
+            "(:#{#query.marriedStatus} IS NULL OR lc.marriedStatus = :#{#query.marriedStatus})")
+    Page<Customer> findByQuery(CustomerQueryDTO query, Pageable pageable);
+
+    @Query("SELECT c FROM Customer c WHERE c.id IN ?1 AND c.isDelete = ?2")
+    List<Customer> findByIdInAndIsDelete(Iterable<Long> ids, boolean isDelete);
 }

+ 12 - 0
src/main/java/com/loan/system/repository/DictDataRepository.java

@@ -1,8 +1,11 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.DictDataDTO;
+import com.loan.system.domain.dto.query.DictDataQueryDTO;
 import com.loan.system.domain.entity.ApprovalRecord;
 import com.loan.system.domain.entity.DictData;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -33,4 +36,13 @@ public interface DictDataRepository extends JpaRepository<DictData,Long> {
     void updateById(DictDataDTO dataDTO, Long id,String updateTime);
 
     List<DictData> findByDictType(String dictType);
+
+    @Query("select d from DictData d where d.status = ?1")
+    Page<DictData> findAllAndIsDelete(boolean b, Pageable pageable);
+
+    @Query("SELECT lc FROM DictData lc WHERE " +
+            "(:#{#query.dictLabel} IS NULL OR lc.dictLabel = :#{#query.dictLabel}) AND " +
+            "(:#{#query.dictType} IS NULL OR lc.dictType = :#{#query.dictType}) AND " +
+            "lc.status = false")
+    Page<DictData> findByQuery(DictDataQueryDTO query, Pageable pageable);
 }

+ 6 - 0
src/main/java/com/loan/system/repository/DictTypeRepository.java

@@ -1,7 +1,10 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.DictTypeDTO;
+import com.loan.system.domain.entity.DictData;
 import com.loan.system.domain.entity.DictType;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -25,4 +28,7 @@ public interface DictTypeRepository extends JpaRepository<DictType,Long> {
             "d.updateTime = :format" +
             " where d.id = :id")
     void updateDictById(DictTypeDTO dictTypeDTO, Long id, String format);
+
+    @Query("select d from DictData d where d.status = :b")
+    Page<DictType> findAllAndIsDelete(boolean b, Pageable pageable);
 }

+ 19 - 0
src/main/java/com/loan/system/repository/DocumentRepository.java

@@ -1,9 +1,12 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.DocumentDTO;
+import com.loan.system.domain.dto.query.DocumentQueryDTO;
 import com.loan.system.domain.entity.DictBusinessType;
 import com.loan.system.domain.entity.Document;
 import com.loan.system.domain.vo.DocumentVO;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -42,4 +45,20 @@ public interface DocumentRepository extends JpaRepository<Document,Long> {
 
     @Query("select d from Document d where d.dictType in ?1 and d.caseId = ?2 and d.isDelete = ?3")
     List<Document> findByFileTypesAndCaseIdAndIsDelete(List<String> fileTypes, Long caseId, boolean b);
+
+    @Query("select d from Document d where d.isDelete = ?1")
+    Page<Document> findAllAndIdDelete(boolean b , Pageable pageable );
+
+    @Transactional
+    @Modifying
+    @Query("update Document d set d.isDelete = false WHERE d.id in ?1")
+    void deleteByIds(List<Long> ids);
+
+    @Query("SELECT lc FROM Document lc WHERE " +
+            "(:#{#query.caseId} IS NULL OR lc.caseId = :#{#query.caseId}) AND " +
+            "(:#{#query.docType} IS NULL OR lc.docType = :#{#query.docType}) AND " +
+            "(:#{#query.originName} IS NULL OR lc.originName like %:#{#query.originName}%) AND " +
+            "(:#{#query.dictType} IS NULL OR lc.dictType = :#{#query.dictType} AND " +
+            "lc.isDelete = false)")
+    Page<Document> findByQuery(DocumentQueryDTO query, Pageable pageable);
 }

+ 15 - 4
src/main/java/com/loan/system/repository/LoanRepository.java

@@ -1,9 +1,7 @@
 package com.loan.system.repository;
 
+import com.loan.system.domain.dto.query.LoanCaseQueryDTO;
 import com.loan.system.domain.entity.LoanCase;
-import com.loan.system.domain.entity.User;
-import com.loan.system.domain.vo.LoanCaseSimpleVO;
-import com.loan.system.domain.vo.LoanCaseVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -12,7 +10,6 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -98,4 +95,18 @@ public interface LoanRepository extends JpaRepository<LoanCase,Long> {
     @Transactional
     @Query("update LoanCase set otherId1 = ?1 , otherId2 = ?2  where id = ?3")
     void updateCustomersById(Long customerId1, Long customerId2, Long caseId);
+
+    @Query("SELECT lc FROM LoanCase lc WHERE " +
+           "(:#{#query.customerId} IS NULL OR lc.customerId = :#{#query.customerId}) AND " +
+           "(:#{#query.businessType} IS NULL OR lc.businessType = :#{#query.businessType}) AND " +
+           "(:#{#query.businessAttrs} IS NULL OR lc.businessAttrs = :#{#query.businessAttrs}) AND " +
+           "(:#{#query.channelName} IS NULL OR lc.channelName = :#{#query.channelName}) AND " +
+           "(:#{#query.isComplete} IS NULL OR lc.isComplete = :#{#query.isComplete}) AND " +
+           "lc.isDelete = COALESCE(:isDelete, false)")
+    Page<LoanCase> findByQueryConditions(LoanCaseQueryDTO query,
+                                         Boolean isDelete,
+                                         Pageable pageable);
+
+    @Query("SELECT l FROM LoanCase l WHERE l.id = :caseId AND l.isDelete = :isDelete")
+    LoanCase findByIdAndIsDelete(Long caseId,Boolean isDelete);
 }

+ 2 - 2
src/main/java/com/loan/system/repository/PawnTicketRepository.java

@@ -24,8 +24,8 @@ public interface PawnTicketRepository extends JpaRepository<PawnTicketInfo,Long>
 
     @Modifying
     @Transactional
-    @Query("update PawnTicketInfo p set p.redeemTicketNo = ?1 where p.pawnTicketNo = ?2 and p.isDelete = ?3")
-    void updateRedeemTicketNoByPawnTicketNoAndIsDelete(String redeemTicketNo, String pawnTicketNo, boolean b);
+    @Query("update PawnTicketInfo p set p.redeemTicketNo = ?1 ,p.endTime = ?4 where p.pawnTicketNo = ?2 and p.isDelete = ?3")
+    void updateRedeemTicketNoByPawnTicketNoAndIsDelete(String redeemTicketNo, String pawnTicketNo,String endTime, boolean b);
 
     @Modifying
     @Transactional

+ 14 - 0
src/main/java/com/loan/system/repository/RecommenderRepository.java

@@ -1,8 +1,11 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.BizRecommenderDTO;
+import com.loan.system.domain.dto.query.RecommenderQueryDTO;
 import com.loan.system.domain.entity.BizRecommender;
 import com.loan.system.domain.entity.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -37,4 +40,15 @@ public interface RecommenderRepository extends JpaRepository<BizRecommender,Long
 
     @Query(value = "SELECT r FROM BizRecommender r WHERE r.id= :id and r.isDelete = :isDelete")
     BizRecommender findByIdAndIsDelete(Long id,boolean isDelete);
+
+    @Query(value = "SELECT r FROM BizRecommender r WHERE r.isDelete = :isDelete")
+    Page<BizRecommender> findAllAndIsDelete(Boolean isDelete,Pageable pageable);
+
+    @Query("SELECT lc FROM BizRecommender lc WHERE " +
+            "(:#{#query.recommenderName} IS NULL OR lc.recommenderName like %:#{#query.recommenderName}%) AND " +
+            "(:#{#query.channelName} IS NULL OR lc.channelName = :#{#query.channelName}) AND " +
+            "(:#{#query.mobile} IS NULL OR lc.mobile like %:#{#query.mobile}%) AND " +
+            "(:#{#query.group} IS NULL OR lc.group = :#{#query.group}) AND " +
+            "lc.isDelete = false ")
+    Page<BizRecommender> findByQuery(RecommenderQueryDTO query, Pageable pageable);
 }

+ 8 - 0
src/main/java/com/loan/system/repository/StepRepository.java

@@ -80,4 +80,12 @@ public interface StepRepository extends JpaRepository<Step,Long> {
 
     @Query("select s from Step s where s.caseId in ?1 and s.code = ?2")
     List<Step> findByCaseIdsAndCode(List<Long> ids, Integer stepCode);
+
+    @Query("select s from Step s where s.caseId = ?2 and s.code in ?1")
+    List<Step> findByStepCodesAndCaseId(List<Integer> list, Long caseId);
+
+    @Modifying
+    @Transactional
+    @Query("update Step s set s.status = ?1,s.updateTime = ?4 where s.parentCode = ?2 and s.caseId = ?3")
+    void updateStatusByCaseIdAndParentCode(String msg, int code, Long caseId, String format);
 }

+ 13 - 1
src/main/java/com/loan/system/repository/UserRepository.java

@@ -1,10 +1,12 @@
 package com.loan.system.repository;
 
 import com.loan.system.domain.dto.UserDTO;
+import com.loan.system.domain.dto.query.UserQueryDTO;
 import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.User;
 import com.loan.system.domain.vo.UserVO;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
@@ -75,4 +77,14 @@ public interface UserRepository extends JpaRepository<User,Long> {
 
     @Query("select u from User u where u.id in ?1 and u.isDelete = ?2")
     List<User> findByIdsAndIsDelete(List<Long> userIds, boolean b);
-}
+
+    @Query("SELECT lc FROM User lc WHERE " +
+            "(:#{#query.id} IS NULL OR lc.id = :#{#query.id}) AND " +
+            "(:#{#query.realName} IS NULL OR lc.realName like %:#{#query.realName}%) AND " +
+            "(:#{#query.mobile} IS NULL OR lc.mobile like %:#{#query.mobile}%) AND " +
+            "(:#{#query.role} IS NULL OR lc.role like %:#{#query.role}%)")
+    Page<User> findAllByQuery(UserQueryDTO query, Pageable pageable);
+
+    @Query("select u.openid from User u where u.isDelete = ?1")
+    List<String> findAllOpenIdAndIsDelete(Boolean isDelete);
+}

+ 9 - 6
src/main/java/com/loan/system/service/ApprovalService.java

@@ -4,8 +4,11 @@ import com.loan.system.domain.dto.ApprovalDTO;
 import com.loan.system.domain.dto.ApprovalRecordDTO;
 import com.loan.system.domain.dto.PreApprovalDTO;
 import com.loan.system.domain.entity.ApprovalRecord;
+import com.loan.system.domain.entity.Step;
 import com.loan.system.domain.vo.ApprovalRecordVO;
 import com.loan.system.domain.vo.ComplementVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
+import com.loan.system.domain.vo.StepVO;
 
 import java.util.List;
 
@@ -30,17 +33,17 @@ public interface ApprovalService {
     List<ApprovalRecordVO> findByCollateralAndCaseIdAndIsDelete(Integer stepCode, Long caseId, boolean isDelete);
 
     //controller
-    void preApprovalSavePrimary(Long userId, Long caseId, PreApprovalDTO preApprovalDTO);
+    void preApprovalSavePrimary(Long userId, LoanCaseSimpleVO loanCaseSimpleVO, PreApprovalDTO preApprovalDTO, StepVO step);
 
-    void preApprovalReject(Long caseId, Long userId, PreApprovalDTO preApprovalDTO);
+    void preApprovalReject(LoanCaseSimpleVO loanCaseSimpleVO, Long userId, PreApprovalDTO preApprovalDTO);
 
-    void approvalPass1(ApprovalDTO approvalDTO);
+    void approvalPass1(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO);
 
-    void approvalReject1( ApprovalDTO approvalDTO);
+    void approvalReject1(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO);
 
-    void approvalPass2(ApprovalDTO approvalDTO);
+    void approvalPass2(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO);
 
-    void approvalReject2(ApprovalDTO approvalDTO);
+    void approvalReject2(LoanCaseSimpleVO loanCaseSimpleVO,ApprovalDTO approvalDTO);
 
     ComplementVO<List<ApprovalRecordVO>> getApprovalDetail(Long caseId);
 

+ 11 - 4
src/main/java/com/loan/system/service/CollateralPlanService.java

@@ -6,17 +6,24 @@ import com.loan.system.domain.entity.CollateralPlan;
 import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.ChannelPushVO;
 import com.loan.system.domain.vo.CollateralPlanVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
 import com.loan.system.utils.ResultUtil;
 
 import java.util.List;
 
 public interface CollateralPlanService {
     void save(CollateralPlan collateralPlan);
+
     CollateralPlan findByCollateralPlanId(Long id);
+
     void logic_delete(Long id);
+
     List<CollateralPlan> findByCaseIdAndIsDelete(Long caseId, boolean isDelete);
+
     void updateCollateralStatusById(Long collateralId, String status);
+
     List<CollateralPlan> findByCollateralIdAndIsDelete(Long collateralId);
+
     CollateralPlan findById(Long id);
 
     void updatePlanById(CollateralPlan collateralPlan, Long planId);
@@ -30,13 +37,13 @@ public interface CollateralPlanService {
     //controller
     List<CollateralPlanVO> listCollateralPlans(Long caseId, String flag);
     
-    Result approvalCollateralPlan(CollateralPlan collateralPlan, CollateralPlanApprovalDTO collateralPlanApprovalDTO, Long recordId);
+    Result approvalCollateralPlan(LoanCaseSimpleVO loanCaseSimpleVO,CollateralPlan collateralPlan, CollateralPlanApprovalDTO collateralPlanApprovalDTO, Long recordId);
 
-    void createCollateralPlan(CollateralPlanDTO collateralPlanDTO, Long planId, Boolean isComplete);
+    void createCollateralPlan(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlanDTO collateralPlanDTO, Long planId, Boolean isComplete);
 
-    void warehouseCollateral(CollateralPlan collateralPlan, String comments);
+    void warehouseCollateral(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlan collateralPlan, String comments);
 
-    void outboundCollateral(CollateralPlan collateralPlan, String comments);
+    void outboundCollateral(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlan collateralPlan, String comments);
 
 
 }

+ 6 - 0
src/main/java/com/loan/system/service/CollateralService.java

@@ -1,7 +1,9 @@
 package com.loan.system.service;
 
 import com.loan.system.domain.dto.CollateralDTO;
+import com.loan.system.domain.dto.query.CollateralQueryDTO;
 import com.loan.system.domain.entity.Collateral;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.ChannelPushVO;
 import com.loan.system.domain.vo.CollateralVO;
 
@@ -31,4 +33,8 @@ public interface CollateralService {
     boolean existsById(Long collateralId);
 
     void updateOperateStatusByIds(List<Long> collateralIds, String msg);
+    
+    Result getCollaterals(Integer pageNum, Integer pageSize);
+    
+    Result getCollateralsByKey(CollateralQueryDTO collateralQueryDTO, Integer pageNum, Integer pageSize);
 }

+ 2 - 0
src/main/java/com/loan/system/service/ContractAndCollateralService.java

@@ -18,4 +18,6 @@ public interface ContractAndCollateralService {
     List<ContractAndCollateral> listByContractId(Long contractId);
 
     void addBatch(Iterator<Map.Entry<Integer, List<Integer>>> iterator, List<Contract> contracts, List<Long> collateralIds, Long caseId);
+
+    List<Long> findCollateralIdsByContractId(Long id);
 }

+ 13 - 2
src/main/java/com/loan/system/service/ContractService.java

@@ -2,9 +2,12 @@ package com.loan.system.service;
 
 import com.loan.system.domain.dto.ContractDTO;
 import com.loan.system.domain.dto.ContractWrapperDTO;
+import com.loan.system.domain.dto.query.ContractQueryDTO;
 import com.loan.system.domain.entity.Contract;
 import com.loan.system.domain.pojo.ContractInformation;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.ContractVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
 import io.swagger.models.Contact;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.transaction.annotation.Transactional;
@@ -49,9 +52,9 @@ public interface ContractService {
     void updateContractStatus(Contract contract, Long caseId);
 
     //controller
-    void completeContract(Long caseId , ContractWrapperDTO contractWrapper);
+    void completeContract(LoanCaseSimpleVO loanCaseSimpleVO, ContractWrapperDTO contractWrapper);
 
-    void getContractInformation(HttpServletResponse response, Long caseId, ContractVO contractVO);
+    void getContractInformation(HttpServletResponse response, Long caseId, Long contractId);
 
     ContractInformation getContractInformationById(Long caseId, Long contractId);
 
@@ -64,4 +67,12 @@ public interface ContractService {
     Double getActualTotalAmount(Long caseId);
 
     void updateIsDisbursementById(Long contractId, boolean isDisbursement);
+
+    Result findAllContract(Integer pageNum, Integer pageSize);
+
+    Result findAllContractByQuery(Integer pageNum, Integer pageSize, ContractQueryDTO contractQueryDTO);
+
+    void deleteContractById(Long id);
+
+    void updateIsDisbursementByCaseId(Long caseId);
 }

+ 7 - 1
src/main/java/com/loan/system/service/CustomerService.java

@@ -1,8 +1,10 @@
 package com.loan.system.service;
 
 import com.loan.system.domain.dto.CustomerDTO;
+import com.loan.system.domain.dto.query.CustomerQueryDTO;
 import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.User;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.CustomerVO;
 
 import java.util.List;
@@ -37,7 +39,7 @@ public interface CustomerService {
 
     void updateInfoByOpenId(CustomerDTO customerDTO);
 
-    List<Customer> getAllCustomersByAdmin(Integer pageNum, Integer pageSize);
+    Result getAllCustomersByAdmin(Integer pageNum, Integer pageSize);
 
     void deleteCustomerByLogic(Long id);
 
@@ -53,6 +55,10 @@ public interface CustomerService {
 
     List<Customer> findByCustomerNameAndIsDelete(String customerName, boolean b);
 
+    Result listCustomersByQuery(CustomerQueryDTO queryDTO, Integer pageNum, Integer pageSize);
+
+    List<CustomerVO> findByIdsInAndIsDelete(Iterable<Long> ids, boolean isDelete);
+
     //Controller
 
 }

+ 33 - 0
src/main/java/com/loan/system/service/DetailService.java

@@ -0,0 +1,33 @@
+package com.loan.system.service;
+
+import com.loan.system.domain.dto.DetailDTO;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.vo.DisbursementDetails;
+import com.loan.system.domain.vo.LoanCaseDetails;
+import com.loan.system.domain.vo.LoanCaseStatistic;
+import com.loan.system.domain.vo.RepaymentDetails;
+
+import javax.servlet.http.HttpServletResponse;
+import java.time.LocalDate;
+import java.util.List;
+
+public interface DetailService {
+
+    Result getArrangeReport(LocalDate begin);
+
+    Result getLoanCaseReport(LocalDate begin, LocalDate end);
+
+    void exportLoanCaseReport(DetailDTO<LoanCaseStatistic> detailDTO, LocalDate begin, LocalDate end, HttpServletResponse response);
+
+    Result getAccountReport(Long caseId, Integer pageNum, Integer pageSize);
+
+    void exportAccountReport(List<LoanCaseDetails> loanCaseDetails, Integer begin, Integer end, HttpServletResponse response);
+
+    Result getDisbursementReport(Long caseId, Integer pageNum, Integer pageSize);
+
+    void exportDisbursementReport(List<DisbursementDetails> disbursementDetails, Integer begin, Integer end, HttpServletResponse response);
+
+    Result repaymentReport(Long caseId, int begin, Integer pageSize);
+
+    void exportRepaymentReport(List<RepaymentDetails> repaymentDetails, Integer begin, Integer end, HttpServletResponse response);
+}

+ 8 - 0
src/main/java/com/loan/system/service/DictionaryService.java

@@ -2,7 +2,9 @@ package com.loan.system.service;
 
 import com.loan.system.domain.dto.DictDataDTO;
 import com.loan.system.domain.dto.DictTypeDTO;
+import com.loan.system.domain.dto.query.DictDataQueryDTO;
 import com.loan.system.domain.entity.*;
+import com.loan.system.domain.pojo.Result;
 
 import java.util.List;
 import java.util.Map;
@@ -19,12 +21,16 @@ public interface DictionaryService {
 
     List<DictData> getAllDictData(boolean status);
 
+    Result listDictData(Integer pageNum, Integer pageSize);
+
     List<DictData> listDictData();
 
     void addDictData(DictDataDTO dataDTO);
 
     void updateDictData(DictDataDTO dataDTO,Long id);
 
+    Result listDictType(Integer pageNum, Integer pageSize);
+
     List<DictType> listDictType();
 
     void addDictType(DictTypeDTO dictTypeDTO);
@@ -32,4 +38,6 @@ public interface DictionaryService {
     void updateDictType(DictTypeDTO dictTypeDTO, Long id);
 
     Map<String, String> contractMap();
+
+    Result listDictDataByQuery(Integer pageNum, Integer pageSize, DictDataQueryDTO query);
 }

+ 9 - 6
src/main/java/com/loan/system/service/DisbursementService.java

@@ -8,6 +8,7 @@ import com.loan.system.domain.entity.Disbursement;
 import com.loan.system.domain.pojo.DateAndAmountPOJO;
 import com.loan.system.domain.vo.DisbursementDetailVO;
 import com.loan.system.domain.vo.DisbursementVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
 
 import java.util.List;
 import java.util.Map;
@@ -37,15 +38,15 @@ public interface DisbursementService {
     String getLoanTime(Long caseId);
 
     //controller
-    void addDisbursementPlan(DisbursementDTO disbursementDTO);
+    void addDisbursementPlan(LoanCaseSimpleVO loanCaseSimpleVO,DisbursementDTO disbursementDTO);
 
-    void disbursementPlanApproval(ApprovalRecordDTO approvalRecordDTO, Long chargeId,Long assistantId);
+    void disbursementPlanApproval(LoanCaseSimpleVO loanCaseSimpleVO,ApprovalRecordDTO approvalRecordDTO, Long chargeId,Long assistantId);
 
-    void disbursementPlanApprovalReject(ApprovalRecordDTO approvalRecordDTO);
+    void disbursementPlanApprovalReject(LoanCaseSimpleVO loanCaseSimpleVO,ApprovalRecordDTO approvalRecordDTO);
 
-    void commitDisbursement(DisbursementStartDTO disbursementStartDTO,Boolean isComplete);
+    void commitDisbursement(LoanCaseSimpleVO loanCaseSimpleVO,DisbursementStartDTO disbursementStartDTO,Boolean isComplete);
 
-    void disbursementApproval(ApprovalRecordDTO approvalRecordDTO, String decision);
+    void disbursementApproval(LoanCaseSimpleVO loanCaseSimpleVO,ApprovalRecordDTO approvalRecordDTO, String decision);
 
     void financeDisbursement(List<DisbursementRecordDTO> disbursementRecordDTOs, Long caseId, Double currentAmount);
 
@@ -55,5 +56,7 @@ public interface DisbursementService {
 
     Map<Long ,List<DateAndAmountPOJO>> getDateAndAmount(Long caseId);
 
-    void financeApproval(ApprovalRecordDTO approvalRecordDTO, String decision);
+    void financeApproval(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalRecordDTO approvalRecordDTO, String decision);
+
+    void completeDisburse(Long caseId);
 }

+ 19 - 1
src/main/java/com/loan/system/service/DocumentService.java

@@ -1,10 +1,18 @@
 package com.loan.system.service;
 
+import com.loan.system.domain.dto.BatchDownloadDTO;
 import com.loan.system.domain.dto.DocumentDTO;
+import com.loan.system.domain.dto.query.DocumentQueryDTO;
 import com.loan.system.domain.entity.Document;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.DocumentVO;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 
 public interface DocumentService {
     List<DocumentVO> findByCaseId(Long caseId);
@@ -19,7 +27,17 @@ public interface DocumentService {
 
     void deleteFileById(Long id);
 
-    List<Document> findAll();
+    void deleteFileByIds(List<Long> ids);
+
+    Result findAll(Integer pageNum, Integer pageSize);
 
     List<DocumentVO> findByFileTypesAndCaseId(List<String> fileTypes, Long caseId);
+
+    Result uploadFileToOss(MultipartFile file, Long caseId, String fileType, Map<String, String> isDelete);
+
+    void downloadFileFromOss(Long caseId,String fileType,String fileName, HttpServletResponse response) ;
+
+    void batchDownloadFilesFromOss(BatchDownloadDTO batchDownloadDTO, HttpServletResponse response) throws IOException;
+
+    Result queryFiles(Integer pageNum, Integer pageSize, DocumentQueryDTO documentQueryDTO);
 }

+ 82 - 36
src/main/java/com/loan/system/service/Impl/ApprovalServiceImpl.java

@@ -6,15 +6,15 @@ import com.loan.system.domain.dto.ApprovalDTO;
 import com.loan.system.domain.dto.ApprovalRecordDTO;
 import com.loan.system.domain.dto.PreApprovalDTO;
 import com.loan.system.domain.entity.ApprovalRecord;
+import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.Step;
 import com.loan.system.domain.entity.User;
 import com.loan.system.domain.enums.DecisionEnum;
+import com.loan.system.domain.enums.RoleEnum;
 import com.loan.system.domain.enums.StepEnum;
 import com.loan.system.domain.enums.StepPropertyEnum;
-import com.loan.system.domain.vo.ApprovalRecordVO;
-import com.loan.system.domain.vo.ComplementVO;
-import com.loan.system.domain.vo.StepVO;
-import com.loan.system.domain.vo.UserVO;
+import com.loan.system.domain.pojo.TemplateMessage;
+import com.loan.system.domain.vo.*;
 import com.loan.system.repository.ApproveRecordRepository;
 import com.loan.system.service.*;
 import com.loan.system.utils.RedisData;
@@ -26,8 +26,7 @@ import org.springframework.util.ObjectUtils;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -39,6 +38,8 @@ public class ApprovalServiceImpl implements ApprovalService {
     private final StepService stepService;
     private final StringRedisTemplate stringRedisTemplate;
     private final ContractSeqService contractSeqService;
+    private final WxService wxService;
+    private final CustomerService customerService;
     @Override
     public ApprovalRecord addApprovalRecord(Long caseId,Integer stepCode ,String  decision ,String  comments) {
         ApprovalRecord approvalRecord = new ApprovalRecord();
@@ -122,7 +123,8 @@ public class ApprovalServiceImpl implements ApprovalService {
     }
 
     @Override
-    public void preApprovalSavePrimary(Long userId, Long caseId, PreApprovalDTO preApprovalDTO) {
+    public void preApprovalSavePrimary(Long userId, LoanCaseSimpleVO loanCaseSimpleVO, PreApprovalDTO preApprovalDTO, StepVO step) {
+        Long caseId = loanCaseSimpleVO.getId();
         //添加记录
         addApprovalRecord(caseId,StepPropertyEnum.PRE_TRIAL.getCode(),DecisionEnum.PASS.getMsg(),preApprovalDTO.getComments());
 
@@ -131,21 +133,27 @@ public class ApprovalServiceImpl implements ApprovalService {
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.PRE_TRIAL_PARENT.getCode(),caseId);
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
         stepService.tryStartStep(StepPropertyEnum.PRE_TRIAL.getCode(),caseId);
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+
+        //TODO:微信推送预审通过消息和通知下一环节:所有审批人员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.APPROVAL.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void preApprovalReject(Long caseId, Long userId, PreApprovalDTO preApprovalDTO) {
+    public void preApprovalReject(LoanCaseSimpleVO loanCaseSimpleVO, Long userId, PreApprovalDTO preApprovalDTO) {
+        Long caseId = loanCaseSimpleVO.getId();
         //添加记录
         addApprovalRecord(caseId,StepPropertyEnum.PRE_TRIAL.getCode(),DecisionEnum.REJECT.getMsg(),preApprovalDTO.getComments());
         //TODO:添加驳回记录(在受理环节显示)
@@ -158,21 +166,12 @@ public class ApprovalServiceImpl implements ApprovalService {
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.PRE_TRIAL_PARENT.getCode(),caseId);
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(),StepPropertyEnum.PRE_TRIAL.getCode(),caseId);
 
-        //TODO:微信推送预审拒绝消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(caseId);
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信推送预审拒绝消息和通知下一环节:给上环节的负责人
+        sendToSales(loanCaseSimpleVO);
     }
 
     @Override
-    public void approvalPass1( ApprovalDTO approvalDTO) {
+    public void approvalPass1(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO) {
         Long caseId = approvalDTO.getCaseId();
         Long userId = BaseContext.getCurrentId();
         addApprovalRecord(caseId, StepPropertyEnum.APPROVAL.getCode(), DecisionEnum.PASS.getMsg(), approvalDTO.getComments());
@@ -181,11 +180,25 @@ public class ApprovalServiceImpl implements ApprovalService {
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.APPROVAL.getCode(), caseId);
         stepService.tryStartStep(StepPropertyEnum.APPROVAL.getCode(), caseId);
 
-        //TODO:微信推送预审拒绝消息和通知下一环节
+        //TODO:微信推送预审拒绝消息和通知下一环节:除自身外的审批员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.APPROVAL_2.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getId().equals(BaseContext.getCurrentId())) continue;
+            if (user.getOpenid() != null) wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void approvalReject1(ApprovalDTO approvalDTO) {
+    public void approvalReject1(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO) {
         Long caseId = approvalDTO.getCaseId();
         Long userId = BaseContext.getCurrentId();
         addApprovalRecord(caseId, StepPropertyEnum.APPROVAL.getCode(), DecisionEnum.REJECT.getMsg(), approvalDTO.getComments());
@@ -202,10 +215,11 @@ public class ApprovalServiceImpl implements ApprovalService {
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.APPROVAL.getCode(), caseId);
 
         //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
+        sendToSales(loanCaseSimpleVO);
     }
 
     @Override
-    public void approvalPass2(ApprovalDTO approvalDTO) {
+    public void approvalPass2(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO) {
         Long caseId = approvalDTO.getCaseId();
         Long userId = BaseContext.getCurrentId();
         addApprovalRecord(caseId, StepPropertyEnum.APPROVAL_2.getCode(), DecisionEnum.PASS.getMsg(), approvalDTO.getComments());
@@ -218,11 +232,25 @@ public class ApprovalServiceImpl implements ApprovalService {
         //生成合同编号
         contractSeqService.generateContractSeq(caseId);
 
-        //TODO:微信推送预审拒绝消息和通知下一环节
+        //TODO:微信推送预审拒绝消息和通知下一环节:通知业务员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.LEAD_SALES.getMsg(), RoleEnum.ASSIST_SALES.getMsg()), false);
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.CONTRACT_SIGN.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        for (User user : users) {
+            if (user.getId().equals(BaseContext.getCurrentId())) continue;
+            if (user.getOpenid() != null) wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void approvalReject2(ApprovalDTO approvalDTO) {
+    public void approvalReject2(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalDTO approvalDTO) {
         Long caseId = approvalDTO.getCaseId();
         Long userId = BaseContext.getCurrentId();
         addApprovalRecord(caseId, StepPropertyEnum.APPROVAL_2.getCode(), DecisionEnum.REJECT.getMsg(), approvalDTO.getComments());
@@ -239,6 +267,7 @@ public class ApprovalServiceImpl implements ApprovalService {
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.APPROVAL_2.getCode(), caseId);
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.APPROVAL.getCode(), caseId);
         //TODO微信推送审批驳回消息和通知重新受理(到业务受理)
+        sendToSales(loanCaseSimpleVO);
     }
 
     @Override
@@ -299,4 +328,21 @@ public class ApprovalServiceImpl implements ApprovalService {
         return approvalRecordVOS;
     }
 
+    private void sendToSales(LoanCaseSimpleVO loanCaseSimpleVO){
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getId())));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.BUSINESS_ACCEPT.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        StepVO step = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), loanCaseSimpleVO.getId());
+        if (step != null && step.getUserId1() != null){
+            User user = userService.findByIdAndIsDelete(step.getUserId1());
+            if (user.getOpenid() != null) wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
+    }
+
 }

+ 84 - 12
src/main/java/com/loan/system/service/Impl/CollateralPlanServiceImpl.java

@@ -4,14 +4,13 @@ import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.context.BaseContext;
 import com.loan.system.domain.dto.CollateralPlanApprovalDTO;
 import com.loan.system.domain.dto.CollateralPlanDTO;
-import com.loan.system.domain.entity.ApprovalRecord;
-import com.loan.system.domain.entity.BizRecommender;
-import com.loan.system.domain.entity.CollateralPlan;
-import com.loan.system.domain.entity.Customer;
+import com.loan.system.domain.entity.*;
 import com.loan.system.domain.enums.DecisionEnum;
+import com.loan.system.domain.enums.RoleEnum;
 import com.loan.system.domain.enums.StepEnum;
 import com.loan.system.domain.enums.StepPropertyEnum;
 import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.pojo.TemplateMessage;
 import com.loan.system.domain.vo.*;
 import com.loan.system.exception.DescribeException;
 import com.loan.system.repository.CollateralPlanRepository;
@@ -25,9 +24,7 @@ import org.springframework.util.ObjectUtils;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.loan.system.domain.enums.DecisionEnum.*;
@@ -44,6 +41,8 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
     private final CollateralService collateralService;
     private final UserService userService;
     private final LocationDatumService locationDatumService;
+    private final WxService wxService;
+    private final CustomerService customerService;
 
     @Override
     public void save(CollateralPlan collateralPlan) {
@@ -149,7 +148,7 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
     }
 
     @Override
-    public Result approvalCollateralPlan(CollateralPlan collateralPlan, CollateralPlanApprovalDTO collateralPlanApprovalDTO, Long recordId) {
+    public Result approvalCollateralPlan(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlan collateralPlan, CollateralPlanApprovalDTO collateralPlanApprovalDTO, Long recordId) {
         Long caseId = collateralPlan.getCaseId();
 
         Integer stepCode = collateralPlan.getFlag().equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.APPROVAL_ASSIGNMENT.getCode() : StepPropertyEnum.APPROVAL_ASSIGNMENT_2.getCode();
@@ -186,6 +185,20 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
             stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), stepCode,caseId);
             stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), stepCode2,caseId);
 
+            String stepName = collateralPlan.getFlag().equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.PLAN_SUBMISSION.getLabel() : StepPropertyEnum.PLAN_SUBMISSION_2.getLabel();
+            TemplateMessage message = new TemplateMessage();
+            Map<String, Map<String, String>> data = new HashMap<>();
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", stepName));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+            Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+            data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+            message.setData(data);
+            User user = userService.findByIdAndIsDelete(collateralPlan.getUserId());
+            if (user != null && user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+
             return ResultUtil.success("success","计划已拒绝");
             //同意计划
         }
@@ -214,11 +227,25 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
         stepService.tryStartStep(stepCode,caseId);
 
         //TODO 改状态+微信推送下一个节点业务员
+        String stepName = collateralPlan.getFlag().equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.EVIDENCE_CONFIRMATION.getLabel() : StepPropertyEnum.DELIVERY_CONFIRMATION.getLabel();
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", stepName));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        User user = userService.findByIdAndIsDelete(collateralPlan.getOperatorId());
+        if (user != null && user.getOpenid() != null)
+            wxService.sendTemplateMessage(user.getOpenid(), message);
+
         return ResultUtil.success("success","计划已通过");
     }
 
     @Override
-    public void createCollateralPlan(CollateralPlanDTO collateralPlanDTO, Long planId, Boolean isComplete) {
+    public void createCollateralPlan(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlanDTO collateralPlanDTO, Long planId, Boolean isComplete) {
         Long caseId = collateralPlanDTO.getCaseId();
         Long userid = BaseContext.getCurrentId();
         CollateralPlan collateralPlan = CollateralPlan.builder()
@@ -268,7 +295,8 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
 
         //更新状态
         Integer stepCode = collateralPlanDTO.getFlag().equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.PLAN_SUBMISSION.getCode() : StepPropertyEnum.PLAN_SUBMISSION_2.getCode();
-        //String stepName2 = collateralPlanDTO.getFlag().equals("入库") ? StepPropertyEnum.APPROVAL_ASSIGNMENT.getLabel() : StepPropertyEnum.APPROVAL_ASSIGNMENT_2.getLabel();
+        //下环节名称
+        String stepName = collateralPlanDTO.getFlag().equals(ENTER_WAREHOUSE.getMsg()) ? StepPropertyEnum.APPROVAL_ASSIGNMENT.getLabel() : StepPropertyEnum.APPROVAL_ASSIGNMENT_2.getLabel();
 
         stepService.updateUserId1ByCaseIdAndStepCode(stepCode,userid,caseId);
 
@@ -280,10 +308,26 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
 
         }
         stepService.tryStartStep(stepCode,caseId);
+
+        //TODO:微信推送计划提交消息和通知下一环节:审批员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", stepName));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void warehouseCollateral(CollateralPlan collateralPlan, String comments) {
+    public void warehouseCollateral(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlan collateralPlan, String comments) {
         Long caseId = collateralPlan.getCaseId();
         Long userId= BaseContext.getCurrentId();
         Long id = collateralPlan.getId();
@@ -323,10 +367,25 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
 //            }
         }
         stepService.tryStartStep(StepPropertyEnum.EVIDENCE_CONFIRMATION.getCode(),caseId);
+
+        stepService.tryStartStep(StepPropertyEnum.DELIVERY_CONFIRMATION.getCode(),caseId);
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", "取证完成,请进行下一环节"));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<String> openIds = userService.listOpenId();
+        for (String openId : openIds) {
+            wxService.sendTemplateMessage(openId, message);
+        }
     }
 
     @Override
-    public void outboundCollateral(CollateralPlan collateralPlan, String comments) {
+    public void outboundCollateral(LoanCaseSimpleVO loanCaseSimpleVO, CollateralPlan collateralPlan, String comments) {
         Long caseId = collateralPlan.getCaseId();
         Long userId= BaseContext.getCurrentId();
         Long id = collateralPlan.getId();
@@ -367,6 +426,19 @@ public class CollateralPlanServiceImpl implements CollateralPlanService {
 //            }
         }
         stepService.tryStartStep(StepPropertyEnum.DELIVERY_CONFIRMATION.getCode(),caseId);
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", "送证完成,请进行下一环节"));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<String> openIds = userService.listOpenId();
+        for (String openId : openIds) {
+            wxService.sendTemplateMessage(openId, message);
+        }
     }
 
     private List<Long> getCollateralIds(String ids){

+ 29 - 0
src/main/java/com/loan/system/service/Impl/CollateralServiceImpl.java

@@ -2,16 +2,25 @@ package com.loan.system.service.Impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.domain.dto.CollateralDTO;
+import com.loan.system.domain.dto.query.CollateralQueryDTO;
 import com.loan.system.domain.entity.Collateral;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.ChannelPushVO;
 import com.loan.system.domain.vo.CollateralVO;
 import com.loan.system.repository.CollateralRepository;
 import com.loan.system.service.CollateralService;
+import com.loan.system.utils.ResultUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 
+import javax.persistence.criteria.Predicate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.List;
 
 @Service
@@ -89,4 +98,24 @@ public class CollateralServiceImpl implements CollateralService {
     public Collateral findCollateralById(Long id){
         return collateralRepository.findCollateralById(id);
     }
+    
+    @Override
+    public Result getCollaterals(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
+        Page<Collateral> data = collateralRepository.findAllAndIsDelete(false, pageable);
+
+        List<CollateralVO> collateralVOList = BeanUtil.copyToList(data.getContent(), CollateralVO.class);
+        
+        return ResultUtil.success(data.getTotalElements(), collateralVOList);
+    }
+    
+    @Override
+    public Result getCollateralsByKey(CollateralQueryDTO collateralQueryDTO, Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
+        Page<Collateral> data = collateralRepository.findByQueryAndIsDelete(collateralQueryDTO, pageable);
+
+        List<CollateralVO> collateralVOList = BeanUtil.copyToList(data.getContent(), CollateralVO.class);
+        
+        return ResultUtil.success(data.getTotalElements(), collateralVOList);
+    }
 }

+ 5 - 0
src/main/java/com/loan/system/service/Impl/ContractAndCollateralServiceImpl.java

@@ -73,4 +73,9 @@ public class ContractAndCollateralServiceImpl implements ContractAndCollateralSe
 
         contractAndCollateralRepository.saveAll(contractAndCollaterals);
     }
+
+    @Override
+    public List<Long> findCollateralIdsByContractId(Long id) {
+       return  contractAndCollateralRepository.findCollateralIdsByContractIdsAndIsDelete(id,false);
+    }
 }

+ 177 - 73
src/main/java/com/loan/system/service/Impl/ContractServiceImpl.java

@@ -4,28 +4,28 @@ import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.context.BaseContext;
 import com.loan.system.domain.dto.ContractDTO;
 import com.loan.system.domain.dto.ContractWrapperDTO;
-import com.loan.system.domain.entity.Contract;
-import com.loan.system.domain.entity.Customer;
-import com.loan.system.domain.entity.DictData;
-import com.loan.system.domain.entity.Document;
+import com.loan.system.domain.dto.query.ContractQueryDTO;
+import com.loan.system.domain.entity.*;
 import com.loan.system.domain.enums.*;
 import com.loan.system.domain.pojo.ContractInformation;
-import com.loan.system.domain.vo.ContractBankInfoVO;
-import com.loan.system.domain.vo.ContractVO;
-import com.loan.system.domain.vo.CustomerVO;
-import com.loan.system.domain.vo.LoanCaseSimpleVO;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.pojo.TemplateMessage;
+import com.loan.system.domain.vo.*;
 import com.loan.system.exception.DescribeException;
 import com.loan.system.repository.ContractRepository;
 import com.loan.system.service.*;
+import com.loan.system.utils.NumberToChineseUtil;
 import com.loan.system.utils.PoiWordUtil;
-import io.swagger.models.Contact;
+import com.loan.system.utils.ResultUtil;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Lazy;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
-import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -53,6 +53,10 @@ public class ContractServiceImpl implements ContractService {
     private final StepService stepService;
     private final EsignService esignService;
     private final ContractBankInfoService  contractBankInfoService;
+    private final WxService wxService;
+    private final UserService userService;
+    private final CollateralService collateralService;
+    private final ContractAndCollateralService contractAndCollateralService;
 
     @Override
     public Contract saveContract(ContractDTO contractDTO) {
@@ -106,47 +110,7 @@ public class ContractServiceImpl implements ContractService {
     @Override
     public List<ContractVO> findContractByCaseId(Long caseId) {
         List<Contract> contracts = contractRepository.findByCaseIdAndIsDelete(caseId, false);
-        List<ContractVO> contractVOS = new ArrayList<>();
-        for (Contract contract : contracts){
-            ContractVO contractVO = BeanUtil.copyProperties(contract, ContractVO.class);
-            contractVO.setEsignFlow(esignService.findByContractIdAndNormal(contract.getId()));
-
-            Customer customer = customerService.findByIdAndIsDelete(contract.getCustomerId());
-            contractVO.setCustomer(BeanUtil.copyProperties(customer, CustomerVO.class));
-            Customer customer1 = customerService.findByIdAndIsDelete(contract.getCustomerId1());
-            contractVO.setCustomer1(BeanUtil.copyProperties(customer1, CustomerVO.class));
-            Customer customer2 = customerService.findByIdAndIsDelete(contract.getCustomerId2());
-            contractVO.setCustomer2(BeanUtil.copyProperties(customer2, CustomerVO.class));
-            String customerNames = "";
-            if (!ObjectUtils.isEmpty(customer)) customerNames += customer.getName();
-            if (!ObjectUtils.isEmpty(customer1)) customerNames += "," + customer1.getName();
-            if (!ObjectUtils.isEmpty(customer2)) customerNames += "," + customer2.getName();
-            contractVO.setCustomerNames(customerNames);
-
-            List<ContractBankInfoVO> bankInfoVOS = contractBankInfoService.findByContractIdAndIsDelete(contract.getId(), false);
-            ContractBankInfoVO bankInfo = null;
-            List<ContractBankInfoVO> entrustBankInfoVOS = new ArrayList<>();
-            for (ContractBankInfoVO bankInfoVO : bankInfoVOS){
-                if (!bankInfoVO.getIsEntrust())
-                    bankInfo = bankInfoVO;
-                else
-                    entrustBankInfoVOS.add(bankInfoVO);
-            }
-            if (bankInfo == null){//如果还没填,默认是第一位客户的银行信息
-                bankInfo = new ContractBankInfoVO();
-                bankInfo.setPayee(customer.getName());
-                bankInfo.setCustomerId(customer.getId());
-                bankInfo.setMobile(customer.getMobile());
-                bankInfo.setId(-1L);
-                bankInfo.setDisburseBank(customer.getBankName());
-                bankInfo.setDisburseAccount(customer.getBankAccount());
-            }
-            contractVO.setBankInfo(bankInfo);
-            contractVO.setEntrustBankInfos(entrustBankInfoVOS);
-            //contractVO.setCustomerName(customer.getName());
-            contractVOS.add(contractVO);
-        }
-        return contractVOS;
+        return convertContractsToContractVOS( contracts);
     }
 
     @Override
@@ -168,7 +132,8 @@ public class ContractServiceImpl implements ContractService {
 
     @Override
     public List<ContractVO> findContractByCaseIdAndIsPush(Long caseId, boolean isPush) {
-        return BeanUtil.copyToList(contractRepository.findByCaseIdAndIsPush(caseId,isPush, false), ContractVO.class);
+        List<Contract> contracts = contractRepository.findByCaseIdAndIsPush(caseId, isPush, false);
+        return convertContractsToContractVOS( contracts);
     }
 
     @Override
@@ -243,12 +208,8 @@ public class ContractServiceImpl implements ContractService {
     }
 
     @Override
-    public void completeContract(Long caseId, ContractWrapperDTO contractWrapper) {
-//        List<ContractVO> contract = findContractByCaseId(caseId);
-//        for (ContractVO contractVO : contract) {
-//            if (!contractVO.getSignedByCustomer())
-//                throw new DescribeException(CONTRACT_SIGN_NOT_COMPLETE);
-//        }
+    public void completeContract(LoanCaseSimpleVO loanCaseSimpleVO, ContractWrapperDTO contractWrapper) {
+        Long caseId = loanCaseSimpleVO.getId();
         List<ContractDTO> contractDTOS = contractWrapper.getContractDTOS();
         for (ContractDTO contractDTO : contractDTOS) {
             contractBankInfoService.addInfo(contractDTO.getBankInfo(),contractDTO.getId());
@@ -260,24 +221,59 @@ public class ContractServiceImpl implements ContractService {
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.CONTRACT_SIGN_PARENT.getCode(),caseId);
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(),StepPropertyEnum.CONTRACT_SIGN.getCode(),caseId);
         stepService.tryStartStep(StepPropertyEnum.CONTRACT_SIGN.getCode(),caseId);
+
+        //TODO:微信消息推送至下一环节:业务员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.PLAN_REPORT.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.ASSIST_SALES.getMsg(),RoleEnum.LEAD_SALES.getMsg()), false);
+        for (User user : users) {
+            if (user.getId().equals(BaseContext.getCurrentId())) continue;
+            if (user.getOpenid() != null) wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void getContractInformation(HttpServletResponse response, Long caseId,ContractVO contractVO){
+    public void getContractInformation(HttpServletResponse response, Long caseId,Long contractId){
+        Contract contract = contractRepository.findContractById(contractId);
         LoanCaseSimpleVO loancase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
         CustomerVO customer = customerService.findByCustomerIdAndIsDelete(loancase.getCustomerId(),false);
-        ContractInformation contractInformation = BeanUtil.copyProperties(contractVO, ContractInformation.class);
-        if (contractVO.getSignedId() != null){
-            Document byId = documentService.findById(contractVO.getSignedId());
+        ContractInformation contractInformation = BeanUtil.copyProperties(contract, ContractInformation.class);
+        if (contract.getSignedId() != null){
+            Document byId = documentService.findById(contract.getSignedId());
             contractInformation.setSignaturePath1(byId.getFilePath());
         }
+        String names = "";
+        String idNumbers = "";
+        if (contract.getCustomerId()!=null){
+            Customer customer1 = customerService.findByIdAndIsDelete(contract.getCustomerId());
+            names = names == "" ? customer1.getName() : names + "、" + customer1.getName();
+            idNumbers = idNumbers == "" ? customer1.getIdNumber() : idNumbers + "、" + customer1.getIdNumber();
+        }
+        if (contract.getCustomerId1()!=null){
+            Customer customer2 = customerService.findByIdAndIsDelete(contract.getCustomerId1());
+            names = names == "" ? customer2.getName() : names + "、" + customer2.getName();
+            idNumbers = idNumbers == "" ? customer2.getIdNumber() : idNumbers + "、" + customer2.getIdNumber();
+        }
+        if (contract.getCustomerId2()!=null){
+            Customer customer3 = customerService.findByIdAndIsDelete(contract.getCustomerId2());
+            names = names == "" ? customer3.getName() : names + "、" + customer3.getName();
+            idNumbers = idNumbers == "" ? customer3.getIdNumber() : idNumbers + "、" + customer3.getIdNumber();
+        }
 
-        contractInformation.setName(customer.getName());
-        contractInformation.setIdNumber(customer.getIdNumber());
+        contractInformation.setName(names);
+        contractInformation.setIdNumber(idNumbers);
+        contractInformation.setContractAmount(NumberToChineseUtil.convertToChinese(contract.getContractAmount())+"万元");
         contractInformation.setMobile(customer.getMobile());
         contractInformation.setContactAddress1(customer.getContactAddress());
-        contractInformation.setContractAttr(loancase.getBusinessAttrs());
-        contractInformation.setContractType(loancase.getBusinessType());
+        contractInformation.setContractAttr(loancase.getBusinessUsage());//改成借款用途了
+        contractInformation.setContractType(loancase.getBusinessAttrs());//改成业务属性了
 
         Map<String, String> contractMap = dictionaryService.contractMap();
         contractInformation.setPages1(contractMap.get(ContractEnum.CONTRACT_COPIES.getLabel()));
@@ -286,13 +282,21 @@ public class ContractServiceImpl implements ContractService {
         contractInformation.setSignLocation1(contractMap.get(ContractEnum.SIGNATURE_ADDRESS.getLabel()));
         contractInformation.setSignLocation2(contractMap.get(ContractEnum.SIGNATURE_ADDRESS.getLabel()));
 
-        String downloadName = contractVO.getContractName()+"-"+contractVO.getId();
+        List<Long> collateralIdsByContractId = contractAndCollateralService.findCollateralIdsByContractId(contract.getId());
+        if (collateralIdsByContractId != null){
+            Collateral collateral = collateralService.findCollateralById(collateralIdsByContractId.get(0));
+            contractInformation.setAddress(collateral.getAddress());
+            contractInformation.setCollateralArea(collateral.getCollateralArea()+"平方米");
+            contractInformation.setCollateralNumber(collateral.getCollateralNo());
+        }
+
+        String downloadName = contract.getContractName()+"-"+contract.getId();
         new PoiWordUtil().writeApprove(response,contractPath+"template1.docx",contractInformation,downloadName);
     }
 
     @Override
     public ContractInformation getContractInformationById(Long caseId, Long contractId) {
-        Contract contract = findContractById(contractId);
+        Contract contract = contractRepository.findContractById(contractId);
         LoanCaseSimpleVO loancase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
         CustomerVO customer = customerService.findByCustomerIdAndIsDelete(loancase.getCustomerId(),false);
         ContractInformation contractInformation = BeanUtil.copyProperties(contract, ContractInformation.class);
@@ -300,13 +304,32 @@ public class ContractServiceImpl implements ContractService {
             Document byId = documentService.findById(contract.getSignedId());
             contractInformation.setSignaturePath1(byId.getFilePath());
         }
+        String names = "";
+        String idNumbers = "";
+        if (contract.getCustomerId()!=null){
+            Customer customer1 = customerService.findByIdAndIsDelete(contract.getCustomerId());
+            names = names == "" ? customer1.getName() : names + "、" + customer1.getName();
+            idNumbers = idNumbers == "" ? customer1.getIdNumber() : idNumbers + "、" + customer1.getIdNumber();
+        }
+        if (contract.getCustomerId1()!=null){
+            Customer customer2 = customerService.findByIdAndIsDelete(contract.getCustomerId1());
+            names = names == "" ? customer2.getName() : names + "、" + customer2.getName();
+            idNumbers = idNumbers == "" ? customer2.getIdNumber() : idNumbers + "、" + customer2.getIdNumber();
+        }
+        if (contract.getCustomerId2()!=null){
+            Customer customer3 = customerService.findByIdAndIsDelete(contract.getCustomerId2());
+            names = names == "" ? customer3.getName() : names + "、" + customer3.getName();
+            idNumbers = idNumbers == "" ? customer3.getIdNumber() : idNumbers + "、" + customer3.getIdNumber();
+        }
+
+        contractInformation.setName(names);
+        contractInformation.setIdNumber(idNumbers);
+        contractInformation.setContractAmount(NumberToChineseUtil.convertToChinese(contract.getContractAmount()));
 
-        contractInformation.setName(customer.getName());
-        contractInformation.setIdNumber(customer.getIdNumber());
         contractInformation.setMobile(customer.getMobile());
         contractInformation.setContactAddress1(customer.getContactAddress());
-        contractInformation.setContractAttr(loancase.getBusinessAttrs());
-        contractInformation.setContractType(loancase.getBusinessType());
+        contractInformation.setContractAttr(loancase.getBusinessUsage());//改成借款用途了
+        contractInformation.setContractType(loancase.getBusinessAttrs());//改成业务属性了
 
         Map<String, String> contractMap = dictionaryService.contractMap();
         contractInformation.setPages1(contractMap.get(ContractEnum.CONTRACT_COPIES.getLabel()));
@@ -315,6 +338,14 @@ public class ContractServiceImpl implements ContractService {
         contractInformation.setSignLocation1(contractMap.get(ContractEnum.SIGNATURE_ADDRESS.getLabel()));
         contractInformation.setSignLocation2(contractMap.get(ContractEnum.SIGNATURE_ADDRESS.getLabel()));
 
+        List<Long> collateralIdsByContractId = contractAndCollateralService.findCollateralIdsByContractId(contract.getId());
+        if (collateralIdsByContractId != null){
+            Collateral collateral = collateralService.findCollateralById(collateralIdsByContractId.get(0));
+            contractInformation.setAddress(collateral.getAddress());
+            contractInformation.setCollateralArea(collateral.getCollateralArea());
+            contractInformation.setCollateralNumber(collateral.getCollateralNo());
+        }
+
         return contractInformation;
     }
 
@@ -332,7 +363,7 @@ public class ContractServiceImpl implements ContractService {
     public void updateActualAmountAndIsCompleteByIds(Map<Long, Double> contractIdAndAmount,Boolean isComplete) {
         for (Map.Entry<Long, Double> entry : contractIdAndAmount.entrySet()){
             Contract contract = contractRepository.findContractById(entry.getKey());
-            Double amount = contract.getActualAmount() + entry.getValue();
+            Double amount = entry.getValue();
             isComplete = contract.getIsDisbursementComplete();
             if(Math.abs(amount - contract.getContractAmount())<Double.MIN_VALUE && isComplete == false)//相同则自动更新
                 isComplete = true;
@@ -354,5 +385,78 @@ public class ContractServiceImpl implements ContractService {
         contractRepository.updateISCompleteById(contractId,isDisbursement);
     }
 
+    @Override
+    public Result findAllContract(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum, pageSize);
+        Page<Contract> data = contractRepository.findAllByIsDelete(false, pageable);
+
+        List<ContractVO> contractVOS = convertContractsToContractVOS(data.getContent());
+
+        return ResultUtil.success(data.getTotalElements(), contractVOS);
+    }
+
+    @Override
+    public Result findAllContractByQuery(Integer pageNum, Integer pageSize, ContractQueryDTO contractQueryDTO) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<Contract> data = contractRepository.findAllByQuery(contractQueryDTO, pageable);
+
+        return ResultUtil.success(data.getTotalElements(), convertContractsToContractVOS(data.getContent()));
+    }
+
+    @Override
+    public void deleteContractById(Long id) {
+        contractRepository.deleteByIdAndIsDelete(id, true);
+    }
+
+    @Override
+    public void updateIsDisbursementByCaseId(Long caseId) {
+        contractRepository.updateIsDisbursementByCaseIdAndIsDelete(caseId,false);
+    }
+
+    private List<ContractVO> convertContractsToContractVOS(List<Contract> contracts) {
+        List<ContractVO> contractVOS = new ArrayList<>();
+        for (Contract contract : contracts){
+            ContractVO contractVO = BeanUtil.copyProperties(contract, ContractVO.class);
+            contractVO.setEsignFlow(esignService.findByContractIdAndNormal(contract.getId()));
+
+            Customer customer = customerService.findByIdAndIsDelete(contract.getCustomerId());
+            contractVO.setCustomer(BeanUtil.copyProperties(customer, CustomerVO.class));
+            Customer customer1 = customerService.findByIdAndIsDelete(contract.getCustomerId1());
+            contractVO.setCustomer1(BeanUtil.copyProperties(customer1, CustomerVO.class));
+            Customer customer2 = customerService.findByIdAndIsDelete(contract.getCustomerId2());
+            contractVO.setCustomer2(BeanUtil.copyProperties(customer2, CustomerVO.class));
+            String customerNames = "";
+            if (!ObjectUtils.isEmpty(customer)) customerNames += customer.getName();
+            if (!ObjectUtils.isEmpty(customer1)) customerNames += "," + customer1.getName();
+            if (!ObjectUtils.isEmpty(customer2)) customerNames += "," + customer2.getName();
+            contractVO.setCustomerNames(customerNames);
+
+            List<ContractBankInfoVO> bankInfoVOS = contractBankInfoService.findByContractIdAndIsDelete(contract.getId(), false);
+            ContractBankInfoVO bankInfo = null;
+            List<ContractBankInfoVO> entrustBankInfoVOS = new ArrayList<>();
+            for (ContractBankInfoVO bankInfoVO : bankInfoVOS){
+                if (!bankInfoVO.getIsEntrust())
+                    bankInfo = bankInfoVO;
+                else
+                    entrustBankInfoVOS.add(bankInfoVO);
+            }
+            if (bankInfo == null && customer != null){//如果还没填,默认是第一位客户的银行信息
+                bankInfo = new ContractBankInfoVO();
+                bankInfo.setPayee(customer.getName());
+                bankInfo.setCustomerId(customer.getId());
+                bankInfo.setMobile(customer.getMobile());
+                bankInfo.setId(-1L);
+                bankInfo.setDisburseBank(customer.getBankName());
+                bankInfo.setDisburseAccount(customer.getBankAccount());
+            }
+            contractVO.setBankInfo(bankInfo);
+            contractVO.setEntrustBankInfos(entrustBankInfoVOS);
+            //contractVO.setCustomerName(customer.getName());
+            contractVOS.add(contractVO);
+        }
+
+        return contractVOS;
+    }
+
 
 }

+ 21 - 2
src/main/java/com/loan/system/service/Impl/CustomerServiceImpl.java

@@ -2,12 +2,15 @@ package com.loan.system.service.Impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.domain.dto.CustomerDTO;
+import com.loan.system.domain.dto.query.CustomerQueryDTO;
 import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.User;
 import com.loan.system.domain.enums.RoleEnum;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.CustomerVO;
 import com.loan.system.repository.CustomerRepository;
 import com.loan.system.service.CustomerService;
+import com.loan.system.utils.ResultUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -102,10 +105,11 @@ public class CustomerServiceImpl implements CustomerService {
     }
 
     @Override
-    public List<Customer> getAllCustomersByAdmin(Integer pageNum, Integer pageSize) {
+    public Result getAllCustomersByAdmin(Integer pageNum, Integer pageSize) {
         Pageable pageable = PageRequest.of(pageNum, pageSize);
         Page<Customer> customerPage = customerRepository.findByIsDelete(false,pageable);
-        return customerPage.getContent();
+
+        return ResultUtil.success(customerPage.getTotalElements(),customerPage.getContent());
     }
 
     @Override
@@ -145,4 +149,19 @@ public class CustomerServiceImpl implements CustomerService {
     public List<Customer> findByCustomerNameAndIsDelete(String customerName, boolean b) {
         return customerRepository.findByNameAndIsDelete(customerName,b);
     }
+
+    @Override
+    public Result listCustomersByQuery(CustomerQueryDTO queryDTO, Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<Customer> data = customerRepository.findByQuery(queryDTO, pageable);
+
+        return ResultUtil.success(data.getTotalElements(),data.getContent());
+
+    }
+
+    @Override
+    public List<CustomerVO> findByIdsInAndIsDelete(Iterable<Long> ids, boolean isDelete) {
+        List<Customer> customers = customerRepository.findByIdInAndIsDelete(ids, isDelete);
+        return BeanUtil.copyToList(customers, CustomerVO.class);
+    }
 }

+ 756 - 0
src/main/java/com/loan/system/service/Impl/DetailServiceImpl.java

@@ -0,0 +1,756 @@
+package com.loan.system.service.Impl;
+
+import com.loan.system.config.FileUploadConfig;
+import com.loan.system.domain.dto.DetailDTO;
+import com.loan.system.domain.entity.*;
+import com.loan.system.domain.enums.DecisionEnum;
+import com.loan.system.domain.enums.StepEnum;
+import com.loan.system.domain.enums.StepPropertyEnum;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.vo.*;
+import com.loan.system.service.*;
+import com.loan.system.utils.ResultUtil;
+import lombok.RequiredArgsConstructor;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+@RequiredArgsConstructor
+public class DetailServiceImpl implements DetailService {
+    private final LoanService loanService;
+    private final RepaymentService repaymentService;
+    private final RepaymentRecordService repaymentRecordService;
+    private final FileUploadConfig fileUploadConfig;
+    private final ContractService contractService;
+    private final ContractRepaymentService contractRepaymentService;
+    private final CustomerService customerService;
+    private final CustomerOtherService customerOtherService;
+    private final RecommenderService recommenderService;
+    private final StepService stepService;
+    private final UserService userService;
+    private final DisbursementService disbursementService;
+    private final CollateralService collateralService;
+    private final ContractAndCollateralService contractAndCollateralService;
+    private final CollateralPlanService collateralPlanService;
+    private final LocationDatumService locationDatumService;
+
+    @Override
+    public Result getArrangeReport(LocalDate begin) {
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String endTime = begin.atTime(23, 59, 59).format(fmt);
+
+        List<LoanCaseStatistic> loanCaseStatistics = new ArrayList<>();
+
+        //指派人员只需要显示进行中的业务
+        List<LoanCaseSimpleVO> loanCases = loanService.findLoanCaseSimpleByIsComplete(DecisionEnum.PROCESS.getMsg());
+        for (LoanCaseSimpleVO loanCase : loanCases){
+            LoanCaseStatistic loanCaseStatistic = new LoanCaseStatistic();
+            List<StepVO> steps = stepService.getChildStepByCaseIdBeforeTime(loanCase.getId(), endTime);
+            //仅显示派单环节的信息
+            for (StepVO step : steps){
+                if (step.getStatus().equals(StepEnum.UNSTART.getMsg()) || step.getUserId1() == null)
+                    continue;
+
+                if (!step.getCode().equals(StepPropertyEnum.EVIDENCE_CONFIRMATION.getCode()) && !step.getCode().equals(StepPropertyEnum.DELIVERY_CONFIRMATION.getCode())
+                        &&!step.getCode().equals(StepPropertyEnum.DISBURSE_START.getCode()) && !step.getCode().equals(StepPropertyEnum.BALANCE_REPAY.getCode()))
+                    continue;
+
+                loanCaseStatistic.setWeekSeq(calculateWeekSequence(LocalDate.parse(step.getBeginTime(), fmt)));
+                loanCaseStatistic.setDisburseDate(getDateAndPlace( step ,loanCase.getId()).get(0));//2.
+                loanCaseStatistic.setCustomerName(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false).getName());//3.
+                loanCaseStatistic.setBusinessType(loanCase.getBusinessType());//4.
+                loanCaseStatistic.setAmount(loanCase.getTotalLoanAmount());//5.
+
+                loanCaseStatistic.setStepName(step.getStepName());//6.
+
+                if (step.getCode().equals(StepPropertyEnum.BALANCE_REPAY.getCode())||step.getCode().equals(StepPropertyEnum.DISBURSE_START.getCode())){
+                    List<String> data = getDateAndPlace(step, loanCase.getId());
+                    if (data.size()>=3)
+                        loanCaseStatistic.setUserName1(data.get(2));
+                    if (data.size()==4)
+                        loanCaseStatistic.setUserName2(data.get(3));
+                }else {
+                    String[] ids = new String[]{};
+                    if (step.getUserIds() != null)
+                        ids = step.getUserIds().split(",");
+                    String userName1 = "";
+                    if (ids.length > 0)
+                        userName1 = userService.findByIdAndIsDelete(Long.parseLong(ids[0])).getRealName();
+                    loanCaseStatistic.setUserName1(userName1);//7.
+
+                    String userName2 = "";
+                    Stream<String> distinct = Arrays.stream(ids).distinct();
+                    List<Long> userIds = distinct.map(Long::parseLong).collect(Collectors.toList());
+                    if(userIds.size() > 1){
+                        List<User> users = userService.findByIdsAndIsDelete(userIds.subList(1, userIds.size()));//保证了第一个不会出现在后面
+                        userName2 = users.stream().map(User::getRealName).collect(Collectors.toList()).toString();
+                    }
+                    loanCaseStatistic.setUserName2(userName2);//8.
+                }
+
+                loanCaseStatistic.setStartDate(step.getBeginTime());//9.
+                loanCaseStatistic.setPlace(getDateAndPlace( step ,loanCase.getId()).get(1));//10.
+                loanCaseStatistic.setEndDate(step.getStatus().equals(StepEnum.COMPLETED.getMsg()) ? step.getUpdateTime() : step.getStatus());//11.
+
+                loanCaseStatistics.add(loanCaseStatistic);
+            }
+
+        }
+        // 对 loanCaseStatistics 进行排序
+        loanCaseStatistics.sort(Comparator
+                .comparing(LoanCaseStatistic::getStartDate)
+                .thenComparing(LoanCaseStatistic::getUserName1));
+
+
+        return ResultUtil.success("success",loanCaseStatistics);
+    }
+
+    @Override
+    public Result getLoanCaseReport(LocalDate begin, LocalDate end) {
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String beginTime = begin.atStartOfDay().format(fmt);
+        String endTime = end.atTime(23, 59, 59).format(fmt);
+
+        List<LoanCaseStatistic> loanCaseStatistics = new ArrayList<>();
+
+        List<LoanCaseSimpleVO> loanCases = loanService.findLoanCaseBetweenRange(beginTime, endTime);
+
+        // 批量获取所有相关的客户ID
+        Set<Long> customerIds = loanCases.stream()
+                .map(LoanCaseSimpleVO::getCustomerId)
+                .collect(Collectors.toSet());
+
+        // 批量获取客户信息
+        Map<Long, CustomerVO> customerMap = new HashMap<>();
+        if (!customerIds.isEmpty()) {
+            List<CustomerVO> customers = customerService.findByIdsInAndIsDelete(customerIds, false);
+            customerMap = customers.stream().collect(Collectors.toMap(CustomerVO::getId, customer -> customer));
+        }
+
+        // 遍历loanCases并收集所有相关的步骤
+        Map<Long, List<StepVO>> caseStepsMap = new HashMap<>();
+        for (LoanCaseSimpleVO loanCase : loanCases) {
+            List<StepVO> steps = stepService.getChildStepByCaseIdBetweenRange(loanCase.getId(), beginTime, endTime);
+            caseStepsMap.put(loanCase.getId(), steps);
+        }
+
+        // 收集所有需要的用户ID用于批量查询
+        Set<Long> userIds = new HashSet<>();
+        for (LoanCaseSimpleVO loanCase : loanCases) {
+            List<StepVO> steps = caseStepsMap.get(loanCase.getId());
+            for (StepVO step : steps) {
+                if (step.getStatus().equals(StepEnum.UNSTART.getMsg()) || step.getUserId1() == null)
+                    continue;
+
+                // 添加主要用户ID
+                if (step.getUserId1() != null) {
+                    userIds.add(step.getUserId1());
+                }
+
+                // 添加其他用户ID
+                if (step.getUserIds() != null) {
+                    String[] ids = step.getUserIds().split(",");
+                    for (String idStr : ids) {
+                        try {
+                            Long userId = Long.parseLong(idStr.trim());
+                            userIds.add(userId);
+                        } catch (NumberFormatException e) {
+                            // 忽略无效的ID
+                        }
+                    }
+                }
+            }
+        }
+
+        // 批量获取用户信息
+        Map<Long, User> userMap = new HashMap<>();
+        if (!userIds.isEmpty()) {
+            List<User> users = userService.findByIdsAndIsDelete(new ArrayList<>(userIds));
+            userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));
+        }
+
+        // 处理数据
+        for (LoanCaseSimpleVO loanCase : loanCases){
+            List<StepVO> steps = caseStepsMap.get(loanCase.getId());
+            for (StepVO step : steps){
+                if (step.getStatus().equals(StepEnum.UNSTART.getMsg()) || step.getUserId1() == null)
+                    continue;
+
+                LoanCaseStatistic loanCaseStatistic = new LoanCaseStatistic();
+                loanCaseStatistic.setWeekSeq(calculateWeekSequence(LocalDate.parse(step.getBeginTime(), fmt)));
+                List<String> dateAndPlace = getDateAndPlace(step, loanCase.getId());
+                if(!dateAndPlace.isEmpty())
+                    loanCaseStatistic.setDisburseDate(dateAndPlace.get(0));//2.
+
+                // 使用缓存的客户信息
+                CustomerVO customer = customerMap.get(loanCase.getCustomerId());
+                if (customer != null) {
+                    loanCaseStatistic.setCustomerName(customer.getName());//3.
+                }
+
+                loanCaseStatistic.setBusinessType(loanCase.getBusinessType());//4.
+                loanCaseStatistic.setAmount(loanCase.getTotalLoanAmount());//5.
+
+                loanCaseStatistic.setStepName(step.getStepName());//6.
+
+                if (step.getCode().equals(StepPropertyEnum.BALANCE_REPAY.getCode())||step.getCode().equals(StepPropertyEnum.DISBURSE_START.getCode())){
+                    List<String> data = getDateAndPlace(step, loanCase.getId());
+                    if (data.size()>=3)
+                        loanCaseStatistic.setUserName1(data.get(2));
+                    if (data.size()==4)
+                        loanCaseStatistic.setUserName2(data.get(3));
+                }else {
+                    String[] ids = new String[]{};
+                    if (step.getUserIds() != null)
+                        ids = step.getUserIds().split(",");
+                    String userName1 = "";
+                    if (ids.length > 0) {
+                        Long userId = Long.parseLong(ids[0]);
+                        User user = userMap.get(userId);
+                        if (user != null) {
+                            userName1 = user.getRealName();
+                        }
+                    }
+                    loanCaseStatistic.setUserName1(userName1);//7.
+
+                    String userName2 = "";
+                    Stream<String> distinct = Arrays.stream(ids).distinct();
+                    List<Long> userIdsList = distinct.map(Long::parseLong).collect(Collectors.toList());
+                    if(userIdsList.size() > 1){
+                        List<User> userList = new ArrayList<>();
+                        for (int i = 1; i < userIdsList.size(); i++) {
+                            User user = userMap.get(userIdsList.get(i));
+                            if (user != null) {
+                                userList.add(user);
+                            }
+                        }
+                        userName2 = userList.stream().map(User::getRealName).collect(Collectors.toList()).toString();
+                    }
+                    loanCaseStatistic.setUserName2(userName2);//8.
+                }
+
+                loanCaseStatistic.setStartDate(step.getBeginTime());//9.
+                if(dateAndPlace.size()>1)
+                    loanCaseStatistic.setPlace(dateAndPlace.get(1));//10.
+                loanCaseStatistic.setEndDate(step.getStatus().equals(StepEnum.COMPLETED.getMsg()) ? step.getUpdateTime() : step.getStatus());//11.
+
+                loanCaseStatistics.add(loanCaseStatistic);
+            }
+        }
+
+        // 对 loanCaseStatistics 进行排序
+        loanCaseStatistics.sort(Comparator
+                .comparing(LoanCaseStatistic::getStartDate)
+                .thenComparing(LoanCaseStatistic::getUserName1));
+
+        return ResultUtil.success("success",loanCaseStatistics);
+    }
+
+    @Override
+    public void exportLoanCaseReport(DetailDTO<LoanCaseStatistic> detailDTO, LocalDate begin, LocalDate end, HttpServletResponse response) {
+        List<LoanCaseStatistic> loanCaseStatistics = detailDTO.getData();
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String beginTime = begin.atStartOfDay().format(fmt);
+        String endTime = end.atTime(23, 59, 59).format(fmt);
+
+        List<LoanCaseStatistic> loanCaseStatisticList = new ArrayList<>();
+        for (LoanCaseStatistic loanCaseStatistic : loanCaseStatistics){
+            if (loanCaseStatistic.getEndDate() != null && !loanCaseStatistic.getEndDate().equals("进行中")){
+                LocalDateTime endDate = LocalDateTime.parse(loanCaseStatistic.getEndDate(), fmt);
+                LocalDateTime begin1 = LocalDateTime.parse(beginTime, fmt);
+                LocalDateTime end1 = LocalDateTime.parse(endTime, fmt);
+                if (endDate.isAfter(begin1) && endDate.isBefore(end1))
+                    loanCaseStatisticList.add(loanCaseStatistic);
+            }
+        }
+        System.out.println(loanCaseStatisticList);
+        //查询概览运营数据,提供给Excel模板文件
+        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("file_store/template/loanStatistics.xlsx");
+
+        if (inputStream == null) {
+            throw new RuntimeException("无法找到Excel模板文件: " + fileUploadConfig.getUploadDir() + "template/" + "loanStatistics.xlsx");
+        }
+
+        try {
+            //基于提供好的模板文件创建一个新的Excel表格对象
+            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
+
+            //获得Excel文件中的一个Sheet页
+            XSSFSheet sheet = excel.getSheet("Sheet1");
+            //TODO:row(从0开始)行,cell(从0开始)获取单元格
+            //获得第1行
+            XSSFRow row = sheet.getRow(0);
+            row.getCell(1).setCellValue(begin.format(DateTimeFormatter.ofPattern("yyyy年M月")));
+
+            //获取单元格
+            for (int i = 0; i < loanCaseStatisticList.size(); i++) {
+                LoanCaseStatistic loanCaseStatistic = loanCaseStatisticList.get(i);
+                int rowIdx = i + 4;
+                row = sheet.getRow(rowIdx);
+                if (row == null) {
+                    row = sheet.createRow(rowIdx);
+                }
+                System.out.println(row);
+                row.getCell(0).setCellValue(loanCaseStatistic.getWeekSeq());
+                row.getCell(1).setCellValue(loanCaseStatistic.getStartDate());
+                row.getCell(2).setCellValue(loanCaseStatistic.getCustomerName());
+                row.getCell(3).setCellValue(loanCaseStatistic.getBusinessType());
+                row.getCell(4).setCellValue(loanCaseStatistic.getAmount());
+                row.getCell(5).setCellValue(loanCaseStatistic.getStepName());
+                row.getCell(6).setCellValue(loanCaseStatistic.getUserName1());
+                row.getCell(7).setCellValue(loanCaseStatistic.getUserName2());
+                row.getCell(8).setCellValue(loanCaseStatistic.getStartDate());
+                row.getCell(9).setCellValue(loanCaseStatistic.getPlace());
+                row.getCell(10).setCellValue(loanCaseStatistic.getEndDate());
+
+            }
+
+            //通过输出流将文件下载到客户端浏览器中
+            ServletOutputStream out = response.getOutputStream();
+            excel.write(out);
+
+            //关闭资源
+            out.flush();
+            out.close();
+            excel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public Result getAccountReport(Long caseId, Integer pageNum, Integer pageSize) {
+        int begin = pageNum * pageSize;
+        List<LoanCaseDetails> loanCaseDetails = new ArrayList<>();
+        //获取业务信息
+        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+
+        //获取客户与其它客户信息
+        Customer customer = customerService.findByIdAndIsDelete(loanCase.getCustomerId());
+        List<CustomersOtherVO> customersOtherVOS = customerOtherService.findByCaseId(caseId);
+
+        //获取回款记录信息(核心)
+        List<RepaymentRecord> repaymentRecords = repaymentRecordService.findByRepaymentIdAndIsInterestAndIsDelete(repaymentService.findByCaseIdAndIsDelete(caseId, false).getId(), false);
+        List<Long> recordIds = repaymentRecords.stream().map(RepaymentRecord::getId).collect(Collectors.toList());
+        List<ContractRepayment> contractRepayments = contractRepaymentService.findByRepaymentRecordIdsAndIsDelete(recordIds);
+
+        List<Long> contractIds = contractRepayments.stream().map(ContractRepayment::getContractId).collect(Collectors.toList());
+        for (Long contractId : contractIds) {
+            double amount = 0.0;//累计回款
+            Contract contract = contractService.findContractById(contractId);
+            for (ContractRepayment contractRepayment : contractRepayments) {
+                if (contractRepayment.getContractId().equals(contractId)) {
+                    LoanCaseDetails loanCaseDetail = new LoanCaseDetails();
+
+                    loanCaseDetail.setContractNo(contract.getContractNo());//1
+//                    PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractId);
+//                    if(pawnTicketInfo!=null){
+//                        loanCaseDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
+//                        loanCaseDetail.setRedeemTime(pawnTicketInfo.getEndTime());//16.
+//                        loanCaseDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//17.
+//                    }
+                    loanCaseDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
+                    loanCaseDetail.setCustomerName(customer.getName());//4.
+                    loanCaseDetail.setCustomerName2(customersOtherVOS.get(0).getName());//5.
+                    loanCaseDetail.setPhoneNumber(customer.getMobile());//6.
+                    loanCaseDetail.setPawnAmount(loanCase.getTotalLoanAmount());//7.
+                    List<String> attributes = new ArrayList<>();
+                    List<String> locations = new ArrayList<>();
+                    List<ContractAndCollateral> contractAndCollaterals = contractAndCollateralService.listByContractId(contractId);
+                    for (ContractAndCollateral contractAndCollateral : contractAndCollaterals) {
+                        if (contractAndCollateral.getContractId().equals(contractId)){
+                            Collateral collateral = collateralService.findCollateralById(contractAndCollateral.getCollateralId());
+                            attributes.add(contract.getBusinessAttr());
+                            locations.add(collateral.getAddress());
+                        }
+                    }
+                    loanCaseDetail.setLocations( locations);
+                    loanCaseDetail.setAttributes(attributes);
+
+                    loanCaseDetail.setChannelName(loanCase.getChannelName());//9.
+                    List<String> userNames=new ArrayList<>();
+                    StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
+                    StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
+                    if(stepVO!=null){
+                        userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
+                    }
+                    if(stepVO1!=null){
+                        userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
+                    }
+                    loanCaseDetail.setUserName(userNames);//10.
+
+                    amount += contractRepayment.getAmount();
+                    loanCaseDetail.setRepayTime(contractRepayment.getCreateTime());//11.
+                    loanCaseDetail.setRepayTotalAmount(amount);//12
+                    loanCaseDetail.setLastRepayAmount(contractRepayment.getAmount());//13.
+                    loanCaseDetail.setBalance(loanCase.getTotalLoanAmount() - amount);//14.
+                    if(Math.abs(loanCase.getTotalLoanAmount() - amount)<Double.MIN_VALUE)
+                        loanCaseDetail.setInterestAmount(contract.getInterestAmount());//15.
+
+                    loanCaseDetails.add(loanCaseDetail);
+                }
+
+            }
+        }
+
+        return ResultUtil.success("success", loanCaseDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+    }
+
+    @Override
+    public void exportAccountReport(List<LoanCaseDetails> loanCaseDetails, Integer begin, Integer end, HttpServletResponse response) {
+        //查询概览运营数据,提供给Excel模板文件
+        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "业务台账.xlsx");
+        try {
+            //基于提供好的模板文件创建一个新的Excel表格对象
+            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
+
+            //获得Excel文件中的一个Sheet页
+            XSSFSheet sheet = excel.getSheet("Sheet1");
+            //TODO:row(从0开始)行,cell(从0开始)获取单元格
+            //获得第1行
+            XSSFRow row = sheet.getRow(1);
+            //获取单元格
+            for (int i = begin; i < end; i++) {
+                LoanCaseDetails loanCaseDetail = loanCaseDetails.get(i);
+                row = sheet.getRow(i);
+                row.getCell(0).setCellValue(loanCaseDetail.getContractNo());
+                row.getCell(1).setCellValue(loanCaseDetail.getPawnTicketNo());
+                row.getCell(2).setCellValue(loanCaseDetail.getLoanTime());
+                row.getCell(3).setCellValue(loanCaseDetail.getCustomerName());
+                row.getCell(4).setCellValue(loanCaseDetail.getCustomerName2());
+                row.getCell(5).setCellValue(loanCaseDetail.getPhoneNumber());
+                row.getCell(6).setCellValue(loanCaseDetail.getPawnAmount());
+                row.getCell(7).setCellValue(loanCaseDetail.getLocations().toString());
+                row.getCell(8).setCellValue(loanCaseDetail.getAttributes().toString());
+                row.getCell(9).setCellValue(loanCaseDetail.getChannelName());
+                row.getCell(10).setCellValue(loanCaseDetail.getUserName().toString());
+                row.getCell(11).setCellValue(loanCaseDetail.getRepayTime());
+                row.getCell(12).setCellValue(loanCaseDetail.getRepayTotalAmount());
+                row.getCell(13).setCellValue(loanCaseDetail.getLastRepayAmount());
+                row.getCell(14).setCellValue(loanCaseDetail.getBalance());
+                row.getCell(15).setCellValue(loanCaseDetail.getInterestAmount());
+                row.getCell(16).setCellValue(loanCaseDetail.getRedeemTime());
+                row.getCell(17).setCellValue(loanCaseDetail.getRedeemTicketNo());
+                row.getCell(18).setCellValue(loanCaseDetail.getComment());
+
+            }
+
+            //通过输出流将文件下载到客户端浏览器中
+            ServletOutputStream out = response.getOutputStream();
+            excel.write(out);
+
+            //关闭资源
+            out.flush();
+            out.close();
+            excel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public Result getDisbursementReport(Long caseId, Integer pageNum, Integer pageSize) {
+        int begin = pageNum * pageSize;
+        List<DisbursementDetails> disbursementDetails = new ArrayList<>();
+
+        //获取业务信息
+        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+        //获取合同信息
+        List<ContractVO> contractVOS = contractService.findContractByCaseId(caseId);
+        for(ContractVO contractVO : contractVOS){
+            DisbursementDetails disbursementDetail = new DisbursementDetails();
+
+            disbursementDetail.setContractNo(contractVO.getContractNo());//1.
+//            PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractVO.getId());
+//            if(pawnTicketInfo!=null){
+//                disbursementDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
+//                disbursementDetail.setRedeemTime(pawnTicketInfo.getEndTime());//9.
+//                disbursementDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//10.
+//            }
+//            disbursementDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
+
+            disbursementDetail.setCustomerName(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false).getName());//4.
+            disbursementDetail.setPawnAmount(contractVO.getContractAmount());//5.
+            List<String> userNames=new ArrayList<>();
+            StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
+            StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
+            if(stepVO!=null){
+                userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
+            }
+            if(stepVO1!=null){
+                userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
+            }
+            disbursementDetail.setUserName(userNames);//6.
+            disbursementDetail.setRecommenderName(recommenderService.getRecommenderById(loanCase.getRecommenderId()).getRecommenderName());//7.
+            disbursementDetail.setChannelName(loanCase.getChannelName());//8.
+
+            disbursementDetails.add(disbursementDetail);
+        }
+
+        //获取当票
+        return ResultUtil.success("success", disbursementDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+    }
+
+    @Override
+    public void exportDisbursementReport(List<DisbursementDetails> disbursementDetails, Integer begin, Integer end, HttpServletResponse response) {
+        //查询概览运营数据,提供给Excel模板文件
+        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "出账明细.xlsx");
+        try {
+            //基于提供好的模板文件创建一个新的Excel表格对象
+            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
+
+            //获得Excel文件中的一个Sheet页
+            XSSFSheet sheet = excel.getSheet("Sheet1");
+            //TODO:row(从0开始)行,cell(从0开始)获取单元格
+            //获得第1行
+            XSSFRow row = sheet.getRow(1);
+            //获取单元格
+            for (int i = begin; i < end; i++) {
+                DisbursementDetails disbursementDetail = disbursementDetails.get(i);
+                row = sheet.getRow(i);
+                row.getCell(0).setCellValue(disbursementDetail.getContractNo());
+                row.getCell(1).setCellValue(disbursementDetail.getLoanTime());
+                row.getCell(2).setCellValue(disbursementDetail.getPawnTicketNo());
+                row.getCell(3).setCellValue(disbursementDetail.getCustomerName());
+                row.getCell(4).setCellValue(disbursementDetail.getPawnAmount());
+                row.getCell(5).setCellValue(disbursementDetail.getUserName().toString());
+                row.getCell(6).setCellValue(disbursementDetail.getRecommenderName());
+                row.getCell(7).setCellValue(disbursementDetail.getChannelName());
+                row.getCell(8).setCellValue(disbursementDetail.getRedeemTime());
+                row.getCell(9).setCellValue(disbursementDetail.getRedeemTicketNo());
+
+            }
+
+            //通过输出流将文件下载到客户端浏览器中
+            ServletOutputStream out = response.getOutputStream();
+            excel.write(out);
+
+            //关闭资源
+            out.flush();
+            out.close();
+            excel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public Result repaymentReport(Long caseId, int begin, Integer pageSize) {
+        List<RepaymentDetails> repaymentDetails = new ArrayList<>();
+        //获取当票信息
+
+        //获取业务信息
+        LoanCaseSimpleVO loanCase = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
+
+        //获取客户与其它客户信息
+        Customer customer = customerService.findByIdAndIsDelete(loanCase.getCustomerId());
+
+        //获取回款记录信息(核心)
+        List<RepaymentRecord> repaymentRecords = repaymentRecordService.findByRepaymentIdAndIsInterestAndIsDelete(repaymentService.findByCaseIdAndIsDelete(caseId, false).getId(), false);
+        List<Long> recordIds = repaymentRecords.stream().map(RepaymentRecord::getId).collect(Collectors.toList());
+        List<ContractRepayment> contractRepayments = contractRepaymentService.findByRepaymentRecordIdsAndIsDelete(recordIds);
+
+        List<Long> contractIds = contractRepayments.stream().map(ContractRepayment::getContractId).collect(Collectors.toList());
+        for (Long contractId : contractIds) {
+            double amount = 0.0;//累计回款
+            Contract contract = contractService.findContractById(contractId);
+            for (ContractRepayment contractRepayment : contractRepayments) {
+                if (contractRepayment.getContractId().equals(contractId)) {
+                    RepaymentDetails repaymentDetail = new RepaymentDetails();
+
+                    repaymentDetail.setContractNo(contract.getContractNo());//1
+//                    PawnTicketInfo pawnTicketInfo = pawnTicketService.findByContractIdAndIsDelete(contractId);
+//                    if(pawnTicketInfo!=null){
+//                        repaymentDetail.setPawnTicketNo(pawnTicketInfo.getPawnTicketNo());//2.
+//                        repaymentDetail.setRedeemTicketNo(pawnTicketInfo.getRedeemTicketNo());//10.
+//                    }
+                    repaymentDetail.setLoanTime(disbursementService.getLoanTime(caseId));//3.
+                    repaymentDetail.setCustomerName(customer.getName());//4.
+                    repaymentDetail.setPawnAmount(loanCase.getTotalLoanAmount());//5.
+                    repaymentDetail.setRepayTime(contractRepayment.getCreateTime());//6.
+                    repaymentDetail.setRepayAmount(contractRepayment.getAmount());//7.
+                    amount += contractRepayment.getAmount();
+                    repaymentDetail.setBalance(loanCase.getTotalLoanAmount() - amount);//8.
+                    if(Math.abs(loanCase.getTotalLoanAmount() - amount)<Double.MIN_VALUE)
+                        repaymentDetail.setInterestAmount(contract.getInterestAmount());//9.
+                    List<String> userNames=new ArrayList<>();
+                    StepVO stepVO = stepService.findByStepCodeAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), caseId);
+                    StepVO stepVO1 = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), caseId);
+                    if(stepVO!=null){
+                        userNames.add(userService.findByIdAndIsDelete(stepVO.getUserId1()).getRealName());
+                    }
+                    if(stepVO1!=null){
+                        userNames.add(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getRealName());
+                    }
+                    repaymentDetail.setUserName(userNames);//11.
+                    repaymentDetail.setRecommenderName(recommenderService.getRecommenderById(loanCase.getRecommenderId()).getRecommenderName());//12.
+                    repaymentDetail.setChannelName(loanCase.getChannelName());//13.
+
+                    repaymentDetails.add(repaymentDetail);
+                }
+
+            }
+        }
+
+        return ResultUtil.success("success", repaymentDetails.stream().skip( begin).limit(pageSize).collect(Collectors.toList()));
+    }
+
+    @Override
+    public void exportRepaymentReport(List<RepaymentDetails> repaymentDetails, Integer begin, Integer end, HttpServletResponse response) {
+        //查询概览运营数据,提供给Excel模板文件
+        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileUploadConfig.getUploadDir() + "出账明细.xlsx");
+        try {
+            //基于提供好的模板文件创建一个新的Excel表格对象
+            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
+
+            //获得Excel文件中的一个Sheet页
+            XSSFSheet sheet = excel.getSheet("Sheet1");
+            //TODO:row(从0开始)行,cell(从0开始)获取单元格
+            //获得第1行
+            XSSFRow row = sheet.getRow(1);
+            int index=1;
+            //获取单元格
+            for (int i = begin; i < end; i++) {
+                RepaymentDetails repaymentDetail = repaymentDetails.get(i);
+                row = sheet.getRow(index);
+                row.getCell(0).setCellValue(repaymentDetail.getContractNo());
+                row.getCell(1).setCellValue(repaymentDetail.getPawnTicketNo());
+                row.getCell(2).setCellValue(repaymentDetail.getLoanTime());
+                row.getCell(3).setCellValue(repaymentDetail.getCustomerName());
+                row.getCell(4).setCellValue(repaymentDetail.getPawnAmount());
+                row.getCell(5).setCellValue(repaymentDetail.getRepayTime());
+                row.getCell(6).setCellValue(repaymentDetail.getRepayAmount());
+                row.getCell(7).setCellValue(repaymentDetail.getBalance());
+                row.getCell(8).setCellValue(repaymentDetail.getInterestAmount());
+                row.getCell(9).setCellValue(repaymentDetail.getRedeemTicketNo());
+                row.getCell(10).setCellValue(repaymentDetail.getUserName().toString());
+                row.getCell(11).setCellValue(repaymentDetail.getRecommenderName());
+                row.getCell(12).setCellValue(repaymentDetail.getChannelName());
+                row.getCell(13).setCellValue(repaymentDetail.getComment());
+
+                index++;
+            }
+
+            //通过输出流将文件下载到客户端浏览器中
+            ServletOutputStream out = response.getOutputStream();
+            excel.write(out);
+
+            //关闭资源
+            out.flush();
+            out.close();
+            excel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private String calculateWeekSequence(LocalDate date) {
+        // 获取月份的第一天
+        LocalDate firstDayOfMonth = date.withDayOfMonth(1);
+
+        // 获取第一天是星期几(1=Monday, 7=Sunday)
+        int firstDayOfWeek = firstDayOfMonth.getDayOfWeek().getValue();
+
+        // 计算指定日期是当月第几天
+        int dayOfMonth = date.getDayOfMonth();
+
+        // 计算是第几周 (W1, W2, W3...)TODO:取余计算需要从0开始
+        // 例如:如果1号是周三,那么1-3号属于第一周,4-10号属于第二周...
+        int weekSequence = ((dayOfMonth + firstDayOfWeek - 2) / 7) + 1;
+
+        return "W" + weekSequence;
+    }
+
+    private List<String > getDateAndPlace(StepVO  step , Long caseId){
+        List<String> list = new ArrayList<>();//有两个,第一个是date,第二个是place
+        String date = "";
+        String place = "";
+        String mainUSerName="";
+        String assistUserName="";
+        if (step.getCode().equals(StepPropertyEnum.EVIDENCE_CONFIRMATION.getCode())){
+            List<CollateralPlan> collateralPlans = collateralPlanService.findByCaseIdAndIsDelete(caseId, false);
+
+            for (CollateralPlan plan : collateralPlans){
+                if (plan.getTime()== null || plan.getPlace()== null)
+                    continue;
+                if (plan.getFlag().equals(DecisionEnum.ENTER_WAREHOUSE.getMsg())){
+                    date = date.isEmpty() ? plan.getTime() :date.concat("、").concat(plan.getTime());
+                    place = place.isEmpty() ? plan.getPlace() :place.concat("、").concat(plan.getPlace());
+                }
+            }
+            list.add(date);
+            list.add(place);
+        }else if (step.getCode().equals(StepPropertyEnum.DELIVERY_CONFIRMATION.getCode())){
+            List<CollateralPlan> collateralPlans = collateralPlanService.findByCaseIdAndIsDelete(caseId, false);
+
+            for (CollateralPlan plan : collateralPlans){
+                if (plan.getTime()== null || plan.getPlace()== null)
+                    continue;
+                if (plan.getFlag().equals(DecisionEnum.OUT_WAREHOUSE.getMsg())){
+                    date = date.isEmpty() ? plan.getTime() :date.concat("、").concat(plan.getTime());
+                    place = place.isEmpty() ? plan.getPlace() :place.concat("、").concat(plan.getPlace());
+                }
+            }
+            list.add(date);
+            list.add(place);
+        }else if (step.getCode().equals(StepPropertyEnum.DISBURSE_START.getCode())) {
+            List<Disbursement> disbursements = disbursementService.getDisbursementByCaseId(caseId);
+            for (Disbursement disbursement : disbursements){
+                if(disbursement.getPlannedTime()!=null)
+                    date = date.isEmpty() ? disbursement.getPlannedTime() :date.concat("、").concat(disbursement.getPlannedTime());
+                if(disbursement.getLocationId()!=null){
+                    LocationDatum locationDatum = locationDatumService.findById(disbursement.getLocationId());
+                    place = place.isEmpty() ? locationDatum.getSimpleAddress() :place.concat("、").concat(locationDatum.getSimpleAddress());
+                }
+                User user = userService.findByIdAndIsDelete(disbursement.getMainUserId());
+                if (user !=null)
+                    mainUSerName = mainUSerName.isEmpty() ? user.getRealName() :mainUSerName.concat("、").concat(user.getRealName());
+                User user1 = userService.findByIdAndIsDelete(disbursement.getAssistUserId());
+                if (user1 !=null)
+                    assistUserName = assistUserName.isEmpty() ? user1.getRealName() :assistUserName.concat( "、").concat(user1.getRealName());
+            }
+
+            list.add( date);
+            list.add(place);
+            list.add(mainUSerName);
+            list.add(assistUserName);
+        }else if(step.getCode().equals(StepPropertyEnum.BALANCE_REPAY.getCode())){
+            Repayment repayment = repaymentService.findByCaseIdAndIsDelete(caseId, false);
+            if (repayment!=null){
+                List<RepaymentRecord> records = repaymentRecordService.findByRepaymentIdAndIsInterestAndIsDelete(repayment.getId(), false);
+                for (RepaymentRecord record : records){
+                    if (record.getRepayTime()!= null || record.getRepayLocation()== null)
+                        date = date.isEmpty() ? record.getRepayTime() :date.concat("、").concat(record.getRepayTime());
+                    if(record.getRepayLocation()!=null)
+                        place = place.isEmpty() ? record.getRepayLocation() :place.concat("、").concat(record.getRepayLocation());
+
+                    User user = userService.findByIdAndIsDelete(record.getMainUser());
+                    if (user !=null)
+                        mainUSerName = mainUSerName.isEmpty() ? user.getRealName() :mainUSerName.concat("、").concat(user.getRealName());
+                    User user1 = userService.findByIdAndIsDelete(record.getAssistUser());
+                    if (user1 !=null)
+                        assistUserName = assistUserName.isEmpty() ? user1.getRealName() :assistUserName.concat( "、").concat(user1.getRealName());
+
+                }
+            }
+            list.add( date);
+            list.add(place);
+            list.add(mainUSerName);
+            list.add(assistUserName);
+        }
+        return list;
+    }
+}

+ 28 - 0
src/main/java/com/loan/system/service/Impl/DictionaryServiceImpl.java

@@ -3,10 +3,16 @@ package com.loan.system.service.Impl;
 import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.domain.dto.DictDataDTO;
 import com.loan.system.domain.dto.DictTypeDTO;
+import com.loan.system.domain.dto.query.DictDataQueryDTO;
 import com.loan.system.domain.entity.*;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.repository.*;
 import com.loan.system.service.DictionaryService;
+import com.loan.system.utils.ResultUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
@@ -62,6 +68,13 @@ public class DictionaryServiceImpl implements DictionaryService {
         return dictDataRepository.findByStatus(status);
     }
 
+    @Override
+    public Result listDictData(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<DictData> data = dictDataRepository.findAllAndIsDelete(false, pageable);
+        return ResultUtil.success(data.getTotalElements(),data.getContent());
+    }
+
     @Override
     public List<DictData> listDictData() {
         return dictDataRepository.findAll();
@@ -86,6 +99,13 @@ public class DictionaryServiceImpl implements DictionaryService {
         dictDataRepository.updateById(dataDTO,id,LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
     }
 
+    @Override
+    public Result listDictType(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<DictType> data = dictTypeRepository.findAllAndIsDelete(false, pageable);
+        return ResultUtil.success(data.getTotalElements(),data.getContent());
+    }
+
     @Override
     public List<DictType> listDictType() {
         return dictTypeRepository.findAll();
@@ -117,4 +137,12 @@ public class DictionaryServiceImpl implements DictionaryService {
 
         return contractMap;
     }
+
+    @Override
+    public Result listDictDataByQuery(Integer pageNum, Integer pageSize, DictDataQueryDTO query) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<DictData> data = dictDataRepository.findByQuery(query, pageable);
+
+        return ResultUtil.success(data.getTotalElements(),data.getContent());
+    }
 }

+ 221 - 55
src/main/java/com/loan/system/service/Impl/DisbursementServiceImpl.java

@@ -9,6 +9,7 @@ import com.loan.system.domain.dto.DisbursementStartDTO;
 import com.loan.system.domain.entity.*;
 import com.loan.system.domain.enums.*;
 import com.loan.system.domain.pojo.DateAndAmountPOJO;
+import com.loan.system.domain.pojo.TemplateMessage;
 import com.loan.system.domain.vo.*;
 import com.loan.system.exception.DescribeException;
 import com.loan.system.repository.DisbursementRepository;
@@ -22,10 +23,7 @@ import org.springframework.util.ObjectUtils;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.loan.system.domain.enums.DecisionEnum.PASS;
@@ -49,6 +47,7 @@ public class DisbursementServiceImpl implements DisbursementService {
     private final LocationDatumService locationDatumService;
     private final ContractService contractService;
     private final ContractBankInfoService contractBankInfoService;
+    private final WxService wxService;
 
     @Override
     public DisbursementVO addDisbursement(DisbursementDTO disbursementDTO) {
@@ -134,7 +133,7 @@ public class DisbursementServiceImpl implements DisbursementService {
     }
 
     @Override
-    public void addDisbursementPlan(DisbursementDTO disbursementDTO) {
+    public void addDisbursementPlan(LoanCaseSimpleVO loanCaseSimpleVO, DisbursementDTO disbursementDTO) {
         Long id = disbursementDTO.getId();
         if (id > 0) {
             Disbursement disbursement = disbursementRepository.findByIdAndIsDelete(id, false);
@@ -165,21 +164,39 @@ public class DisbursementServiceImpl implements DisbursementService {
         //修改状态
         stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.PLAN_REPORT.getCode(), BaseContext.getCurrentId(), disbursementDTO.getCaseId());
         if (PlanIsCleared(disbursementDTO.getCaseId())) {
-            //TODO:存在问题
             stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.PLAN_REPORT.getCode(), disbursementDTO.getCaseId());
         }
         //删除驳回记录
         new RedisData(redisTemplate).deleteApprovalByKey(disbursementDTO.getCaseId(), StepPropertyEnum.PLAN_REPORT.getLabel(), StepPropertyEnum.PLAN_REPORT.getCode());
         stepService.tryStartStep(StepPropertyEnum.PLAN_REPORT.getCode(), disbursementDTO.getCaseId());
 
+        //TODO:微信推送预审拒绝消息和通知下一环节:审批员
+        com.loan.system.domain.pojo.TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getId())));//caseId
+        data.put("phrase7", Collections.singletonMap("value",StepPropertyEnum.PLAN_AUDIT.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
+
     }
 
     @Override
-    public void disbursementPlanApproval(ApprovalRecordDTO approvalRecordDTO, Long chargeId, Long assistantId) {
+    public void disbursementPlanApproval(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalRecordDTO approvalRecordDTO, Long chargeId, Long assistantId) {
         Long caseId = approvalRecordDTO.getCaseId();
         //指派下一环节负责人
-        if (assistantId != null)
+        User user = null;
+        if (assistantId != null){
             stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.DISBURSE_START.getCode(), assistantId, caseId);
+            user = userService.findByIdAndIsDelete(assistantId);
+        }
         stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.DISBURSE_START.getCode(), chargeId, caseId);
         disbursementRepository.updateUserById(chargeId, assistantId, approvalRecordDTO.getRecordId());
 
@@ -194,21 +211,25 @@ public class DisbursementServiceImpl implements DisbursementService {
             stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.PLAN_AUDIT.getCode(), caseId);
         stepService.tryStartStep(StepPropertyEnum.PLAN_AUDIT.getCode(), caseId);
 
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepName("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信推送下环节负责人
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.DISBURSE_START.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        User user1 = userService.findByIdAndIsDelete(chargeId);
+        if (user1 != null && user1.getOpenid() != null)
+            wxService.sendTemplateMessage(user1.getOpenid(), message);
+        if (user != null && user.getOpenid() != null)
+            wxService.sendTemplateMessage(user.getOpenid(), message);
     }
 
     @Override
-    public void disbursementPlanApprovalReject(ApprovalRecordDTO approvalRecordDTO) {
+    public void disbursementPlanApprovalReject(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalRecordDTO approvalRecordDTO) {
         Long caseId = approvalRecordDTO.getCaseId();
         //填写驳回
         ApprovalRecord approvalRecord = approvalService.addApprovalRecord(caseId, StepPropertyEnum.PLAN_AUDIT.getCode(), DecisionEnum.REJECT.getMsg(), approvalRecordDTO.getComments());
@@ -220,22 +241,30 @@ public class DisbursementServiceImpl implements DisbursementService {
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.PLAN_AUDIT.getCode(), caseId);
         //new RedisData(redisTemplate).setRejectApprovalRecord(caseId,StepPropertyEnum.PLAN_REPORT.getLabel(),StepPropertyEnum.PLAN_REPORT.getCode(),approvalRecordDTO.getComments());
 
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        StepVO stepVO1 = stepService.findBystepCodeAndCaseId(StepPropertyEnum.PLAN_REPORT.getCode(), caseId);
-//        message.setMobile(userService.findByIdAndIsDelete(stepVO1.getUserId1()).getMobile());
-//        message.setUserRole(null);
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setstepCode(StepPropertyEnum.PLAN_AUDIT.getCode());
-//        message.setRelatedId(caseId);
-//        message.setRelatedType("");
-        //       messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信通知上环节负责人
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value",StepPropertyEnum.PLAN_REPORT.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        Disbursement disbursement = disbursementRepository.findByIdAndIsDelete(approvalRecordDTO.getRecordId(), false);
+        User user = userService.findByIdAndIsDelete(disbursement.getOperatorUserId());
+        if (user != null && user.getOpenid() != null)
+            wxService.sendTemplateMessage(user.getOpenid(), message);
+
     }
 
     @Override
-    public void commitDisbursement(DisbursementStartDTO disbursementStartDTO, Boolean isComplete) {
+    public void commitDisbursement(LoanCaseSimpleVO loanCaseSimpleVO, DisbursementStartDTO disbursementStartDTO, Boolean isComplete) {
+        Disbursement disbursement = disbursementRepository.findByIdAndIsDelete(disbursementStartDTO.getDisbursementRecordDTO().getDisbursementId(),false);
+        if (disbursement.getMainUserId()!=null && !disbursement.getMainUserId().equals(BaseContext.getCurrentId())
+        || (disbursement.getAssistUserId() != null && !disbursement.getAssistUserId().equals(BaseContext.getCurrentId())))
+            throw new DescribeException(STEP_USER_NOT_EXPECTED);
+
         DisbursementRecordDTO disbursementRecordDTO = disbursementStartDTO.getDisbursementRecordDTO();
         Long caseId = disbursementRecordDTO.getCaseId();
         Long recordId = disbursementRecordDTO.getId();
@@ -325,37 +354,46 @@ public class DisbursementServiceImpl implements DisbursementService {
                 break;
             }
         }
-        if (flag || disburseIsComplete(caseId))
-            stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.DISBURSE_START.getCode(), caseId);
+        if (flag || disburseIsComplete(caseId)){
+            updateStatusOnDisbursement(caseId);
+        }
         stepService.tryStartStep(StepPropertyEnum.DISBURSE_START.getCode(), caseId);
 
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepName("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信通知下一环节:审批员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.DISBURSE_AUDIT.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
 
     }
 
-    private boolean disburseIsComplete(Long caseId) {
+    private boolean disburseIsComplete(Long caseId) {//如果刚好金额都匹配上,则表示出款完成
         List<DisbursementRecord> records = disbursementRecordService.findRecordByCaseId(caseId);
         Double totalAmount = 0.0;
         for (DisbursementRecord record : records)
             totalAmount += record.getAmount();
         LoanCaseSimpleVO l = loanService.findLoanCaseSimpleByIdAndIsDelete(caseId, false);
 
-        return Math.abs(totalAmount - l.getTotalLoanAmount())<Double.MIN_VALUE;
+        if(Math.abs(totalAmount - l.getTotalLoanAmount())<Double.MIN_VALUE){
+            contractService.updateIsDisbursementByCaseId(caseId);//将全部设置为已更新
+            return true;
+        }
+        return false;
 
     }
 
     @Override
-    public void disbursementApproval(ApprovalRecordDTO approvalRecordDTO, String decision) {
+    public void disbursementApproval(LoanCaseSimpleVO loanCaseSimpleVO, ApprovalRecordDTO approvalRecordDTO, String decision) {
         Long caseId = approvalRecordDTO.getCaseId();
         //填写审批意见
         ApprovalRecord approvalRecord = approvalService.addApprovalRecord(caseId, StepPropertyEnum.DISBURSE_AUDIT.getCode(), decision, approvalRecordDTO.getComments());
@@ -376,12 +414,46 @@ public class DisbursementServiceImpl implements DisbursementService {
             if (ApprovalIsCompleted(caseId, StepPropertyEnum.DISBURSE_AUDIT.getCode()) && step.getStatus().equals(StepEnum.COMPLETED.getMsg()))
                 stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.DISBURSE_AUDIT.getCode(), caseId);
             stepService.tryStartStep(StepPropertyEnum.DISBURSE_AUDIT.getCode(), caseId);
+
+            //TODO:微信通知下一环节:出款确认
+            TemplateMessage message = new TemplateMessage();
+            Map<String, Map<String, String>> data = new HashMap<>();
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.FINANCE_DISBURSE.getLabel()));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+            Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+            data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+            message.setData(data);
+            List<User> users = userService.findByRoleAndIsDelete(Arrays.asList( RoleEnum.FINANCE.getMsg()), false);
+            for (User user : users) {
+                if (user.getOpenid() != null)
+                    wxService.sendTemplateMessage(user.getOpenid(), message);
+            }
         } else {
             new RedisData(redisTemplate).setRejectApprovalRecord(caseId, StepPropertyEnum.DISBURSE_START.getLabel(), StepPropertyEnum.DISBURSE_START.getCode(), approvalRecordDTO.getComments());
 
             //修改状态
             stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.DISBURSE_START.getCode(), caseId);//重新出款
             stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.DISBURSE_AUDIT.getCode(), caseId);
+
+            //TODO:微信推送预审拒绝消息和通知上环节负责人
+            TemplateMessage message = new TemplateMessage();
+            Map<String, Map<String, String>> data = new HashMap<>();
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.DISBURSE_START.getLabel()));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+            Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+            data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+            message.setData(data);
+            Disbursement disbursement = disbursementRepository.findByIdAndIsDelete(record.getDisbursementId(), false);
+            User user1 = userService.findByIdAndIsDelete(disbursement.getMainUserId());
+            User user2 = userService.findByIdAndIsDelete(disbursement.getAssistUserId());
+            if (user1 != null && user1.getOpenid() != null)
+                wxService.sendTemplateMessage(user1.getOpenid(), message);
+            if (user2 != null && user2.getOpenid() != null)
+                wxService.sendTemplateMessage(user2.getOpenid(), message);
         }
     }
 
@@ -490,14 +562,21 @@ public class DisbursementServiceImpl implements DisbursementService {
                     userVOMap2.put(plan.getId(), u);
                 }
 
-                List<ContractDisbursement> contractDisbursements = contractDisbursementService.findByRecordIdAndIsPlan(plan.getId(), true);
+                planVOs.add(disbursementVO);
+            }
+            for (DisbursementVO planVO : planVOs){//重新再计算每个计划的金额(即使又进行了循环,但速度也比访问数据库快)
+                List<ContractDisbursement> contractDisbursements = contractDisbursementService.findByRecordIdAndIsPlan(planVO.getId(), true);
                 Map<Long, Double> contractAndAmount = new HashMap<>();
+                Map<Long, Double> contractAndAmount1 = new HashMap<>();
                 for (ContractDisbursement contractDisbursement : contractDisbursements) {
                     contractAndAmount.merge(contractDisbursement.getContractId(), contractDisbursement.getAmount(), Double::sum);
-                }
-                disbursementVO.setContractAndPlanAmount(contractAndAmount);
 
-                planVOs.add(disbursementVO);
+                    ApprovalRecordVO approvalRecordVO = planVO.getApprovalRecordVO();
+                    if(approvalRecordVO!=null && approvalRecordVO.getDecision().equals(PASS.getMsg()))
+                        contractAndAmount1.merge(contractDisbursement.getContractId(), contractDisbursement.getAmount(), Double::sum);
+                }
+                planVO.setContractAndPlanAmount(contractAndAmount);
+                planVO.setContractAndPlanAmount1(contractAndAmount1);
             }
             disbursementDetailVO.setDisbursementPlans(planVOs);
             disbursementDetailVO.setCurrentPlanAmount(currentPlanAmount);
@@ -508,6 +587,7 @@ public class DisbursementServiceImpl implements DisbursementService {
             double currentAmount = 0.0;
             double currentAmount1 = 0.0;
             Map<Long, Double> contractAndCurrentAmount = new HashMap<>();//合同的目前总金额
+            Map<Long, Double> contractAndCurrentAmount1 = new HashMap<>();//合同的目前总金额
             for (int i = 0; i < records.size(); i++) {
                 DisbursementRecordVO record = records.get(i);
                 List<ApprovalRecordVO> financeApprovalRecordVOs = record.getFinanceApprovalRecordVOs();
@@ -518,7 +598,7 @@ public class DisbursementServiceImpl implements DisbursementService {
                 Long recordId = record.getId();
                 List<ContractDisbursement> contractDisbursements = contractDisbursementService.findByRecordIdAndIsPlan(recordId, false);
 
-                Map<Long, Double> contractAndAmount = new HashMap<>();
+                Map<Long, Double> contractAndAmount = new HashMap<>();//单个计划
                 for (ContractDisbursement contractDisbursement : contractDisbursements) {
                     //对合同的金额做累加
                     contractAndCurrentAmount.merge(contractDisbursement.getContractId(), contractDisbursement.getAmount(), Double::sum);
@@ -542,6 +622,16 @@ public class DisbursementServiceImpl implements DisbursementService {
             disbursementDetailVO.setDisbursementRecords(records);
             // 4.private Map<Long,Double> contractAndCurrentAmount;//目前合同对应的出款金额
             disbursementDetailVO.setContractAndCurrentAmount(contractAndCurrentAmount);
+            for (DisbursementRecordVO record1 : records){
+                List<ApprovalRecordVO> financeApprovalRecordVOs = record1.getFinanceApprovalRecordVOs();
+                if(financeApprovalRecordVOs!=null && financeApprovalRecordVOs.get(financeApprovalRecordVOs.size()-1).getDecision().equals(PASS.getMsg())){
+                    Map<Long, Double> contractIdAndAmount = record1.getContractIdAndAmount();
+                    contractIdAndAmount.forEach((contractId, amount) -> {
+                        contractAndCurrentAmount1.merge(contractId, amount, Double::sum);
+                    });
+                }
+            }
+            disbursementDetailVO.setContractAndCurrentAmount1(contractAndCurrentAmount1);
             // 6.private Double currentAmount;//目前金额
             disbursementDetailVO.setCurrentAmount(currentAmount);
             disbursementDetailVO.setCurrentAmount1(currentAmount1);
@@ -646,7 +736,7 @@ public class DisbursementServiceImpl implements DisbursementService {
     }
 
     @Override
-    public void financeApproval(ApprovalRecordDTO approvalRecordDTO, String decision) {
+    public void financeApproval(LoanCaseSimpleVO loanCaseSimpleVO,ApprovalRecordDTO approvalRecordDTO, String decision) {
         Long caseId = approvalRecordDTO.getCaseId();
         //填写审批意见
         ApprovalRecord approvalRecord = approvalService.addApprovalRecord(caseId, StepPropertyEnum.FINANCE_DISBURSE.getCode(), decision, approvalRecordDTO.getComments());
@@ -657,6 +747,7 @@ public class DisbursementServiceImpl implements DisbursementService {
         disbursementRecordDTO.setId(record.getId());
         String approvalIds = record.getFinanceApprovalIds() == null ? approvalRecord.getId().toString() : record.getFinanceApprovalIds() + "," + approvalRecord.getId();
         disbursementRecordDTO.setFinanceApprovalIds(approvalIds);
+        disbursementRecordDTO.setCreateTime(approvalRecordDTO.getDisbursementTime());
         disbursementRecordService.updateRecordById(disbursementRecordDTO);
 
         //修改状态
@@ -680,13 +771,88 @@ public class DisbursementServiceImpl implements DisbursementService {
             if (ApprovalIsCompleted(caseId, StepPropertyEnum.FINANCE_DISBURSE.getCode()) && step.getStatus().equals(StepEnum.COMPLETED.getMsg()))
                 stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.FINANCE_DISBURSE.getCode(), caseId);
             stepService.tryStartStep(StepPropertyEnum.FINANCE_DISBURSE.getCode(), caseId);
+
+            TemplateMessage message = new TemplateMessage();
+            Map<String, Map<String, String>> data = new HashMap<>();
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.DISBURSE_CONFIRM.getLabel()));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+            Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+            data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+            message.setData(data);
+            List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.ASSIST_SALES.getMsg(), RoleEnum.LEAD_SALES.getMsg()), false);
+            for (User user : users)
+                if (user.getOpenid() != null)
+                    wxService.sendTemplateMessage(user.getOpenid(), message);
+
         } else {
             new RedisData(redisTemplate).setRejectApprovalRecord(caseId, StepPropertyEnum.DISBURSE_START.getLabel(), StepPropertyEnum.DISBURSE_START.getCode(), approvalRecordDTO.getComments());
 
             //修改状态
             stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.DISBURSE_START.getCode(), caseId);//重新出款
             stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.FINANCE_DISBURSE.getCode(), caseId);
+
+            //TODO:微信推送预审拒绝消息和通知上环节负责人
+            TemplateMessage message = new TemplateMessage();
+            Map<String, Map<String, String>> data = new HashMap<>();
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.DISBURSE_START.getLabel()));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+            Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+            data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+            message.setData(data);
+            Disbursement disbursement = disbursementRepository.findByIdAndIsDelete(record.getDisbursementId(), false);
+            User user1 = userService.findByIdAndIsDelete(disbursement.getMainUserId());
+            User user2 = userService.findByIdAndIsDelete(disbursement.getAssistUserId());
+            if (user1 != null && user1.getOpenid() != null)
+                wxService.sendTemplateMessage(user1.getOpenid(), message);
+            if (user2 != null && user2.getOpenid() != null)
+                wxService.sendTemplateMessage(user2.getOpenid(), message);
+        }
+    }
+
+    @Override
+    public void completeDisburse(Long caseId) {
+        //1.检查各环节是否有正在进行的事务
+        List<Disbursement> disbursements = disbursementRepository.findDisbursementsByCaseId(caseId,false);
+        if (disbursements==null)//无出款计划,报错
+            throw new DescribeException(ILLEGAL_OPERATION);
+        for (Disbursement disbursement : disbursements){
+            ApprovalRecord approvalRecord = approvalService.findByIdAndIsDelete(disbursement.getApprovalId());
+            if (approvalRecord==null || approvalRecord.getDecision().equals(DecisionEnum.REJECT.getMsg()))//有计划但无审批或驳回,报错
+                throw new DescribeException(ILLEGAL_OPERATION_1);
+        }
+        List<DisbursementRecordVO> records = disbursementRecordService.findRecordVOByCaseId(caseId);
+        if (records==null || records.size()!=disbursements.size())
+            throw new DescribeException(ILLEGAL_OPERATION_2);//有计划但还未出款,报错
+        for (DisbursementRecordVO disbursementRecordVO: records){
+            if (disbursementRecordVO.getApprovalRecordVOs()==null || disbursementRecordVO.getApprovalRecordVOs().get(disbursementRecordVO.getApprovalRecordVOs().size()-1).getDecision().
+                    equals(DecisionEnum.REJECT.getMsg()))
+                throw new DescribeException(ILLEGAL_OPERATION_3);//有审批
+            if (disbursementRecordVO.getFinanceApprovalRecordVOs()==null || disbursementRecordVO.getFinanceApprovalRecordVOs().get(disbursementRecordVO.getFinanceApprovalRecordVOs().size()-1).getDecision().
+                    equals(DecisionEnum.REJECT.getMsg()))
+                throw new DescribeException(ILLEGAL_OPERATION_4);//有财务审批
+        }
+
+        //2.更新合同信息
+        contractService.updateIsDisbursementByCaseId(caseId);
+
+        //3.更新各环节
+        stepService.updateStatusByCaseIdAndParentCode(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.DISBURSE_PARENT.getCode(),caseId);
+
+        //4.开启回款
+        stepService.tryStartStep(StepPropertyEnum.DISBURSE_CONFIRM.getCode(), caseId);
+    }
+
+    void updateStatusOnDisbursement(Long caseId){
+        List<StepVO> stepVOs = stepService.findByStepCodesAndCaseId(Arrays.asList(StepPropertyEnum.PLAN_REPORT.getCode(), StepPropertyEnum.PLAN_AUDIT.getCode()), caseId);
+        for (StepVO stepVO : stepVOs){
+            if (stepVO.getStatus().equals(StepEnum.PROCESS.getMsg()))
+                stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), stepVO.getCode(), caseId);
         }
+        stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.DISBURSE_START.getCode(), caseId);
     }
 
     private Boolean PlanIsCleared(Long caseId) {

+ 236 - 8
src/main/java/com/loan/system/service/Impl/DocumentServiceImpl.java

@@ -1,26 +1,77 @@
 package com.loan.system.service.Impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import com.aliyun.oss.model.OSSObject;
+import com.loan.system.controller.wechat.OssFileController;
+import com.loan.system.domain.dto.BatchDownloadDTO;
 import com.loan.system.domain.dto.DocumentDTO;
+import com.loan.system.domain.dto.query.DocumentQueryDTO;
+import com.loan.system.domain.entity.Customer;
 import com.loan.system.domain.entity.Document;
+import com.loan.system.domain.enums.ExceptionEnum;
+import com.loan.system.domain.pojo.Result;
+import com.loan.system.domain.vo.CustomerVO;
 import com.loan.system.domain.vo.DocumentVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
 import com.loan.system.repository.DocumentRepository;
+import com.loan.system.service.CustomerService;
 import com.loan.system.service.DocumentService;
+import com.loan.system.service.LoanCaseService;
+import com.loan.system.service.LoanService;
+import com.loan.system.utils.ResultUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 @Service
+@RequiredArgsConstructor
+@Slf4j
 public class DocumentServiceImpl implements DocumentService {
     private final DocumentRepository documentRepository;
+    private final OssService ossService;
+    Map<String, String> dictTypeMap = new HashMap<String, String>() {{
+        put("idCard", "借款人身份证");
+        put("customers1IdCard", "共同借款人1身份证");
+        put("customers2IdCard", "共同借款人2身份证");
+        put("householdRegister", "户口本照片");
+        put("marriageCertificate", "婚姻证明");
+        put("propertyCertificate", "房产证");
+        put("ownershipCertificate", "产调证明");
+        put("microCourtInquiry", "微法院查询");
+        put("businessLicense", "营业执照");
+        put("personalCredit", "个人征信");
+        put("contract", "合同");
+        put("receipt", "当票");
+        put("otherCertificates", "他项权证");
+        put("contractAttachment", "合同其他附件");
+        put("otherAttachments", "其他附件");
+        put("bankReceipt", "银行回单");
+        put("settlementCertificate", "借款结清证明");
+        put("evidenceCollectionConfirm", "押品入库证明");
+        put("deliveryConfirm", "押品出库证明");
+    }};
 
-    @Autowired
-    public DocumentServiceImpl(DocumentRepository documentRepository) {
-        this.documentRepository = documentRepository;
-    }
     @Override
     public List<DocumentVO> findByCaseId(Long caseId) {
         return BeanUtil.copyToList(documentRepository.findByCaseId(caseId), DocumentVO.class);
@@ -54,12 +105,189 @@ public class DocumentServiceImpl implements DocumentService {
     }
 
     @Override
-    public List<Document> findAll() {
-        return documentRepository.findAll();
+    public void deleteFileByIds(List<Long> ids) {
+        documentRepository.deleteByIds(ids);
+    }
+
+    @Override
+    public Result findAll(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<Document> data = documentRepository.findAllAndIdDelete(false, pageable);
+        return ResultUtil.success(data.getTotalElements(),BeanUtil.copyToList(data.getContent(), DocumentVO.class));
     }
 
     @Override
     public List<DocumentVO> findByFileTypesAndCaseId(List<String> fileTypes, Long caseId) {
         return BeanUtil.copyToList(documentRepository.findByFileTypesAndCaseIdAndIsDelete(fileTypes, caseId, false), DocumentVO.class);
     }
-}
+
+    @Override
+    public Result uploadFileToOss(MultipartFile file, Long caseId, String fileType, Map<String, String> isDelete) {
+        // 处理待删除的文件
+        Iterator<Map.Entry<String, String>> iterator = isDelete.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<String, String> entry = iterator.next();
+            Long id = Long.parseLong(entry.getKey());
+            Integer value = Integer.parseInt(entry.getValue());
+            Document document = findById(id);
+            if (ObjectUtils.isEmpty(document))
+                break;
+
+            if (value != 0) {
+                log.info("删除文件: {}", id);
+                deleteFileById(id);
+                // 从OSS删除文件
+                ossService.deleteFile(document.getFileName());
+            }
+        }
+
+        if (file == null)
+            return ResultUtil.success("success");
+
+        String originalName = file.getOriginalFilename();
+        String ext = FilenameUtils.getExtension(originalName).toLowerCase(Locale.ROOT);
+
+        // 生成新的文件名
+        String randomUUID = UUID.randomUUID().toString();
+        String newFileName = String.format("%d/%s/%s.%s", caseId, fileType, randomUUID, ext);
+
+        // 上传到OSS
+        String fileUrl="";
+        try {
+            fileUrl = ossService.uploadFile(file.getInputStream(), newFileName);
+        }catch (Exception e){
+            return ResultUtil.error(ExceptionEnum.DIRECTORY_CREATE_ERROR);
+        }
+
+        Document document = new Document();
+        document.setCaseId(caseId);
+        document.setFileName(randomUUID+"."+ext);
+        document.setOriginName(originalName);
+        document.setFilePath(fileUrl); // 存储OSS文件URL
+        document.setFileSize(file.getSize());
+        document.setDocType(ext);
+        document.setDictType(fileType);
+        document.setIsDelete(false);
+        document.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        document.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        DocumentVO documentVO = uploadFile(document);
+
+        return ResultUtil.success("上传成功", documentVO);
+    }
+
+    @Override
+    public void downloadFileFromOss(Long caseId, String fileType, String filename, HttpServletResponse response) {
+        try {
+            String fullFileName = String.format("%d/%s/%s", caseId, fileType, filename);
+            // 从OSS获取文件
+            OSSObject ossObject = ossService.downloadFile(fullFileName);
+
+            if (ossObject == null) {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在");
+                return;
+            }
+
+            // 设置响应头
+            response.setContentType(ossObject.getObjectMetadata().getContentType());
+            response.setContentLength((int) ossObject.getObjectMetadata().getContentLength());
+
+            // 如果需要浏览器直接显示文件而不是下载,可以设置inline
+            // 如果需要强制下载,可以设置attachment
+            String disposition = "inline; filename=\"" + URLEncoder.encode(dictTypeMap.get(fileType) +"-"+ filename, "UTF-8") + "\"";
+            response.setHeader("Content-Disposition", disposition);
+
+            // 将文件内容写入响应流
+            try (InputStream inputStream = ossObject.getObjectContent();
+                 OutputStream outputStream = response.getOutputStream()) {
+
+                byte[] buffer = new byte[8192];
+                int bytesRead;
+                while ((bytesRead = inputStream.read(buffer)) != -1) {
+                    outputStream.write(buffer, 0, bytesRead);
+                }
+                outputStream.flush();
+            }
+
+        } catch (Exception e) {
+            try {
+                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "文件读取失败: " + e.getMessage());
+            } catch (IOException ioException) {
+                // 处理发送错误响应时的异常
+            }
+        }
+    }
+
+
+    @Override
+    public void batchDownloadFilesFromOss(BatchDownloadDTO batchDownloadDTO, HttpServletResponse response) throws  IOException{
+        List<DocumentDTO> documentDTOList = batchDownloadDTO.getDocumentDTOList();
+
+        // 设置响应头
+        String zipFilename = "批量下载_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + ".zip";
+        response.setContentType("application/zip");
+        response.setCharacterEncoding("UTF-8");
+        response.setHeader("Content-Disposition",
+                "attachment; filename=\"" + URLEncoder.encode(zipFilename, "UTF-8") + "\"");
+
+        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
+            byte[] buffer = new byte[8192];
+            int bytesRead;
+
+            for (int i = 0; i < documentDTOList.size(); i++) {
+                DocumentDTO documentDTO = documentDTOList.get(i);
+                String filename = documentDTO.getFileName();
+                Long caseId = documentDTO.getCaseId();
+                String fileType = documentDTO.getDictType();
+
+                try {
+                    String fullFileName = String.format("%d/%s/%s", caseId, fileType, filename);
+                    OSSObject ossObject = ossService.downloadFile(fullFileName);
+
+                    if (ossObject == null) {
+                        // 文件不存在,可以记录日志或添加错误文件到ZIP
+                        continue;
+                    }
+
+                    // 创建ZIP条目
+                    ZipEntry zipEntry = new ZipEntry(dictTypeMap.get(fileType) +"-"+ documentDTO.getOriginName());
+                    // 可选:设置条目的创建时间
+                    zipEntry.setTime(ossObject.getObjectMetadata().getLastModified().getTime());
+                    zipOut.putNextEntry(zipEntry);
+
+                    // 将文件内容写入ZIP
+                    try (InputStream inputStream = ossObject.getObjectContent()) {
+                        while ((bytesRead = inputStream.read(buffer)) != -1) {
+                            zipOut.write(buffer, 0, bytesRead);
+                        }
+                    }
+                    zipOut.closeEntry();
+
+                } catch (Exception e) {
+                    // 记录单个文件下载失败,继续处理其他文件
+                    // 可以在这里添加错误日志
+                    e.printStackTrace();
+                }
+            }
+
+            zipOut.finish();
+            zipOut.flush();
+
+        } catch (Exception e) {
+            try {
+                response.reset(); // 重置响应
+                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                        "打包文件失败: " + e.getMessage());
+            } catch (IOException ioException) {
+                // 处理发送错误响应时的异常
+            }
+        }
+    }
+
+    @Override
+    public Result queryFiles(Integer pageNum, Integer pageSize, DocumentQueryDTO documentQueryDTO) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<Document> data = documentRepository.findByQuery(documentQueryDTO, pageable);
+
+        return ResultUtil.success(data.getTotalElements(), data.getContent());
+    }
+}

+ 90 - 39
src/main/java/com/loan/system/service/Impl/LoanServiceImpl.java

@@ -1,40 +1,33 @@
 package com.loan.system.service.Impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
 import com.loan.system.context.BaseContext;
 import com.loan.system.domain.dto.*;
+import com.loan.system.domain.dto.query.LoanCaseQueryDTO;
 import com.loan.system.domain.entity.*;
 import com.loan.system.domain.enums.*;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.pojo.TemplateMessage;
 import com.loan.system.domain.vo.*;
 import com.loan.system.exception.DescribeException;
-import com.loan.system.repository.CustomerOtherRepository;
-import com.loan.system.repository.CustomerRepository;
 import com.loan.system.repository.LoanRepository;
 import com.loan.system.service.*;
 import com.loan.system.utils.RedisData;
+import com.loan.system.utils.ResultUtil;
 import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
 
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static com.loan.system.domain.enums.ExceptionEnum.STEP_HAS_NOT_PROCESS;
-import static com.loan.system.domain.enums.ExceptionEnum.STEP_USER_NOT_EXPECTED;
-
 @Service
 @RequiredArgsConstructor
 public class LoanServiceImpl implements LoanService {
@@ -51,6 +44,7 @@ public class LoanServiceImpl implements LoanService {
     private final PawnTicketService pawnTicketService;
     private final StringRedisTemplate stringRedisTemplate;
     private final WxService wxService;
+    private final EsignService esignService;
 
     @Override
     public List<LoanCaseVO> findLoanCaseByIsComplete(Integer pageNum, Integer pageSize, String isComplete, boolean isDelete) {
@@ -169,16 +163,6 @@ public class LoanServiceImpl implements LoanService {
         return loanCaseVO;
     }
 
-    @Override
-    public LoanCase findLoanCaseByIdAndIsDelete(Long caseId, boolean isDelete) {
-        return loanRepository.findLoanCaseById(caseId, isDelete);
-    }
-
-    @Override
-    public void updateUpdatetimeByIdAndIsDeleted(Long id, boolean isDelete) {
-        loanRepository.updateUpdatetimeByIdAndIsDeleted(id, false, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-    }
-
     @Override
     public void logic_delete(Long id) {
         loanRepository.logic_delete(id, true, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
@@ -225,7 +209,14 @@ public class LoanServiceImpl implements LoanService {
     }
 
     @Override
-    public void updateIsCompleteByCaseId(String msg, Long caseId) {
+    public void updateIsCompleteByCaseId(String msg,Integer stepCode, Long caseId) {
+        if (stepCode!=null && stepCode.equals(StepPropertyEnum.CONTRACT_SIGN.getCode())){
+            List<EsignFlowVO> esignFlowVOS = esignService.findByCaseId(caseId);
+            for (EsignFlowVO esignFlowVO:esignFlowVOS){
+                if (esignFlowVO.getFlowStatus()!=2)
+                    throw new DescribeException(ExceptionEnum.CONTRACT_SIGN_NOT_COMPLETE);
+            }
+        }
         String updateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
         loanRepository.updateIsCompleteByCaseId(msg, caseId, updateTime);
     }
@@ -268,14 +259,14 @@ public class LoanServiceImpl implements LoanService {
 
     //TODO:controller使用
     @Override
-    public List<LoanCaseVO> listLoanCaseByStepCode(Integer stepCode) {
+    public List<LoanCaseVO> listLoanCaseByStepCode(Integer stepCode, Integer pageNum, Integer pageSize) {
         //根据角色返回业务列表,业务员返回全部未完成、审批员与财务员仅展示未审批或未财务审批的人物
         List<Long> ids = new ArrayList<>();
         List<StepVO> currentSteps = new ArrayList<>();
-        if(stepCode.equals(StepPropertyEnum.CASE_ARCHIVE.getCode())){
+        if(stepCode.equals(StepPropertyEnum.CASE_ARCHIVE_PARENT.getCode())){
             //归档环节仅显示已完成的业务
             ids = loanRepository.findIdsByIsCompleteAndIsDelete(DecisionEnum.COMPLETE.getMsg(), false);
-            List<StepVO> stepVOS = stepService.listByStepCodeAndCaseIds(ids, stepCode);
+            List<StepVO> stepVOS = stepService.listByStepCodeAndCaseIds(ids, StepPropertyEnum.CASE_ARCHIVE.getCode());
             currentSteps.addAll(stepVOS);
 
         }else{
@@ -294,11 +285,10 @@ public class LoanServiceImpl implements LoanService {
                     if (step.getParentCode() == 0) continue;
 
                     //同一用户只能以一个角色处理同一单业务:如果当前环节是第二个角色处理过该单业务,则跳过(true)
-//                flag=stepService.hasRolesInCase(caseId,BaseContext.getCurrentId(),step.getCode());
+                //flag=stepService.hasRolesInCase(caseId,BaseContext.getCurrentId(),step);
 
                     //只保存正在处理的
-                    Step parent = stepService.findStepByCodeAndCaseId(step.getParentCode(), caseId);
-                    if (step.getStatus().equals(StepEnum.PROCESS.getMsg()) && parent.getCode().equals(stepCode) && !flag) {
+                    if (step.getStatus().equals(StepEnum.PROCESS.getMsg()) && step.getParentCode().equals(stepCode) && !flag) {
                         if (step.getCode().equals(StepPropertyEnum.CASE_COMPLETE.getCode())) {//仅显示结清(回款完成)的”业务终结“环节
                             Step step1 = stepService.findStepByCodeAndCaseId(StepPropertyEnum.BALANCE_REPAY.getCode(), caseId);
                             if (step1 != null && step1.getStatus().equals(StepEnum.COMPLETED.getMsg())) {
@@ -422,8 +412,14 @@ public class LoanServiceImpl implements LoanService {
 //            Long userId=stepService.findByStepNameAndCaseId(StepPropertyEnum.BUSINESS_ACCEPT.getCode(), loanCase.getId()).getUserId1();
 //            loanCaseVO.setUserName(userService.findByIdAndIsDelete(userId).getUsername());
             StepVO stepVO = currentSteps.get(i);
-            if (stepVO.getCode().equals(StepPropertyEnum.BUSINESS_ACCEPT.getCode()) && stepVO.getStatus().equals(StepEnum.COMPLETED.getMsg()))
-                stepVO.setStepName("预审状态");
+            if (stepVO.getCode().equals(StepPropertyEnum.BUSINESS_ACCEPT.getCode()) && stepVO.getStatus().equals(StepEnum.COMPLETED.getMsg())){
+                StepVO approvalStep = stepService.findByStepCodeAndCaseId(StepPropertyEnum.APPROVAL.getCode(), loanCase.getId());
+                StepVO preApprovalStep = stepService.findByStepCodeAndCaseId(StepPropertyEnum.PRE_TRIAL.getCode(), loanCase.getId());
+                if (preApprovalStep.getStatus().equals(StepEnum.PROCESS.getMsg()))
+                    stepVO.setStepName("预审状态");
+                if (approvalStep.getStatus().equals(StepEnum.PROCESS.getMsg()))
+                    stepVO.setStepName("审批状态");
+            }
             loanCaseVO.setStep(currentSteps.get(i));
             User user = userService.findByIdAndIsDelete(currentSteps.get(i).getUserId1());
             if (user != null) {
@@ -613,7 +609,7 @@ public class LoanServiceImpl implements LoanService {
 
             //TODO:8.微信推送预审通过消息和通知下一环节
             List<User> users = new ArrayList<>();
-            String stepName = "待处理环节为:";
+            String stepName = "";
             if (isSkip) {
                 users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
                 stepName = stepName.concat(StepPropertyEnum.APPROVAL.getLabel());
@@ -623,10 +619,11 @@ public class LoanServiceImpl implements LoanService {
             }
             TemplateMessage message = new TemplateMessage();
             Map<String, Map<String, String>> data = new HashMap<>();
-            data.put("thing1", Collections.singletonMap("value", loanCaseDTO.getBusinessType()));
-            data.put("thing3", Collections.singletonMap("value", customerDTO.getName()));
-            data.put("amount4", Collections.singletonMap("value", String.valueOf(loanCaseDTO.getTotalLoanAmount())));
-            data.put("things5", Collections.singletonMap("value", stepName));
+            data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+            data.put("phrase7", Collections.singletonMap("value", stepName));//当前环节
+            data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseDTO.getTotalLoanAmount())));//业务类型
+            data.put("thing3", Collections.singletonMap("value", customerDTO.getName()));//客户名称
+            data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseDTO.getTotalLoanAmount())));//典当金额
             message.setData(data);
             for (User user : users) {
                 if (user.getId().equals(BaseContext.getCurrentId())) continue;
@@ -640,7 +637,7 @@ public class LoanServiceImpl implements LoanService {
     @Override
     public void loanCaseComplete(Long caseId, Boolean isCancel, Map<String, String> pawnList) {
         if (!isCancel) {
-            updateIsCompleteByCaseId(DecisionEnum.COMPLETE.getMsg(), caseId);
+            updateIsCompleteByCaseId(DecisionEnum.COMPLETE.getMsg(),StepPropertyEnum.CASE_ARCHIVE.getCode(), caseId);
 
             //保存当票信息
             Iterator<Map.Entry<String, String>> iterator = pawnList.entrySet().iterator();
@@ -659,11 +656,14 @@ public class LoanServiceImpl implements LoanService {
 
             stepService.tryStartStep(StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
         } else {
-            updateIsCompleteByCaseId(DecisionEnum.PROCESS.getMsg(), caseId);
+            updateIsCompleteByCaseId(DecisionEnum.PROCESS.getMsg(), StepPropertyEnum.CASE_ARCHIVE.getCode(),caseId);
 
-            stepService.deleteUserRecordByCaseIdAndStepCode(StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
-            stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.REPAY_PARENT.getCode(), caseId);
-            stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
+            StepVO step = stepService.findByStepCodeAndCaseId(StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
+            if (step!=null&&step.getStatus().equals(StepEnum.COMPLETED.getMsg())){
+                stepService.deleteUserRecordByCaseIdAndStepCode(StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
+                stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.REPAY_PARENT.getCode(), caseId);
+                stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.CASE_COMPLETE.getCode(), caseId);
+            }
             stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.CASE_ARCHIVE.getCode(), caseId);
 
         }
@@ -719,6 +719,57 @@ public class LoanServiceImpl implements LoanService {
         }
     }
 
+    @Override
+    public Result listLoanCaseInfo(Integer pageNum, Integer pageSize, String isComplete) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        List<LoanCaseAdminVO> loanCaseVO = new ArrayList<>();
+        Page<LoanCase> loanCases;
+        if (isComplete == null){
+             loanCases = loanRepository.findByIsDelete(false, pageable);
+        }else {
+            loanCases = loanRepository.findByIsCompleteAndIsDelete(isComplete, false, pageable);
+        }
+
+        for (LoanCase loanCase : loanCases.getContent()){
+            LoanCaseAdminVO loanCaseVO1 = BeanUtil.copyProperties(loanCase, LoanCaseAdminVO.class);
+            loanCaseVO1.setCustomer(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false));
+            loanCaseVO1.setRecommender(BeanUtil.copyProperties(recommender.getRecommenderById(loanCase.getRecommenderId()), BizRecommenderVO.class));
+            loanCaseVO.add(loanCaseVO1);
+        }
+
+        return ResultUtil.success(loanCases.getTotalElements(),loanCaseVO);
+    }
+
+    @Override
+    public Result findLoanCasesByQuery(LoanCaseQueryDTO queryDTO, Integer pageNum, Integer pageSize) {
+        Page<LoanCase> result = loanRepository.findByQueryConditions(queryDTO, false, PageRequest.of(pageNum-1, pageSize));
+        List<LoanCaseAdminVO> loanCaseVO = new ArrayList<>();
+        for (LoanCase loanCase : result.getContent()){
+            LoanCaseAdminVO loanCaseVO1 = BeanUtil.copyProperties(loanCase, LoanCaseAdminVO.class);
+            loanCaseVO1.setCustomer(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false));
+            loanCaseVO1.setRecommender(BeanUtil.copyProperties(recommender.getRecommenderById(loanCase.getRecommenderId()), BizRecommenderVO.class));
+            loanCaseVO.add(loanCaseVO1);
+        }
+        return ResultUtil.success(result.getTotalElements(),loanCaseVO);
+    }
+
+    @Override
+    public Result findLoanCaseAndFileDetail(Long id) {
+        Document document = documentService.findById(id);
+        LoanCase loanCase = loanRepository.findByIdAndIsDelete(document.getCaseId(), false);
+        LoanCaseVO loanCaseVO = BeanUtil.copyProperties(loanCase, LoanCaseVO.class);
+        loanCaseVO.setCustomer(customerService.findByCustomerIdAndIsDelete(loanCase.getCustomerId(), false));
+        if (loanCase.getOtherId1()!= null)
+            loanCaseVO.setCustomers1(customerService.findByCustomerIdAndIsDelete(loanCase.getOtherId1(), false));
+        if (loanCase.getOtherId2() != null)
+            loanCaseVO.setCustomers2(customerService.findByCustomerIdAndIsDelete(loanCase.getOtherId2(), false));
+
+        DocumentVO documentVO = BeanUtil.copyProperties(document, DocumentVO.class);
+        documentVO.setLoanCaseVO(loanCaseVO);
+
+        return ResultUtil.success("success",documentVO);
+    }
+
     private List<LoanCaseVO> getLoanCaseVO(List<LoanCase> loanCases) {
         List<LoanCaseVO> loanCaseVO = new ArrayList<>();
         for (LoanCase loanCase1 : loanCases) {

+ 1 - 1
src/main/java/com/loan/system/service/Impl/PawnTicketServiceImpl.java

@@ -48,7 +48,7 @@ public class PawnTicketServiceImpl implements PawnTicketService {
 
     @Override
     public void updateRedeemTicketNoByPawnTicketNo(String redeemTicketNo, String pawnTicketNo) {
-        pawnTicketRepository.updateRedeemTicketNoByPawnTicketNoAndIsDelete(redeemTicketNo, pawnTicketNo, false);
+        pawnTicketRepository.updateRedeemTicketNoByPawnTicketNoAndIsDelete(redeemTicketNo, pawnTicketNo, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),false);
     }
 
     @Override

+ 14 - 4
src/main/java/com/loan/system/service/Impl/RecommenderServiceImpl.java

@@ -2,9 +2,12 @@ package com.loan.system.service.Impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import com.loan.system.domain.dto.BizRecommenderDTO;
+import com.loan.system.domain.dto.query.RecommenderQueryDTO;
 import com.loan.system.domain.entity.BizRecommender;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.repository.RecommenderRepository;
 import com.loan.system.service.RecommenderService;
+import com.loan.system.utils.ResultUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -35,11 +38,11 @@ public class RecommenderServiceImpl implements RecommenderService {
     }
 
     @Override
-    public List<BizRecommender> getRecommenders(Integer pageNum, Integer pageSize) {
-        Pageable pageable = PageRequest.of(pageNum, pageSize);
-        Page<BizRecommender> page = recommenderRepository.findAll(pageable);
+    public Result getRecommenders(Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<BizRecommender> page = recommenderRepository.findAllAndIsDelete(false,pageable);
 
-        return page.getContent();
+        return ResultUtil.success(page.getTotalElements(),page.getContent());
     }
 
     @Override
@@ -57,5 +60,12 @@ public class RecommenderServiceImpl implements RecommenderService {
         return recommenderRepository.findByIsDelete(isDelete);
     }
 
+    @Override
+    public Result getRecommendersByKey(RecommenderQueryDTO recommenderQueryDTO, Integer pageNum, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
+        Page<BizRecommender> page = recommenderRepository.findByQuery(recommenderQueryDTO,pageable);
+        return ResultUtil.success(page.getTotalElements(),page.getContent());
+    }
+
 
 }

+ 150 - 70
src/main/java/com/loan/system/service/Impl/RepaymentServiceImpl.java

@@ -6,11 +6,9 @@ import com.loan.system.domain.dto.ClearDetailDTO;
 import com.loan.system.domain.dto.RepaymentApprovalDTO;
 import com.loan.system.domain.dto.RepaymentRecordDTO;
 import com.loan.system.domain.entity.*;
-import com.loan.system.domain.enums.DecisionEnum;
-import com.loan.system.domain.enums.ExceptionEnum;
-import com.loan.system.domain.enums.StepEnum;
-import com.loan.system.domain.enums.StepPropertyEnum;
+import com.loan.system.domain.enums.*;
 import com.loan.system.domain.pojo.DateAndAmountPOJO;
+import com.loan.system.domain.pojo.TemplateMessage;
 import com.loan.system.domain.vo.*;
 import com.loan.system.exception.DescribeException;
 import com.loan.system.repository.RepaymentRepository;
@@ -53,6 +51,8 @@ public class RepaymentServiceImpl implements RepaymentService {
     private final DocumentService  documentService;
     private final ClearDetailService clearDetailService;
     private final StringRedisTemplate redisTemplate;
+    private final WxService wxService;
+    private final DisbursementRecordService disbursementRecordService;
 
 
     @Override
@@ -216,11 +216,10 @@ public class RepaymentServiceImpl implements RepaymentService {
                 repaymentRecordVOS.add(repaymentRecordVO);
             }
             repaymentDetailVO.setClearDetails(clearDetailService.listByCaseId(caseId));
-
-            repaymentDetailVO.setDateAndAmounts(disbursementService.getDateAndAmount(caseId));
             repaymentDetailVO.setRepaymentRecords(repaymentRecordVOS);
 
         }
+        repaymentDetailVO.setDateAndAmounts(disbursementService.getDateAndAmount(caseId));
         repaymentDetailVO.setCurrentAmount(currentAmount);
         repaymentDetailVO.setCurrentInterestAmount(currentInterestAmount);
         repaymentDetailVO.setActualTotalAmount(contractService.getActualTotalAmount(caseId));
@@ -314,14 +313,29 @@ public class RepaymentServiceImpl implements RepaymentService {
             List<DateAndAmountPOJO> dateAndAmountPOJOs = dateAndAmount.get(contract.getId());
             contractCompleteVO.setLoanDateList(dateAndAmountPOJOs.stream().map(DateAndAmountPOJO::getDate).collect(Collectors.toList()));
             List<ContractRepayment> contractRepayments = contractRepaymentService.findByContractId(contract.getId());
-            if (contractRepayments != null){
-                Double lastAmount = contractRepayments.get(contractRepayments.size()-1).getAmount();
-                Double amount = contractRepayments.stream().reduce(0.0, (sum, contractRepayment) -> sum + contractRepayment.getAmount(), Double::sum);
-                contractCompleteVO.setRepaymentTotalAmount(amount-lastAmount);
-                contractCompleteVO.setRepaymentLastAmount(lastAmount);
-            }else {
-                contractCompleteVO.setRepaymentTotalAmount(0.0);
-                contractCompleteVO.setRepaymentLastAmount(0.0);
+            contractCompleteVO.setRepaymentTotalAmount(0.0);
+            contractCompleteVO.setRepaymentLastAmount(0.0);
+            List<Long> recordIds = contractRepayments.stream().map(ContractRepayment::getRepaymentRecordId).distinct().collect(Collectors.toList());//记录次数
+            Double amount =0.0;
+            for (int i=0;i<recordIds.size();i++){
+                if(i< recordIds.size()-1){
+                    for (ContractRepayment contractRepayment : contractRepayments){
+                        if (contractRepayment.getRepaymentRecordId().equals(recordIds.get(i))){
+                            amount += contractRepayment.getAmount();
+                            amount += (contractRepayment.getInterestAmount()*0.0001);
+                        }
+                    }
+                    contractCompleteVO.setRepaymentTotalAmount(amount);
+                } else if (i== recordIds.size()-1) {//最后一条
+                    amount =0.0;
+                    for (ContractRepayment contractRepayment : contractRepayments){
+                        if (contractRepayment.getRepaymentRecordId().equals(recordIds.get(i))){
+                            amount += contractRepayment.getAmount();
+                            amount += (contractRepayment.getInterestAmount()*0.0001);
+                        }
+                    }
+                    contractCompleteVO.setRepaymentLastAmount(amount);
+                }
             }
             contractCompleteVO.setInterestAmount(contract.getInterestAmount());
             contractCompleteVO.setClearedTime(contract.getClearedTime());
@@ -338,7 +352,8 @@ public class RepaymentServiceImpl implements RepaymentService {
     }
 
     @Override
-    public void repayComplete(Long caseId) {
+    public void repayComplete(LoanCaseSimpleVO loanCaseSimpleVO) {
+        Long caseId = loanCaseSimpleVO.getId();
         //更新回款单
         updateStatusByCaseId(DecisionEnum.REPAYMENT_COMPLETE.getMsg(), caseId);
 
@@ -346,10 +361,25 @@ public class RepaymentServiceImpl implements RepaymentService {
         stepService.updateStatusByCaseId(StepEnum.COMPLETED.getMsg(), StepPropertyEnum.REPAYMENT_COMPLETE.getCode(), caseId);
 
         stepService.tryStartStep(StepPropertyEnum.REPAYMENT_COMPLETE.getCode(), caseId);
+
+        //TODO:微信推送回款完成消息和通知下一环节:综合人员
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.REPAYMENT_COMPLETE.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        List<String> openIds = userService.listOpenId();
+        for (String openId : openIds) {
+            wxService.sendTemplateMessage(openId, message);
+        }
     }
 
     @Override
-    public void addDisbursement(RepaymentRecordDTO repaymentRecordDTO, Long caseId, Long recordId) {
+    public void addDisbursement(RepaymentRecordDTO repaymentRecordDTO, LoanCaseSimpleVO loanCaseSimpleVO, Long recordId) {
+        Long caseId = loanCaseSimpleVO.getId();
         Repayment repayment = findByCaseIdAndIsDelete(caseId, false);
         if (ObjectUtils.isEmpty(repayment)) {
             Repayment rep = new Repayment();
@@ -407,29 +437,36 @@ public class RepaymentServiceImpl implements RepaymentService {
 
         stepService.tryStartStep(StepPropertyEnum.REPAY_START.getCode(), caseId);
 
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信推送预审拒绝消息和通知下一环节:审批员
+        com.loan.system.domain.pojo.TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value",StepPropertyEnum.REPAY_APPROVAL.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.APPROVER.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
     }
 
     @Override
-    public void repaymentApproval(RepaymentApprovalDTO approvalDTO, Long chargeId, Long assistantId) {
+    public void repaymentApproval(LoanCaseSimpleVO loanCaseSimpleVO, RepaymentApprovalDTO approvalDTO, Long chargeId, Long assistantId) {
         Long caseId = approvalDTO.getCaseId();
         //填写审批意见
         ApprovalRecord approvalRecord = approvalService.addApprovalRecord(caseId, StepPropertyEnum.REPAY_APPROVAL.getCode(), DecisionEnum.PASS.getMsg(), approvalDTO.getComments());
         repaymentRecordService.updateApprovalById(approvalRecord.getId(), approvalDTO.getRecordId());
 
         //指派下环节负责人
-        if (assistantId != null)
+        User user = null;
+        if (assistantId != null){
             stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.BALANCE_REPAY.getCode(), assistantId, caseId);
+            user = userService.findByIdAndIsDelete(assistantId);
+        }
         stepService.updateUserId1ByCaseIdAndStepCode(StepPropertyEnum.BALANCE_REPAY.getCode(), chargeId, caseId);
         repaymentRecordService.updateUsersById(chargeId, assistantId, approvalDTO.getRecordId());
 
@@ -444,11 +481,24 @@ public class RepaymentServiceImpl implements RepaymentService {
         stepService.tryStartStep(StepPropertyEnum.REPAY_APPROVAL.getCode(), caseId);
 
         //TODO:微信推送预审通过消息和通知下一环节
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.BALANCE_REPAY.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        User user1 = userService.findByIdAndIsDelete(chargeId);
+        if (user1 != null && user1.getOpenid() != null)
+            wxService.sendTemplateMessage(user1.getOpenid(), message);
+        if (user != null && user.getOpenid() != null)
+            wxService.sendTemplateMessage(user.getOpenid(), message);
     }
 
     @Override
-    public void repaymentCancel(RepaymentApprovalDTO approvalDTO) {
+    public void repaymentCancel(LoanCaseSimpleVO loanCaseSimpleVO, RepaymentApprovalDTO approvalDTO) {
         Long caseId = approvalDTO.getCaseId();
         //填写驳回意见
         ApprovalRecord approvalRecord = approvalService.addApprovalRecord(caseId, StepPropertyEnum.REPAY_APPROVAL.getCode(), DecisionEnum.REJECT.getMsg(), approvalDTO.getComments());
@@ -459,17 +509,20 @@ public class RepaymentServiceImpl implements RepaymentService {
         stepService.updateStatusByCaseId(StepEnum.PROCESS.getMsg(), StepPropertyEnum.REPAY_START.getCode(), caseId);
         stepService.updateStatusByCaseId(StepEnum.UNSTART.getMsg(), StepPropertyEnum.REPAY_APPROVAL.getCode(), caseId);
 
-        //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        //TODO:微信推送下环节负责人
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.REPAY_START.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        message.setData(data);
+        RepaymentRecord repaymentRecord = repaymentRecordService.findByIdAndIsDelete(approvalDTO.getRecordId());
+        User user = userService.findByIdAndIsDelete(repaymentRecord.getPlanUserId());
+        if (user != null && user.getOpenid() != null)
+            wxService.sendTemplateMessage(user.getOpenid(), message);
     }
 
     @Override
@@ -505,7 +558,8 @@ public class RepaymentServiceImpl implements RepaymentService {
     }
 
     @Override
-    public void balanceRepay(RepaymentRecordDTO repaymentRecordDTO, Long caseId) {
+    public void balanceRepay(LoanCaseSimpleVO loanCaseSimpleVO, RepaymentRecordDTO repaymentRecordDTO) {
+        Long caseId = loanCaseSimpleVO.getId();
         //TODO:可能只回本金,可能只回利息,可能一起回
         //添加回款记录有id则更新(本金、本金+利息),无id则新增(利息)
         Long recordId = repaymentRecordDTO.getRecordId();
@@ -518,11 +572,16 @@ public class RepaymentServiceImpl implements RepaymentService {
         }
         else {
             record = repaymentRecordService.findByIdAndIsDelete(recordId);
-            if(record.getRepayTime()!=null)
-                throw new DescribeException(ExceptionEnum.REPAYMENT_PLAN_HAS_COMPLETED);
-            originalAmount = record.getAmount();
-
-            repaymentRecordService.updateRepaymentRecordById2(repaymentRecordDTO, recordId);
+            if (record != null){
+                if (record.getMainUser()!=null&&!record.getMainUser().equals(BaseContext.getCurrentId())
+                        || record.getAssistUser() != null && !record.getAssistUser().equals(BaseContext.getCurrentId()))
+                    throw new DescribeException(ExceptionEnum.STEP_USER_NOT_EXPECTED);
+                if( record.getRepayTime()!=null)//TODO:重点,如果有变动需要改
+                    throw new DescribeException(ExceptionEnum.REPAYMENT_PLAN_HAS_COMPLETED);
+                originalAmount = record.getAmount();
+
+                repaymentRecordService.updateRepaymentRecordById2(repaymentRecordDTO, recordId);
+            }
         }
 
         //TODO:添加结清记录
@@ -560,21 +619,25 @@ public class RepaymentServiceImpl implements RepaymentService {
         stepService.tryStartStep(StepPropertyEnum.BALANCE_REPAY.getCode(), caseId);
 
         //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.FINANCE_CONFIRM.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.FINANCE.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
 
     }
 
     @Override
-    public void financeConfirm(List<Long> recordIds, Long caseId, String comment) {
+    public void financeConfirm(List<Long> recordIds, LoanCaseSimpleVO loanCaseSimpleVO, String comment) {
+        Long caseId = loanCaseSimpleVO.getId();
         for (Long recordId : recordIds) {
             //暂时复用审批人
             RedisData redisData = new RedisData(redisTemplate);
@@ -600,20 +663,23 @@ public class RepaymentServiceImpl implements RepaymentService {
         stepService.tryStartStep(StepPropertyEnum.FINANCE_CONFIRM.getCode(), caseId);
 
         //TODO:微信推送预审通过消息和通知下一环节
-//        SysMessage message = new SysMessage();
-//        message.setMobile(null);
-//        message.setUserRole("");
-//        message.setMessageTitle("");
-//        message.setMessageContent("");
-//        message.setStepCode("");
-//        message.setRelatedId(loanCase.getId());
-//        message.setRelatedType("");
-//        messageService.addMessage(message);
-//        wxService.sendTemplateMessage(loanCase.getCustomer().getMobile(),new TemplateMessage());
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.FINANCE_CONFIRM.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        List<String> openIds = userService.listOpenId();
+        for (String openId : openIds) {
+            wxService.sendTemplateMessage(openId, message);
+        }
     }
 
     @Override
-    public void autoRepay(RepaymentRecordDTO repaymentRecordDTO, Long caseId) {
+    public void autoRepay(RepaymentRecordDTO repaymentRecordDTO, LoanCaseSimpleVO loanCaseSimpleVO) {
+        Long caseId = loanCaseSimpleVO.getId();
         Repayment repayment = findByCaseIdAndIsDelete(caseId, false);
         if (ObjectUtils.isEmpty(repayment)) {
             Repayment rep = new Repayment();
@@ -660,6 +726,20 @@ public class RepaymentServiceImpl implements RepaymentService {
 
         stepService.tryStartStep(StepPropertyEnum.AUTO_REPAY.getCode(), caseId);
 
+        TemplateMessage message = new TemplateMessage();
+        Map<String, Map<String, String>> data = new HashMap<>();
+        data.put("character_string6", Collections.singletonMap("value", String.valueOf(caseId)));//caseId
+        data.put("phrase7", Collections.singletonMap("value", StepPropertyEnum.FINANCE_CONFIRM.getLabel()));//当前环节
+        data.put("thing1", Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getBusinessType())));//业务类型
+        Customer customer = customerService.findByIdAndIsDelete(loanCaseSimpleVO.getCustomerId());
+        data.put("thing3", Collections.singletonMap("value", customer!=null ? customer.getName() : ""));//客户名称
+        data.put("amount4",Collections.singletonMap("value", String.valueOf(loanCaseSimpleVO.getTotalLoanAmount())));//典当金额
+        List<User> users = userService.findByRoleAndIsDelete(Arrays.asList(RoleEnum.FINANCE.getMsg()), false);
+        for (User user : users) {
+            if (user.getOpenid() != null)
+                wxService.sendTemplateMessage(user.getOpenid(), message);
+        }
+
     }
 
     //TODO:用于判断总的金额是否结清

+ 18 - 9
src/main/java/com/loan/system/service/Impl/StepServiceImpl.java

@@ -242,6 +242,10 @@ public class StepServiceImpl implements StepService {
         steps.get(1).setBeginTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         steps.get(1).setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
 
+        steps.get(steps.size()-2).setStatus(StepEnum.PROCESS.getMsg());
+        steps.get(steps.size()-2).setBeginTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        steps.get(steps.size()-2).setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+
         steps.get(steps.size()-1).setStatus(StepEnum.PROCESS.getMsg());
         steps.get(steps.size()-1).setBeginTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         steps.get(steps.size()-1).setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
@@ -310,13 +314,15 @@ public class StepServiceImpl implements StepService {
     }
 
     @Override
-    public Boolean hasRolesInCase(Long caseId, Long userId,Integer stepCode) {
-        Step s = stepRepository.findByStepCodeAndCaseId(stepCode, caseId);
+    public Boolean hasRolesInCase(Long caseId, Long userId,StepVO s) {
         if(s.getStatus().equals(StepEnum.UNSTART.getMsg()))
             return false;
 
         User user = userService.findByIdAndIsDelete(userId);
         String[] userRoles=user.getRole().split(",");//1.获取该用户角色
+        if (userRoles.length==1)//仅有一个角色,不存在一个业务有两个角色
+            return false;
+
         Map<String,Integer> roleCount=new HashMap<>();
         for (String userRole : userRoles)
             roleCount.put(userRole,0);
@@ -348,7 +354,7 @@ public class StepServiceImpl implements StepService {
 
         //假设该角色能处理该环节(前题是环节还在进行中)
         if(s.getStatus().equals(StepEnum.PROCESS.getMsg())){
-            List<String> roles=map.get(stepCode);
+            List<String> roles=map.get(s.getCode());
             for (String role:roles){
                 if(roleCount.get(role)!=null){
                     int count=roleCount.get(role)+1;
@@ -385,12 +391,7 @@ public class StepServiceImpl implements StepService {
 
     @Override
     public void updateStatusByCaseIdAndParentCode(String msg, int code, Long caseId) {
-        List<StepVO> steps = getStepByCaseId(caseId);
-        for (StepVO step : steps) {
-            if (step.getParentCode().equals(code) && step.getStatus().equals(StepEnum.UNSTART.getMsg())) {
-                updateStatusByCaseId(msg, step.getCode(), caseId);
-            }
-        }
+        stepRepository.updateStatusByCaseIdAndParentCode(msg,code,caseId,LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
     }
 
     @Override
@@ -403,4 +404,12 @@ public class StepServiceImpl implements StepService {
     public List<StepVO> listByStepCodeAndCaseIds(List<Long> ids, Integer stepCode) {
         return BeanUtil.copyToList(stepRepository.findByCaseIdsAndCode(ids,stepCode), StepVO.class);
     }
+
+    @Override
+    public List<StepVO> findByStepCodesAndCaseId(List<Integer> list, Long caseId) {
+        List<Step> steps = stepRepository.findByStepCodesAndCaseId(list, caseId);
+        return BeanUtil.copyToList(steps, StepVO.class);
+    }
+
+
 }

+ 21 - 52
src/main/java/com/loan/system/service/Impl/UserServiceImpl.java

@@ -7,6 +7,7 @@ import com.loan.system.constant.MessageConstant;
 import com.loan.system.constant.PasswordConstant;
 import com.loan.system.domain.dto.UserDTO;
 import com.loan.system.domain.dto.UserLoginDTO;
+import com.loan.system.domain.dto.query.UserQueryDTO;
 import com.loan.system.domain.entity.*;
 import com.loan.system.domain.enums.*;
 import com.loan.system.domain.pojo.Result;
@@ -55,8 +56,6 @@ public class UserServiceImpl implements UserService {
     @Autowired
     private LoanService loanService;
     @Autowired
-    private ContractService contractService;
-    @Autowired
     private StepService stepService;
     @Autowired
     private CollateralPlanService collateralPlanService;
@@ -79,16 +78,8 @@ public class UserServiceImpl implements UserService {
         return userRepository.findByMobile(mobile);
     }
 
-
-    @Override
-    public List<Customer> getAllCustomers(Integer pageNum, Integer pageSize, Boolean isDelete) {
-        Pageable pageable = PageRequest.of(pageNum, pageSize);
-        Page<Customer> customerPage = customerRepository.findByIsDelete(isDelete, pageable);
-        return customerPage.getContent();
-    }
-
     @Override
-    public List<User> getAllUsers(Integer pageNum, Integer pageSize, Boolean isDelete) {
+    public Result getAllUsers(Integer pageNum, Integer pageSize, Boolean isDelete) {
         Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
         Page<User> userPage;
         if (isDelete == null)
@@ -96,7 +87,7 @@ public class UserServiceImpl implements UserService {
         else
             userPage = userRepository.findByIsDelete(isDelete, pageable);
 
-        return userPage.getContent();
+        return ResultUtil.success(userPage.getTotalElements(),BeanUtil.copyToList(userPage.getContent(),UserVO.class));
     }
 
     @Override
@@ -115,12 +106,6 @@ public class UserServiceImpl implements UserService {
         return userRepository.existsByMobileAndIsDelete(phoneNumber, false);
     }
 
-    @Override
-    public List<UserVO> getUsersByRole(String role) {
-        String roleSql = "%" + role + "%";
-        return BeanUtil.copyToList(userRepository.getUsersByRoleAndIsDelete(roleSql, false), UserVO.class);
-    }
-
     @Override
     public void addUser(UserDTO user) {
         User user1 = BeanUtil.copyProperties(user, User.class);
@@ -159,12 +144,16 @@ public class UserServiceImpl implements UserService {
     public List<User> findByRoleAndIsDelete(List<String> roles, boolean isDelete) {
         return userRepository.findByIsDelete(isDelete).stream()
                 .filter(user -> roles.stream()
-                        .anyMatch(role -> user.getRole().contains(role)))
+                        .anyMatch(role -> getRoles(user.getRole()).contains(role)))
                 .distinct()
                 .collect(Collectors.toList());
 
     }
 
+    private List<String> getRoles(String role) {
+        return Arrays.asList(role.split(","));
+    }
+
     @Override
     public boolean existsByIdAndIsDelete(Long chargeId) {
         return userRepository.existsByIdAndIsDelete(chargeId, false);
@@ -208,39 +197,6 @@ public class UserServiceImpl implements UserService {
         userRepository.updateUserById(user, id);
     }
 
-    @Override
-    public CaseAndUserVO findAllFinances() {
-        CaseAndUserVO caseAndUserVO = new CaseAndUserVO();
-        List<User> users = userRepository.findAllFinancesByIsDelete(false);
-        users.sort((u1, u2) -> Collator.getInstance(Locale.CHINESE).compare(u1.getRealName(), u2.getRealName()));
-        caseAndUserVO.setUsers(BeanUtil.copyToList(users, UserVO.class));
-
-        //获取正在处理项目的财务员
-        List<LoanCaseVO> loanCases = loanService.listLoanCaseByIsComplete(DecisionEnum.PROCESS.getMsg());
-        Map<Long, List<LoanCaseVO>> userAndCases = new HashMap<>();
-        for (LoanCaseVO loanCaseVO : loanCases) {
-            Long caseId = loanCaseVO.getId();
-            System.out.println("caseId = " + caseId);
-            //有指派人且利息不等于0.0
-            List<Contract> contracts = contractService.findContractByCaseId2(caseId);
-            System.out.println("contracts = " + contracts);
-            for (Contract contract : contracts) {
-                Long financeId = contract.getFinanceUserId();
-                System.out.println("financeId = " + financeId);
-                // 修复:确保financeId不为null,同时修正利息金额判断逻辑
-                if (financeId != null && Math.abs(contract.getInterestAmount()) > 0.0001) { // 使用一个小的阈值来避免浮点数精度问题
-                    userAndCases
-                            .computeIfAbsent(financeId, k -> new ArrayList<>())  // key 为空就 new ArrayList
-                            .add(loanCaseVO);
-                }
-            }
-
-        }
-        caseAndUserVO.setCaseUsers(userAndCases);
-
-        return caseAndUserVO;
-    }
-
     @Override
     public void setOpenidById(String openId, Long id) {
         userRepository.setOpenid(openId, id);
@@ -330,5 +286,18 @@ public class UserServiceImpl implements UserService {
             customerRepository.deleteByMobileAndName(user.getMobile(), user.getRealName());
     }
 
+    @Override
+    public Result getAllUsersByQuery(UserQueryDTO userQueryDTO,Integer pageNum, Integer pageSize) {
+        Pageable pageRequest = PageRequest.of(pageNum - 1, pageSize);
+        Page<User> users = userRepository.findAllByQuery(userQueryDTO, pageRequest);
+
+        return ResultUtil.success(users.getTotalElements(),BeanUtil.copyToList(users.getContent(), UserVO.class));
+    }
+
+    @Override
+    public List<String> listOpenId() {
+        return userRepository.findAllOpenIdAndIsDelete(false);
+    }
+
 
 }

+ 2 - 2
src/main/java/com/loan/system/service/Impl/WxServiceImpl.java

@@ -139,7 +139,8 @@ public class WxServiceImpl implements WxService {
 
         // 确保 message 中的 openid 一致
         message.setTouser(openid);
-        message.setTemplate_id(MessageConstant.TEMPLATE_ID_TWO);
+        message.setTemplate_id(MessageConstant.TEMPLATE_ID_THREE);
+        message.setPage(MessageConstant.pageUrl);
         RestTemplate restTemplate = new RestTemplate();
         Map<String, Object> result = restTemplate.postForObject(url, message, Map.class);
 
@@ -217,5 +218,4 @@ public class WxServiceImpl implements WxService {
         }
     }
 
-
 }

+ 12 - 8
src/main/java/com/loan/system/service/LoanService.java

@@ -1,12 +1,13 @@
 package com.loan.system.service;
 
 import com.loan.system.domain.dto.LoanCaseDTO;
+import com.loan.system.domain.dto.query.LoanCaseQueryDTO;
 import com.loan.system.domain.entity.LoanCase;
+import com.loan.system.domain.pojo.Result;
 import com.loan.system.domain.vo.LoanCaseSimpleVO;
 import com.loan.system.domain.vo.LoanCaseVO;
-import io.swagger.models.auth.In;
+import com.loan.system.domain.vo.LoanCaseAdminVO;
 
-import java.time.LocalDate;
 import java.util.List;
 import java.util.Map;
 
@@ -19,10 +20,6 @@ public interface LoanService {
 
     LoanCaseVO findLoanCaseDetailsById(Long caseId);
 
-    LoanCase findLoanCaseByIdAndIsDelete(Long caseId, boolean isDelete);
-
-    void updateUpdatetimeByIdAndIsDeleted(Long id,boolean isDelete);
-
     void logic_delete(Long id);
 
     LoanCaseSimpleVO findLoanCaseSimpleByIdAndIsDelete(Long caseId, boolean isDelete);
@@ -37,7 +34,7 @@ public interface LoanService {
 
     List<LoanCaseVO> findLoanCaseByIds(List<Long> ids, Integer pageNum, Integer pageSize, boolean IsDelete);
 
-    void updateIsCompleteByCaseId(String msg, Long caseId);
+    void updateIsCompleteByCaseId(String msg,Integer stepCode, Long caseId);
 
     List<LoanCaseSimpleVO> findLoanCaseSimpleByIsComplete(String msg);
 
@@ -50,7 +47,7 @@ public interface LoanService {
     List<LoanCaseVO> listLoanCaseByIsComplete(String isComplete);
 
     //controller 使用
-    List<LoanCaseVO> listLoanCaseByStepCode(Integer stepCode);
+    List<LoanCaseVO> listLoanCaseByStepCode(Integer stepCode, Integer pageNum, Integer pageSize);
 
     LoanCaseVO createLoanCase(Long customerId);
 
@@ -61,4 +58,11 @@ public interface LoanService {
     void cancelLoanCase(Long caseId);
 
     List<LoanCaseVO> listLoanCaseByKeyAndIsComplete(String key, String msg,Integer pageNum, Integer pageSize);
+    
+    Result listLoanCaseInfo(Integer pageNum, Integer pageSize, String isComplete);
+    
+    // 按条件查询业务信息
+    Result findLoanCasesByQuery(LoanCaseQueryDTO queryDTO, Integer pageNum, Integer pageSize);
+
+    Result findLoanCaseAndFileDetail(Long id);
 }

+ 5 - 1
src/main/java/com/loan/system/service/RecommenderService.java

@@ -1,14 +1,16 @@
 package com.loan.system.service;
 
 import com.loan.system.domain.dto.BizRecommenderDTO;
+import com.loan.system.domain.dto.query.RecommenderQueryDTO;
 import com.loan.system.domain.entity.BizRecommender;
+import com.loan.system.domain.pojo.Result;
 
 import java.util.List;
 
 public interface RecommenderService {
     void addRecommender(BizRecommenderDTO bizRecommenderDTO);
 
-    List<BizRecommender> getRecommenders(Integer pageNum, Integer pageSize);
+    Result getRecommenders(Integer pageNum, Integer pageSize);
 
 
     void updateRecommenderById(BizRecommenderDTO bizRecommenderDTO,Long  id);
@@ -16,4 +18,6 @@ public interface RecommenderService {
     BizRecommender getRecommenderById(Long recommenderId);
 
     List<BizRecommender> listAllRecommenders(Boolean isDelete);
+
+    Result getRecommendersByKey(RecommenderQueryDTO recommenderQueryDTO, Integer pageNum, Integer pageSize);
 }

+ 8 - 7
src/main/java/com/loan/system/service/RepaymentService.java

@@ -4,6 +4,7 @@ import com.loan.system.domain.dto.RepaymentApprovalDTO;
 import com.loan.system.domain.dto.RepaymentRecordDTO;
 import com.loan.system.domain.entity.Repayment;
 import com.loan.system.domain.vo.LoanCaseCompleteVO;
+import com.loan.system.domain.vo.LoanCaseSimpleVO;
 import com.loan.system.domain.vo.RepaymentDetailVO;
 
 import java.util.List;
@@ -30,19 +31,19 @@ public interface RepaymentService {
 
     LoanCaseCompleteVO getCompleteDetails(Long caseId);
 
-    void repayComplete(Long caseId);
+    void repayComplete(LoanCaseSimpleVO loanCaseSimpleVO);
 
-    void addDisbursement(RepaymentRecordDTO repaymentRecordDTO, Long caseId, Long recordId);
+    void addDisbursement(RepaymentRecordDTO repaymentRecordDTO, LoanCaseSimpleVO loanCaseSimpleVO, Long recordId);
 
-    void repaymentApproval(RepaymentApprovalDTO approvalDTO, Long chargeId, Long assistantId);
+    void repaymentApproval(LoanCaseSimpleVO loanCaseSimpleVO, RepaymentApprovalDTO approvalDTO, Long chargeId, Long assistantId);
 
-    void repaymentCancel(RepaymentApprovalDTO approvalDTO);
+    void repaymentCancel(LoanCaseSimpleVO loanCaseSimpleVO,RepaymentApprovalDTO approvalDTO);
 
     void financeDisbursement(Long caseId, Double interest, Long contractId);
 
-    void balanceRepay(RepaymentRecordDTO repaymentRecordDTO, Long caseId);
+    void balanceRepay(LoanCaseSimpleVO loanCaseSimpleVO, RepaymentRecordDTO repaymentRecordDTO);
 
-    void financeConfirm(List<Long> recordIds, Long caseId, String comment);
+    void financeConfirm(List<Long> recordIds, LoanCaseSimpleVO loanCaseSimpleVO, String comment);
 
-    void autoRepay(RepaymentRecordDTO repaymentRecordDTO, Long caseId);
+    void autoRepay(RepaymentRecordDTO repaymentRecordDTO, LoanCaseSimpleVO loanCaseSimpleVO);
 }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff