This commit is contained in:
77
2024-05-05 23:00:18 +08:00
commit f676e778cc
468 changed files with 37520 additions and 0 deletions

44
ruoyi-dk/pom.xml Normal file
View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>dk-sass-server</artifactId>
<version>4.8.2</version>
</parent>
<artifactId>ruoyi-dk</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.16.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,99 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.dk.domain.BorrowStatus;
import com.ruoyi.dk.enums.BankTypeEnums;
import com.ruoyi.dk.service.BorrowStatusService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/BorrowStatus")
public class BorrowStatusController extends BaseController {
private final BorrowStatusService borrowStatusService;
/**
* 查询借款状态列表
*/
@SaCheckPermission("dk:BorrowStatus:list")
@GetMapping("/list")
public TableDataInfo<BorrowStatus> list(PageQuery pageParams, @Validated BorrowStatus bo) {
IPage<BorrowStatus> page = borrowStatusService.page(pageParams.build(), Wrappers.query(bo));
return TableDataInfo.build(page);
}
@GetMapping("/bankType")
public R<List<String>> bankType(){
List<String> list = Arrays.stream(BankTypeEnums.values()).map(BankTypeEnums::getName).collect(Collectors.toList());
return R.ok(list);
}
@GetMapping("/all")
public R<List<BorrowStatus>> all(){
List<BorrowStatus> list = borrowStatusService.list();
return R.ok(list);
}
/**
* 获取借款状态详细信息
*/
@SaCheckPermission("dk:BorrowStatus:query")
@GetMapping("/{id}")
public R<BorrowStatus> getInfo(@NotNull(message = "主键不能为空") @PathVariable("id") Long id) {
return R.ok(borrowStatusService.getById(id));
}
/**
* 新增借款状态
*/
@SaCheckPermission("dk:BorrowStatus:add")
@Log(title = "借款状态", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping()
public R<Void> add(@Validated @RequestBody BorrowStatus bo) {
return toAjax(borrowStatusService.save(bo) ? 1 : 0);
}
/**
* 修改借款状态
*/
@SaCheckPermission("dk:BorrowStatus:edit")
@Log(title = "借款状态", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody BorrowStatus bo) {
return toAjax(borrowStatusService.updateById(bo) ? 1 : 0);
}
/**
* 删除借款状态
*/
@SaCheckPermission("dk:BorrowStatus:remove")
@Log(title = "借款状态" , businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String ids) {
List<String> idList = Stream.of(ids.split(",")).collect(Collectors.toList());
return toAjax(borrowStatusService.removeByIds(idList) ? 1 : 0);
}
}

View File

@@ -0,0 +1,43 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.dk.domain.AgreementSetting;
import com.ruoyi.dk.service.AgreementSettingService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/AgreementSetting")
public class DkAgreementSettingController extends BaseController {
private final AgreementSettingService agreementSettingService;
/**
* 获取协议设置详细信息
*/
@SaCheckPermission("dk:AgreementSetting:query")
@GetMapping("/info")
public R<AgreementSetting> getInfo() {
return R.ok(agreementSettingService.getAgreementSetting());
}
/**
* 修改协议设置
*/
@SaCheckPermission("dk:AgreementSetting:edit")
@Log(title = "协议设置", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody AgreementSetting bo) {
return toAjax(agreementSettingService.updateById(bo) ? 1 : 0);
}
}

View File

@@ -0,0 +1,121 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.dto.admin.req.BorrowUpdateStatusReq;
import com.ruoyi.dk.dto.admin.resp.BorrowResp;
import com.ruoyi.dk.service.BorrowService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/borrow")
public class DkBorrowController extends BaseController {
private final BorrowService borrowService;
/**
* 查询借款计划列表
*/
@SaCheckPermission("dk:borrow:list")
@GetMapping("/list")
public TableDataInfo<BorrowResp> list(PageQuery pageQuery, @Validated Borrow bo) {
IPage<BorrowResp> page = borrowService.pageAdmin(pageQuery, bo);
return TableDataInfo.build(page);
}
/**
* 获取借款计划详细信息
*/
@SaCheckPermission("dk:borrow:query")
@GetMapping("/{id}")
public R<Borrow> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(borrowService.getById(id));
}
/**
* 新增借款计划
*/
@SaCheckPermission("dk:borrow:add")
@Log(title = "借款计划", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping()
public R<Void> add(@Validated @RequestBody Borrow bo) {
return toAjax(borrowService.save(bo) ? 1 : 0);
}
/**\
*
* 修改借款计划
*/
@SaCheckPermission("dk:borrow:edit")
@Log(title = "借款计划", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody Borrow bo) {
return toAjax(borrowService.updateById(bo) ? 1 : 0);
}
@Log(title = "修改接口银行卡", businessType = BusinessType.UPDATE)
@PostMapping("updateBank")
public R<Void> updateBank(@RequestBody Borrow bo) {
return toAjax(borrowService.updateBank(bo));
}
@SaCheckPermission("dk:borrow:edit")
@Log(title = "修改借款", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PostMapping("/updateLoan")
public R<Void> updateLoan(@Validated @RequestBody Borrow bo) {
return toAjax(borrowService.updateLoan(bo));
}
@SaCheckPermission("dk:borrow:edit")
@Log(title = "修改借款状态", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PostMapping("/updateStatus")
public R<Void> updateStatus(@Validated @RequestBody BorrowUpdateStatusReq bo) {
return toAjax(borrowService.updateStatus(bo));
}
/**
* 删除借款计划
*/
@SaCheckPermission("dk:borrow:remove")
@Log(title = "借款计划" , businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String ids) {
List<String> idList = Stream.of(ids.split(",")).collect(Collectors.toList());
return toAjax(borrowService.removeByIds(idList) ? 1 : 0);
}
@GetMapping("/getContract")
public R<String> getContract(String tradeNo){
String contract = borrowService.getContract(tradeNo);
R<String> success = R.ok();
success.setData(contract);
return success;
}
}

View File

@@ -0,0 +1,87 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.dto.admin.req.UpdatePwdCustomerReq;
import com.ruoyi.dk.dto.admin.resp.CustomerAdminResp;
import com.ruoyi.dk.dto.admin.resp.CustomerExportVo;
import com.ruoyi.dk.mapper.CustomerMapper;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/dkCustomer")
public class DkCustomerController extends BaseController {
private final CustomerService customerService;
@Resource
private CustomerMapper customerMapper;
@SaCheckPermission("dk:dkCustomer:list")
@GetMapping("/list")
public TableDataInfo<CustomerAdminResp> list(PageQuery pageQuery, @Validated CustomerAdminResp bo) {
IPage<CustomerAdminResp> page = customerService.pageAdmin(pageQuery, bo);
return TableDataInfo.build(page);
}
@Operation(summary = "导出客户列表")
@SaCheckPermission("dk:dkCustomer:export")
@Log(title = "客户", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public void export(@Validated CustomerAdminResp bo, HttpServletResponse response) {
List<CustomerExportVo> list = customerMapper.exportAdmin(bo);
ExcelUtil.exportExcel(list, "客户", CustomerExportVo.class, response);
}
@SaCheckPermission("dk:dkCustomer:query")
@GetMapping("/{id}")
public R<Customer> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(customerService.getById(id));
}
@SaCheckPermission("dk:dkCustomer:edit")
@Log(title = "客户", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody Customer bo) {
return toAjax(customerService.updateById(bo) ? 1 : 0);
}
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String ids) {
List<String> idList = Stream.of(ids.split(",")).collect(Collectors.toList());
return toAjax(customerService.removeByIds(idList) ? 1 : 0);
}
@Log(title = "修改密码" , businessType = BusinessType.DELETE)
@PostMapping("/resetPwd")
public R<Void> resetPwd(@RequestBody UpdatePwdCustomerReq customer) {
return toAjax(customerService.updatePwd(customer.getCustomerId(),customer.getPassword()));
}
}

View File

@@ -0,0 +1,62 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.dk.domain.CustomerInfo;
import com.ruoyi.dk.service.CustomerInfoService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/dkCustomerInfo")
public class DkCustomerInfoController extends BaseController {
private final CustomerInfoService customerInfoService;
@SaCheckPermission("dk:dkCustomerInfo:list")
@GetMapping("/list")
public TableDataInfo<CustomerInfo> list(PageQuery pageQuery, @Validated CustomerInfo bo) {
IPage<CustomerInfo> page = customerInfoService.page(pageQuery.build(), Wrappers.query(bo));
return TableDataInfo.build(page);
}
@GetMapping("/getInfoByCustomerId")
public R<CustomerInfo> getInfoByCustomer(Long customerId) {
return R.ok(customerInfoService.getByCustomerId(customerId));
}
@PostMapping("/updateAllowSignature")
public R<Void> updateAllowSignature(@RequestBody CustomerInfo bo) {
customerInfoService.updateAllowSignature(bo);
return R.ok();
}
@SaCheckPermission("dk:dkCustomerInfo:query")
@GetMapping("/{id}")
public R<CustomerInfo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(customerInfoService.getById(id));
}
@SaCheckPermission("dk:dkCustomerInfo:edit")
@Log(title = "客户资料", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated @RequestBody CustomerInfo bo) {
return toAjax(customerInfoService.updateById(bo) ? 1 : 0);
}
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.dk.domain.HomeSetting;
import com.ruoyi.dk.service.HomeSettingService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 常规设置Controller
*
* @author duteliang
* @date 2023-11-29
*/
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/HomeSetting")
public class DkHomeSettingController extends BaseController {
private final HomeSettingService homeSettingService;
/**
* 获取常规设置详细信息
*/
@SaCheckPermission("dk:HomeSetting:query")
@GetMapping("/info")
public R<HomeSetting> getInfo() {
return R.ok(homeSettingService.getHomeSetting());
}
/**
* 修改常规设置
*/
@SaCheckPermission("dk:HomeSetting:edit")
@Log(title = "常规设置", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody HomeSetting bo) {
return toAjax(homeSettingService.updateById(bo) ? 1 : 0);
}
}

View File

@@ -0,0 +1,48 @@
package com.ruoyi.dk.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.dk.domain.LoansSetting;
import com.ruoyi.dk.service.LoansSettingService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 贷款设置Controller
*
* @author duteliang
* @date 2023-11-29
*/
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/dk/LoansSetting")
public class DkLoansSettingController extends BaseController {
private final LoansSettingService loansSettingService;
/**
* 获取贷款设置详细信息
*/
@SaCheckPermission("dk:LoansSetting:query")
@GetMapping("/info")
public R<LoansSetting> getInfo() {
return R.ok(loansSettingService.getLoansSetting());
}
/**
* 修改贷款设置
*/
@SaCheckPermission("dk:LoansSetting:edit")
@Log(title = "贷款设置", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated @RequestBody LoansSetting bo) {
return toAjax(loansSettingService.updateById(bo) ? 1 : 0);
}
}

View File

@@ -0,0 +1,46 @@
package com.ruoyi.dk.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.service.BorrowService;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.common.core.domain.R;
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 java.time.LocalDate;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/dk/home")
public class HomeController {
@Autowired
private CustomerService customerService;
@Autowired
private BorrowService borrowService;
@GetMapping("/index")
public R<Map<String,Long>> index() {
Map<String,Long> map = new HashMap<>();
LocalDate now = LocalDate.now();
// 今日注册, 总注册
long todayRegister = customerService.count(Wrappers.lambdaQuery(Customer.class).between(Customer::getCreateTime,
now.atTime(LocalTime.MIN), now.atTime(LocalTime.MAX)));
long totalRegister = customerService.count();
// 今日订单, 总订单
long todayBorrow = borrowService.count(Wrappers.lambdaQuery(Borrow.class).between(Borrow::getCreateTime,
now.atTime(LocalTime.MIN), now.atTime(LocalTime.MAX)));
long totalBorrow = borrowService.count();
map.put("todayRegister",todayRegister);
map.put("totalRegister",totalRegister);
map.put("todayBorrow",todayBorrow);
map.put("totalBorrow",totalBorrow);
return R.ok(map);
}
}

View File

@@ -0,0 +1,110 @@
package com.ruoyi.dk.controller.app;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.domain.HomeSetting;
import com.ruoyi.dk.dto.admin.resp.BorrowAdminVO;
import com.ruoyi.dk.dto.app.req.BorrowStartReq;
import com.ruoyi.dk.dto.app.resp.BorrowInfo;
import com.ruoyi.dk.dto.app.resp.LoanProcessResp;
import com.ruoyi.dk.service.BorrowService;
import com.ruoyi.dk.service.HomeSettingService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BeanConvertUtil;
import com.ruoyi.common.utils.MessageUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/app/borrow")
@Tag(name = "贷款相关的接口")
public class AppBorrowController {
@Autowired
private BorrowService borrowService;
@Autowired
private HomeSettingService homeSettingService;
@PostMapping("/start")
@Operation(summary = "发起贷款")
public R<Borrow> start(@RequestBody BorrowStartReq req){
Long userId = LoginHelper.getUserId();
req.setCustomerId(userId);
Borrow borrow = borrowService.borrow(req);
return R.ok(borrow);
}
@GetMapping("/withdraw")
@Operation(summary = "提现")
public R<Void> withdraw(Double withdrawAmount,String withdrawCode){
Long customerId = LoginHelper.getUserId();
HomeSetting homeSetting = homeSettingService.getHomeSetting();
if(homeSetting.getOpenWithdrawCode()){
if(StringUtils.isBlank(withdrawCode)){
return R.fail(MessageUtils.message("dk.withdraw.code.null"));
}
if(!homeSetting.getWithdrawCode().equals(withdrawCode)){
return R.fail(MessageUtils.message("dk.withdraw.code.error"));
}
}
borrowService.withdraw(withdrawAmount,customerId);
return R.ok();
}
@GetMapping("/getStepBorrow")
@Operation(summary = "获取贷款进度")
public R<LoanProcessResp> getStepBorrow(){
Long customerId = LoginHelper.getUserId();
LoanProcessResp stepBorrow = borrowService.getStepBorrow(customerId);
return R.ok(stepBorrow);
}
@GetMapping("/info")
@Operation(summary = "查看贷款详情")
public R<BorrowInfo> info(String tradeNo){
Borrow borrow = borrowService.getByTradeNo(tradeNo);
BorrowInfo borrowInfo = BeanConvertUtil.convertTo(borrow, BorrowInfo::new);
LoanProcessResp stepBorrow = borrowService.parseStepBorrow(borrow);
borrowInfo.setLoanProcessResp(stepBorrow);
borrowInfo.setDefaultCoinUnit(homeSettingService.getHomeSetting().getDefaultCoinUnit());
return R.ok(borrowInfo);
}
@GetMapping("/page")
@Operation(summary = "分页查询贷款我的贷款")
public TableDataInfo<BorrowAdminVO> page(PageQuery pageParams){
Long customerId = LoginHelper.getUserId();
LambdaQueryWrapper<Borrow> query = Wrappers.lambdaQuery(Borrow.class)
.eq(Borrow::getCustomerId,customerId)
.orderByDesc(Borrow::getCreateTime);
IPage<Borrow> page = borrowService.page(pageParams.build(), query);
TableDataInfo<BorrowAdminVO> info = TableDataInfo.build(page, BorrowAdminVO::new);
List<BorrowAdminVO> rows = info.getRows();
for (BorrowAdminVO row : rows) {
row.setDefaultCoinUnit(homeSettingService.getHomeSetting().getDefaultCoinUnit());
}
return info;
}
@GetMapping("/getContract")
public R<String> getContract(String tradeNo){
String contract = borrowService.getContract(tradeNo);
R<String> success = R.ok();
success.setData(contract);
return success;
}
}

View File

@@ -0,0 +1,57 @@
package com.ruoyi.dk.controller.app;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.domain.CustomerInfo;
import com.ruoyi.dk.dto.admin.resp.CustomerAdminVO;
import com.ruoyi.dk.service.CustomerInfoService;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.dk.service.HomeSettingService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BeanConvertUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/app/customer")
@Tag(name = "客户接口")
public class AppCustomerController {
@Autowired
private CustomerInfoService customerInfoService;
@Autowired
private CustomerService customerService;
@Autowired
private HomeSettingService homeSettingService;
@GetMapping("/info")
@Operation(summary = "客户信息")
public R<CustomerAdminVO> info(){
Long customerId = LoginHelper.getUserId();
Customer customer = customerService.getById(customerId);
CustomerAdminVO customerAdminVO = BeanConvertUtil.convertTo(customer, CustomerAdminVO::new);
customerAdminVO.setDefaultCoinUnit(homeSettingService.getHomeSetting().getDefaultCoinUnit());
return R.ok(customerAdminVO);
}
@GetMapping("/card/info")
@Operation(summary = "客户资料信息")
public R<CustomerInfo> cardInfo(){
Long customerId = LoginHelper.getUserId();
CustomerInfo customerInfo = customerInfoService.getByCustomerId(customerId);
return R.ok(customerInfo);
}
@PostMapping("/updateCustomerCard")
@Operation(summary = "修改客户资料信息")
public R<Void> updateCustomerCard(@RequestBody CustomerInfo customerInfo){
Long customerId = LoginHelper.getUserId();
customerInfo.setCustomerId(customerId);
customerInfoService.updateCustomerInfo(customerInfo);
return R.ok();
}
}

View File

@@ -0,0 +1,87 @@
package com.ruoyi.dk.controller.app;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.dto.app.req.CustomerRegisterReq;
import com.ruoyi.dk.dto.app.req.UpdatePwdOpenReq;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.dk.sms.CodeService;
import com.ruoyi.dk.sms.CodeType;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/customer/open")
@RestController
@Tag(name = "用户开放接口")
public class AppCustomerOpenController {
@Autowired
private CodeService codeService;
@Autowired
private CustomerService customerService;
@GetMapping("/sms/register")
@Operation(summary = "用户注册-验证码")
public R<String> customerRegister(String phoneNumber) {
String numbers = RandomUtil.randomNumbers(6);
codeService.put(phoneNumber, CodeType.CUSTOMER_REGISTER,numbers);
R<String> success = R.ok();
success.setData(numbers);
return success;
}
@PostMapping("/register")
@Operation(summary = "用户注册")
public R<Void> customerRegister(@RequestBody CustomerRegisterReq register) {
if(!codeService.check(register.getPhoneNumber(), CodeType.CUSTOMER_REGISTER,register.getCode())){
throw new CustomException(MessageUtils.message("dk.code.error"));
}
customerService.register(register);
return R.ok();
}
@GetMapping("/sms/forget")
@Operation(summary = "忘记密码-验证码")
public R<String> customerForgetPassword(String phoneNumber) {
String numbers = RandomUtil.randomNumbers(6);
codeService.put(phoneNumber, CodeType.CUSTOMER_FORGET_PASSWORD,numbers);
R<String> success = R.ok();
success.setData(numbers);
return success;
}
@GetMapping("/sms/forget/check")
@Operation(summary = "忘记密码-验证码-校验")
public R<String> customerForgetPasswordCheck(String phoneNumber,String code) {
if(!codeService.check(phoneNumber, CodeType.CUSTOMER_REGISTER,code)){
throw new CustomException(MessageUtils.message("dk.code.error"));
}
Customer customer = customerService.getCustomerByName(phoneNumber);
String uuid = UUID.randomUUID().toString();
RedisUtils.setCacheObject(uuid, customer);
R<String> success = R.ok();
success.setData(uuid);
return success;
}
@PostMapping("/updatePwd")
@Operation(summary = "修改密码")
public R<Void> customerForgetPasswordCheck(@RequestBody UpdatePwdOpenReq updatePwdOpenReq) {
Customer customer = RedisUtils.getCacheObject(updatePwdOpenReq.getCheckCode());
if(customer == null){
throw new CustomException(MessageUtils.message("dk.password.update.error"));
}
if(!updatePwdOpenReq.getPassword().equals(updatePwdOpenReq.getConfirmPassword())){
throw new CustomException(MessageUtils.message("dk.password.check.error"));
}
customerService.updatePwd(customer.getId(),updatePwdOpenReq.getPassword());
return R.ok();
}
}

View File

@@ -0,0 +1,87 @@
package com.ruoyi.dk.controller.app;
import cn.hutool.core.util.RandomUtil;
import com.ruoyi.dk.domain.HomeSetting;
import com.ruoyi.dk.domain.LoansSetting;
import com.ruoyi.dk.dto.app.req.CalLoanReq;
import com.ruoyi.dk.dto.app.resp.CalLoanResp;
import com.ruoyi.dk.dto.app.resp.DefaultLocalSetting;
import com.ruoyi.dk.dto.app.resp.LoanUser;
import com.ruoyi.dk.kit.CalLoanManager;
import com.ruoyi.dk.service.HomeSettingService;
import com.ruoyi.dk.service.LoansSettingService;
import com.ruoyi.dk.util.Loan;
import com.ruoyi.dk.util.PhoneRandomUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.BeanConvertUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Random;
@RestController
@RequestMapping("/app/home/loans")
@Tag(name = "首页开放")
public class AppHomeController {
@Autowired
private CalLoanManager calLoanManager;
@Autowired
private LoansSettingService loansSettingService;
@Autowired
private HomeSettingService homeSettingService;
@GetMapping("/defaultLocal")
@Operation(summary = "获取默认语言")
public R<DefaultLocalSetting> defaultLocal(){
HomeSetting homeSetting = homeSettingService.getHomeSetting();
String defaultLocal = homeSetting.getDefaultLocal();
if(StringUtils.isEmpty(defaultLocal)){
defaultLocal = "zh_CN";
}
DefaultLocalSetting defaultLocalSetting = new DefaultLocalSetting();
defaultLocalSetting.setDefaultLocal(defaultLocal);
defaultLocalSetting.setDefaultCoinUnit(homeSetting.getDefaultCoinUnit());
defaultLocalSetting.setOpenWithdrawCode(homeSetting.getOpenWithdrawCode());
return R.ok(defaultLocalSetting);
}
@PostMapping("/calLoan")
@Operation(summary = "计算每月还款")
public R<CalLoanResp> calLoan(@RequestBody CalLoanReq calLoanReq) {
if(calLoanReq.getTotalLoanMoney() == null || calLoanReq.getTotalMonth() == null){
LoansSetting loansSetting = loansSettingService.getLoansSetting();
if(calLoanReq.getTotalLoanMoney() == null){
calLoanReq.setTotalLoanMoney(loansSetting.getLoansInitAccount());
}
if(calLoanReq.getTotalMonth() == null){
calLoanReq.setTotalMonth(Integer.valueOf(loansSetting.getLoansInitMonth()));
}
}
Loan loan = calLoanManager.calLoan(calLoanReq);
CalLoanResp calLoanResp = BeanConvertUtil.convertTo(loan, CalLoanResp::new);
calLoanResp.setDefaultCoinUnit(homeSettingService.getHomeSetting().getDefaultCoinUnit());
return R.ok(calLoanResp);
}
@GetMapping("/loansUser")
@Operation(summary = "获取随机贷款用户")
public R<LoanUser> loansUser() {
Random random = new Random();
HomeSetting homeSetting = homeSettingService.getHomeSetting();
LoanUser loanUser = new LoanUser();
loanUser.setPhone(PhoneRandomUtil.gen(homeSetting.getRandomPhoneVersion()));
loanUser.setAmount(RandomUtil.randomInt(10,100)+"000");
loanUser.setDefaultCoinUnit(homeSetting.getDefaultCoinUnit());
loanUser.setTime(LocalDate.now().plusDays(-random.nextInt(7)).format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));
return R.ok(loanUser);
}
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.dk.controller.app;
import cn.hutool.core.util.NumberUtil;
import com.ruoyi.dk.domain.AgreementSetting;
import com.ruoyi.dk.domain.HomeSetting;
import com.ruoyi.dk.domain.LoansSetting;
import com.ruoyi.dk.dto.app.resp.LoansSettingVO;
import com.ruoyi.dk.enums.BankTypeEnums;
import com.ruoyi.dk.service.AgreementSettingService;
import com.ruoyi.dk.service.HomeSettingService;
import com.ruoyi.dk.service.LoansSettingService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.BeanConvertUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
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 java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/app/home/setting")
@Tag(name = "设置信息")
public class AppSettingController {
@Autowired
private AgreementSettingService agreementSettingService;
@Autowired
private HomeSettingService homeSettingService;
@Autowired
private LoansSettingService loansSettingService;
@GetMapping("/agreement")
@Operation(summary = "协议内容")
public R<AgreementSetting> agreement() {
AgreementSetting setting = agreementSettingService.getAgreementSetting();
return R.ok(setting);
}
@GetMapping("/home")
@Operation(summary = "常规内容")
public R<HomeSetting> home() {
HomeSetting setting = homeSettingService.getHomeSetting();
return R.ok(setting);
}
@GetMapping("/bankType")
@Operation(summary = "获取银行列表")
public R<List<String>> bankType(){
List<String> list = Arrays.stream(BankTypeEnums.values()).map(BankTypeEnums::getName).collect(Collectors.toList());
return R.ok(list);
}
@GetMapping("/loans")
@Operation(summary = "贷款信息")
public R<LoansSettingVO> loans() {
LoansSetting setting = loansSettingService.getLoansSetting();
LoansSettingVO vo = BeanConvertUtil.convertTo(setting, LoansSettingVO::new);
Double minDayServiceRate = 0D;
Double minMonthRate = Arrays.stream(setting.getServiceRate().split(","))
.map(Double::valueOf).min(Double::compareTo).orElse(null);
vo.setMinMonthRate(minMonthRate);
if(minMonthRate != null){
minDayServiceRate = NumberUtil.div(minMonthRate, new Double(30D), 4);
}
vo.setMinDayServiceRate(minDayServiceRate);
return R.ok(vo);
}
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.dk.controller.app;
import com.ruoyi.dk.dto.app.req.LoginPhoneBody;
import com.ruoyi.dk.kit.DkLoginKit;
import com.ruoyi.common.core.domain.R;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class LoginV2Controller {
@Autowired
private DkLoginKit dkLoginKit;
@PostMapping("/customer/login")
@Operation(summary = "用户登陆")
public R<Map<String, Object>> loginCustomer(@RequestBody LoginPhoneBody loginBody) {
Map<String, Object> ajax = new HashMap<>();
String token = dkLoginKit.login(loginBody.getMobile(),loginBody.getPassword());
ajax.put("token", token);
return R.ok(ajax);
}
}

View File

@@ -0,0 +1,57 @@
package com.ruoyi.dk.controller.app;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.dk.dto.common.FileUploadRes;
import com.ruoyi.dk.oss.ali.StsOssKit;
import com.ruoyi.dk.oss.ali.StsResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysOssService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* <p>created on 2021/7/13</p>
* @author zhangliang
*/
@RestController
@Tag(name = "通用接口")
@Slf4j
public class V2CommonController {
@Autowired
private StsOssKit stsOssKit;
@Autowired
private ISysOssService iSysOssService;
@GetMapping("/v2/common/sts")
@Operation(summary = "文件上传")
public R getSts(){
StsResult stsToken = stsOssKit.getStsToken();
if(stsToken == null){
return R.fail(400, MessageUtils.message("dk.file.upload.init.error"));
}
return R.ok(stsToken);
}
@PostMapping("/v2/common/upload")
@Operation(summary = "文件上传")
public R uploadFile(MultipartFile file) {
if (ObjectUtil.isNull(file)) {
return R.fail("上传文件不能为空");
}
SysOssVo oss = iSysOssService.upload(file);
FileUploadRes resp = new FileUploadRes();
resp.setUrl(oss.getUrl());
resp.setPath(oss.getFileName());
resp.setFileName(oss.getOriginalName());
return R.ok(resp);
}
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* 协议设置
* @TableName dk_agreement_setting
*/
@TableName(value ="dk_agreement_setting")
@Data
@Schema(description = "协议设置对象")
public class AgreementSetting implements Serializable {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 借款协议
*/
@Schema(description = "借款协议")
private String loansAgreement;
/**
* 服务协议
*/
@Schema(description = "服务协议")
private String serviceAgreement;
/**
* 授权协议
*/
@Schema(description = "授权协议")
private String authAgreement;
/**
* 法律责任
*/
@Schema(description = "法律责任")
private String lawAgreement;
private String contractTemplate;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,210 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 借款计划对象 dk_borrow
*
* @author duteliang
* @date 2023-11-29
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("dk_borrow")
@Schema(description = "借款计划")
public class Borrow implements Serializable {
private static final long serialVersionUID=1L;
/** ID */
@TableId(value = "id")
@Schema(description = "ID")
private Long id;
@Schema(description = "用途说明")
private String noteRemark;
private Boolean auditFlag;
/** 订单编号 */
@Schema(description = "订单编号")
private String tradeNo;
/** 总贷款额 */
@Schema(description = "总贷款额")
private BigDecimal totalLoanMoney;
/** 还款月数 */
@Schema(description = "还款月数")
private Integer totalMonth;
/** 月利率 */
@Schema(description = "月利率")
private Double loanMonthRate;
/** 年利率 */
@Schema(description = "年利率")
private Double loanYearRate;
/** 总利息数 */
@Schema(description = "总利息数")
private BigDecimal totalInterest;
/** 还款总额 */
@Schema(description = "还款总额")
private BigDecimal totalRepayment;
/** 首月还款额 */
@Schema(description = "首月还款额")
private BigDecimal firstRepayment;
/** 每月还款额 */
@Schema(description = "每月还款额")
private BigDecimal avgRepayment;
/** 每月还款日 */
@Schema(description = "每月还款日")
private Integer dueDate;
/** 是否打款 */
@Schema(description = "是否打款")
private Integer remitFlag;
@Schema(description = "客户电话")
private String customerPhone;
/** 借款状态 */
@Schema(description = "借款状态")
private String borrowName;
/** 借款状态编码 **/
@Schema(description = "借款状态ID")
private Long borrowStatusId;
@Schema(description = "借款状态样式")
private String borrowNameStyle;
/** 借款说明 */
@Schema(description = "借款说明")
private String borrowRemark;
/** 还款说明 */
@Schema(description = "还款说明")
private String repayRemark;
/** 计划 */
@Schema(description = "计划")
private String infoJson;
/** 客户ID */
@Schema(description = "客户ID")
private Long customerId;
/** 真实姓名 */
@Schema(description = "真实姓名")
private String realName;
/** 身份证照片 */
@Schema(description = "身份证照片")
private String cardNum;
/** 身份证正面 */
@Schema(description = "身份证正面")
private String cardFrontPicture;
private String handCardPicture;
/** 身份证背面 */
@Schema(description = "身份证背面")
private String cardBackPicture;
/** 单位名称 */
@Schema(description = "单位名称")
private String companyName;
/** 职位 */
@Schema(description = "职位")
private String companyTitle;
/** 单位电话 */
@Schema(description = "单位电话")
private String companyPhone;
/** 工作年龄 */
@Schema(description = "工作年龄")
private String companyYear;
/** 单位地址 */
@Schema(description = "单位地址")
private String companyAddress;
/** 详细地址 */
@Schema(description = "详细地址")
private String companyAddressInfo;
/** 现居住地址 */
@Schema(description = "现居住地址")
private String customerAddress;
/** 详细地址 */
@Schema(description = "详细地址")
private String customerAddressInfo;
/** 亲属姓名 */
@Schema(description = "亲属姓名")
private String kinsfolkName;
/** 亲属电话 */
@Schema(description = "亲属电话")
private String kinsfolkPhone;
/** 亲属关系 1-父母、2-配偶、3-子女4-祖父母 */
@Schema(description = "亲属关系 1-父母、2-配偶、3-子女4-祖父母")
private String kinsfolkRef;
@Schema(description = "转账备注")
private String transRemark;
/** $column.columnComment */
@Schema(description = "$column.columnComment")
private String bankType;
/** $column.columnComment */
@Schema(description = "$column.columnComment")
private String backCardNum;
/** $column.columnComment */
@Schema(description = "$column.columnComment")
private String firstBankType;
/** $column.columnComment */
@Schema(description = "$column.columnComment")
private String firstBackCardNum;
/** 修改银行卡次数 */
@Schema(description = "修改银行卡次数")
private Integer updateBackNum;
@Schema(description = "收入(万)")
private BigDecimal incomeWan;
/** 创建时间 */
@Schema(description = "创建时间")
private LocalDateTime createTime;
/** 修改时间 */
@Schema(description = "修改时间")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("dk_borrow_log")
public class BorrowLog {
/** ID */
@TableId(value = "id")
private Long id;
private Double withdrawAccount;
private Long customerId;
}

View File

@@ -0,0 +1,67 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 借款状态对象 dk_borrow_status
*
* @author duteliang
* @date 2023-11-29
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("dk_borrow_status")
@Schema(description = "借款状态添加对象")
public class BorrowStatus implements Serializable {
private static final long serialVersionUID=1L;
/** ID */
@TableId(value = "id")
@Schema(description = "ID")
private Long id;
/** 是否可以打款 */
@Schema(description = "是否可以打款")
private Integer usedRemit;
@Schema(description = "借款状态编码")
private String borrowCode;
@Schema(description = "是否允许提现")
private Boolean withdrawFlag;
/** 借款状态 */
@Schema(description = "借款状态")
private String borrowName;
/** 借款说明 */
@Schema(description = "借款说明")
private String borrowRemark;
@Schema(description = "借款样式")
private String borrowNameStyle;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private Date createTime;
/** 修改时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private Date updateTime;
}

View File

@@ -0,0 +1,105 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 客户
* @TableName dk_customer
*/
@TableName(value ="dk_customer")
@Data
@Schema(description = "客户模型")
public class Customer implements Serializable {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 手机
*/
@Schema(description = "手机")
private String phoneNumber;
/**
* 用户名称
*/
@Schema(description = "用户名称")
private String nickName;
/**
* 用户密码
*/
@Schema(description = "用户密码")
private String password;
/**
* 是否实名
*/
@Schema(description = "是否实名")
private Integer realNameAuth;
/**
* 是否贷款
*/
@Schema(description = "是否贷款")
private Integer loansFlag;
@Schema(description = "允许提现")
private Boolean allowWithdrawFlag;
/**
* 是否提现
*/
@Schema(description = "是否提现")
private Integer withdrawFlag;
/**
* 余额
*/
@Schema(description = "余额")
private BigDecimal account;
@Schema(description = "贷款金额")
private BigDecimal borrowAccount;
@Schema(description = "还款金额")
private BigDecimal repaymentAccount;
/**
* 状态 0-正常 1-封禁
*/
@Schema(description = "状态 0-正常 1-封禁")
private Integer status;
@Schema(description = "最后登陆时间")
private LocalDateTime lastLoginTime;
@Schema(description = "最后登陆IP")
private String lastLoginIp;
@Schema(description = "当前登录时间")
private LocalDateTime createTime;
@Schema(description = "修改时间")
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@JsonIgnore
public String getPassword() {
return password;
}
}

View File

@@ -0,0 +1,161 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 客户资料
* @TableName dk_customer_info
*/
@TableName(value ="dk_customer_info")
@Data
@Schema(description = "客户资料")
public class CustomerInfo implements Serializable {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
@Schema(description = "身份信息完整度")
private Boolean cardFlag = false;
@Schema(description = "资料信息完整度")
private Boolean infoFlag = false;
@Schema(description = "银行卡信息完整度")
private Boolean bankFlag = false;
/**
* 客户ID
*/
@Schema(description = "客户ID")
private Long customerId;
@Schema(description = "客户电话")
private String customerPhone;
/**
* 真实姓名
*/
@Schema(description = "真实姓名")
private String realName;
/**
* 身份证号码
*/
@Schema(description = "身份证号码")
private String cardNum;
/**
* 身份证正面
*/
@Schema(description = "身份证正面")
private String cardFrontPicture;
/**
* 手持身份证照片
*/
@Schema(description = "手持身份证照片")
private String handCardPicture;
/**
* 身份证背面
*/
@Schema(description = "身份证背面")
private String cardBackPicture;
/**
* 单位名称
*/
@Schema(description = "单位名称")
private String companyName;
/**
* 职位
*/
@Schema(description = "职位")
private String companyTitle;
/**
* 单位电话
*/
@Schema(description = "单位电话")
private String companyPhone;
/**
* 工作年龄
*/
@Schema(description = "工作年龄")
private String companyYear;
/**
* 单位地址
*/
@Schema(description = "单位地址")
private String companyAddress;
/**
* 详细地址
*/
@Schema(description = "详细地址")
private String companyAddressInfo;
/**
* 现居住地址
*/
@Schema(description = "现居住地址")
private String customerAddress;
/**
* 详细地址
*/
@Schema(description = "详细地址")
private String customerAddressInfo;
@Schema(description = "收入(万)")
private BigDecimal incomeWan;
/**
* 亲属姓名
*/
@Schema(description = "亲属姓名")
private String kinsfolkName;
/**
* 亲属电话
*/
@Schema(description = "亲属电话")
private String kinsfolkPhone;
/**
* 亲属关系 1-父母、2-配偶、3-子女4-祖父母
*/
@Schema(description = "亲属关系 1-父母、2-配偶、3-子女4-祖父母")
private String kinsfolkRef;
/**
* 开户银行
*/
@Schema(description = "开户银行")
private String bankType;
/**
* 银行卡号
*/
@Schema(description = "银行卡号")
private String backCardNum;
@Schema(description = "签名")
private String signature;
private Boolean allowSignature = true;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,48 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
/**
* 常规设置
* @TableName dk_home_setting
*/
@TableName(value ="dk_home_setting")
@Data
public class HomeSetting implements Serializable {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 站点标题
*/
private String homeTitle;
/**
* banner图
*/
private String bannerOne;
/**
* 公章
*/
private String commonSeal;
private String defaultLocal;
private String chatUrl;
private String withdrawCode;
private Boolean openWithdrawCode;
private String defaultCoinUnit;
private String randomPhoneVersion;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.dk.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
/**
* 贷款设置
* @TableName dk_loans_setting
*/
@TableName(value ="dk_loans_setting")
@Data
public class LoansSetting implements Serializable {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 贷款最小金额(元)
*/
private BigDecimal loansMinAccount;
/**
* 贷款最大金额(元)
*/
private BigDecimal loansMaxAccount;
/**
* 贷款初始金额(元)
*/
private BigDecimal loansInitAccount;
/**
* 允许选择月份
*/
private String loansMonth;
/**
* 初始选择月份
*/
private String loansInitMonth;
/**
* 每月还款日
*/
private Integer dueDate;
/**
* 服务费率
*/
private String serviceRate;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.dk.dto.admin.req;
import lombok.Data;
@Data
public class BorrowUpdateStatusReq {
private Long id;
private Integer usedRemit;
private String borrowName;
private Long borrowStatusId;
private String borrowRemark;
private String borrowNameStyle;
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.dk.dto.admin.req;
import lombok.Data;
@Data
public class UpdatePwdCustomerReq {
private Long customerId;
private String password;
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.dk.dto.admin.resp;
import com.ruoyi.dk.domain.Borrow;
import lombok.Data;
@Data
public class BorrowAdminVO extends Borrow {
private String defaultCoinUnit;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.dk.dto.admin.resp;
import com.ruoyi.dk.domain.Borrow;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class BorrowResp extends Borrow {
private String customerLoginName;
@Schema(description = "是否允许提现")
private Boolean withdrawFlag;
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.dk.dto.admin.resp;
import com.ruoyi.dk.domain.Customer;
import lombok.Data;
@Data
public class CustomerAdminResp extends Customer {
private String realName;
private Boolean allowSignature = true;
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.dk.dto.admin.resp;
import com.ruoyi.dk.domain.Customer;
import lombok.Data;
@Data
public class CustomerAdminVO extends Customer {
private String defaultCoinUnit;
}

View File

@@ -0,0 +1,126 @@
package com.ruoyi.dk.dto.admin.resp;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.dk.enums.KinsfolkRefEnum;
import com.ruoyi.dk.enums.YesOrNoEnum;
import com.ruoyi.common.annotation.ExcelEnumFormat;
import com.ruoyi.common.convert.ExcelEnumConvert;
import lombok.Data;
@Data
@ExcelIgnoreUnannotated
public class CustomerExportVo {
@ExcelProperty(value = "登陆手机号")
private String phoneNumber;
/**
* 用户名称
*/
@ExcelProperty(value = "登陆手机号")
private String nickName;
/**
* 是否实名
*/
@ExcelProperty(value = "是否实名",converter = ExcelEnumConvert.class)
@ExcelEnumFormat(enumClass = YesOrNoEnum.class)
private Integer realNameAuth;
/**
* 是否贷款
*/
@ExcelProperty(value = "是否贷款",converter = ExcelEnumConvert.class)
@ExcelEnumFormat(enumClass = YesOrNoEnum.class)
private Integer loansFlag;
/**
* 是否提现
*/
@ExcelProperty(value = "是否提现",converter = ExcelEnumConvert.class)
@ExcelEnumFormat(enumClass = YesOrNoEnum.class)
private Integer withdrawFlag;
@ExcelProperty(value = "真实姓名")
private String realName;
@ExcelProperty(value = "身份证号码")
private String cardNum;
/**
* 单位名称
*/
@ExcelProperty(value = "单位名称")
private String companyName;
/**
* 职位
*/
@ExcelProperty(value = "职位")
private String companyTitle;
/**
* 单位电话
*/
@ExcelProperty(value = "单位电话")
private String companyPhone;
/**
* 工作年龄
*/
@ExcelProperty(value = "工作年龄")
private String companyYear;
/**
* 单位地址
*/
@ExcelProperty(value = "单位地址")
private String companyAddress;
/**
* 详细地址
*/
@ExcelProperty(value = "详细地址")
private String companyAddressInfo;
/**
* 现居住地址
*/
@ExcelProperty(value = "现居住地址")
private String customerAddress;
/**
* 详细地址
*/
@ExcelProperty(value = "详细地址")
private String customerAddressInfo;
@ExcelProperty(value = "亲属关系",converter = ExcelEnumConvert.class)
@ExcelEnumFormat(enumClass = KinsfolkRefEnum.class)
private String kinsfolkRef;
/**
* 亲属姓名
*/
@ExcelProperty(value = "亲属姓名")
private String kinsfolkName;
/**
* 亲属电话
*/
@ExcelProperty(value = "亲属电话")
private String kinsfolkPhone;
/**
* 开户银行
*/
@ExcelProperty(value = "开户银行")
private String bankType;
/**
* 银行卡号
*/
@ExcelProperty(value = "银行卡号")
private String backCardNum;
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.dk.dto.admin.resp;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class CustomerInfo {
/**
* ID
*/
private Long id;
/**
* 手机
*/
private String phoneNumber;
/**
* 用户名称
*/
private String nickName;
/**
* 用户密码
*/
private String password;
/**
* 是否实名
*/
private Integer realNameAuth;
/**
* 是否贷款
*/
private Integer loansFlag;
/**
* 是否提现
*/
private Integer withdrawFlag;
/**
* 余额
*/
private Long account;
/**
* 可提现金额
*/
private Long withdrawAccount;
/**
* 状态 0-正常 1-封禁
*/
private Integer status;
private LocalDateTime lastLoginTime;
private String lastLoginIp;
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.dk.dto.app.req;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "发起贷款入参")
public class BorrowStartReq {
@Schema(description = "客户ID")
private Long customerId;
@Schema(description = "用途说明")
private String noteRemark;
@Schema(description = "总贷款额")
private BigDecimal totalLoanMoney;
@Schema(description = "还款月数")
private Integer totalMonth;
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.dk.dto.app.req;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "贷款计算器")
public class CalLoanReq {
@Schema(description = "总贷款额")
private BigDecimal totalLoanMoney;
@Schema(description = "还款月数")
private Integer totalMonth;
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.dk.dto.app.req;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "用户注册-入参")
public class CustomerRegisterReq {
/**
* 手机
*/
@Schema(description = "手机号")
private String phoneNumber;
/**
* 用户密码
*/
@Schema(description = "密码")
private String password;
/**
* code
*/
@Schema(description = "验证码")
private String code;
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.dk.dto.app.req;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>created on 2021/7/13</p>
*
* @author zhangliang
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class LoginPhoneBody implements Serializable {
private static final long serialVersionUID=1L;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "密码")
private String password;
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.dk.dto.app.req;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "用户忘记密码-修改密码入参")
public class UpdatePwdOpenReq {
@Schema(description = "校验码")
private String checkCode;
@Schema(description = "密码")
private String password;
@Schema(description = "确认密码")
private String confirmPassword;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.dk.dto.app.resp;
import com.ruoyi.dk.domain.Borrow;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "贷款详情DTO")
public class BorrowInfo extends Borrow {
@Schema(description = "贷款进度条")
private LoanProcessResp loanProcessResp;
private String defaultCoinUnit;
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.dk.dto.app.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "贷款进度")
@Data
public class BorrowStepResp {
@Schema(description = "名称")
private String name;
@Schema(description = "是否完成")
private boolean over = false;
public BorrowStepResp(String name, boolean over) {
this.name = name;
this.over = over;
}
public BorrowStepResp() {
}
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.dk.dto.app.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "计算利息返回数据")
public class CalLoanResp {
@Schema(description = "贷款总额")
private BigDecimal totalLoanMoney; //
@Schema(description = "货币单位")
private String defaultCoinUnit;
@Schema(description = "还款月份")
private int totalMonth; //
@Schema(description = "贷款年利率")
private double loanRateYear; //
@Schema(description = "贷款日利率")
private double loanRateDay; //
@Schema(description = "贷款日利率")
private double loanRateMonth; //
@Schema(description = "总利息数")
private BigDecimal totalInterest; //
@Schema(description = "还款总额")
private BigDecimal totalRepayment; //
@Schema(description = "首月还款额")
private BigDecimal firstRepayment; //
@Schema(description = "月均还款额")
private BigDecimal avgRepayment; //
}

View File

@@ -0,0 +1,10 @@
package com.ruoyi.dk.dto.app.resp;
import lombok.Data;
@Data
public class DefaultLocalSetting {
private String defaultLocal;
private String defaultCoinUnit;
private Boolean openWithdrawCode;
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.dk.dto.app.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "贷款进度说明")
public class LoanProcessResp {
@Schema(description = "贷款进度条")
private List<BorrowStepResp> borrowStep;
@Schema(description = "借款状态样式")
private String borrowNameStyle;
/** 借款说明 */
@Schema(description = "借款说明")
private String borrowRemark;
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.dk.dto.app.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "贷款用户")
public class LoanUser {
/**
* 手机
*/
@Schema(description = "手机号")
private String phone;
/**
* 金额
*/
@Schema(description = "金额")
private String amount;
private String defaultCoinUnit;
/**
* 时间
*/
@Schema(description = "贷款时间")
private String time;
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.dk.dto.app.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "费率设置-出参")
public class LoansSettingVO {
/**
* 贷款最小金额(元)
*/
@Schema(description = "贷款最小金额(元)")
private BigDecimal loansMinAccount;
/**
* 贷款最大金额(元)
*/
@Schema(description = "贷款最大金额(元)")
private BigDecimal loansMaxAccount;
/**
* 贷款初始金额(元)
*/
@Schema(description = "贷款初始金额(元)")
private BigDecimal loansInitAccount;
/**
* 允许选择月份
*/
@Schema(description = "允许选择月份")
private String loansMonth;
/**
* 初始选择月份
*/
@Schema(description = "初始选择月份")
private String loansInitMonth;
/**
* 每月还款日
*/
@Schema(description = "每月还款日")
private Integer dueDate;
/**
* 最小 日息
*/
@Schema(description = "最小 日息")
private Double minDayServiceRate;
private Double minMonthRate;
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.dk.dto.common;
import lombok.Data;
@Data
public class FileUploadRes {
private String url;
private String fileName;
private String path;
}

View File

@@ -0,0 +1,25 @@
package com.ruoyi.dk.enums;
public enum BankTypeEnums {
PBC("中国人民银行"),
ICBC("中国工商银行"),
CCB("中国建设银行"),
HSBC("汇丰银行"),
BOC("中国银行"),
ABC("中国农业银行"),
BC("交通银行"),
ZS_CMB("招商银行"),
CMB("中国民生银行"),
CITIC("中信银行"),
;
private final String name;
BankTypeEnums(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.dk.enums;
import lombok.Getter;
// 1=父母,2=配偶,3=子女,4=祖父母
@Getter
public enum KinsfolkRefEnum {
FM(1,"父母"),
PO(2,"配偶"),
ZN(3,"子女"),
ZFM(4,"祖父母"),
;
private final Integer code;
private final String text;
KinsfolkRefEnum(Integer code, String text) {
this.code = code;
this.text = text;
}
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.dk.enums;
import lombok.Getter;
// 0=否,1=是
@Getter
public enum YesOrNoEnum {
NO(0,""),
YES(1,""),
;
private final Integer code;
private final String text;
YesOrNoEnum(Integer code, String text) {
this.code = code;
this.text = text;
}
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.dk.executor;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;
/**
* 线程变量定义
* <p>created on 2023/3/3 11:16</p>
* @author ZL
*/
public class ExecutorConstant {
// private final static int CPU_NUM = Runtime.getRuntime().availableProcessors();
private final static int CPU_NUM = 6;
public static Executor SYNC_EXECUTOR;
public static Executor COMMON_EXECUTOR;
static {
ThreadPoolExecutor syncExecutor = initExecutor(CPU_NUM,
CPU_NUM << 2,
5,
TimeUnit.SECONDS,
new SynchronousQueue<>(),
"syncThreadPool-%d");
SYNC_EXECUTOR = TtlExecutors.getTtlExecutor(syncExecutor);
ThreadPoolExecutor commonExecutor = new ThreadPoolExecutor(CPU_NUM,
CPU_NUM << 2,
5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50),
init("commonThreadPool-%d"),
new ThreadPoolExecutor.CallerRunsPolicy());
COMMON_EXECUTOR = TtlExecutors.getTtlExecutor(commonExecutor);
}
public static void main(String[] args) {
System.out.println(6 << 2);
}
private static ThreadFactory init(String nameFormat){
return new ThreadFactoryBuilder().setNameFormat(nameFormat).build();
}
private static ThreadPoolExecutor initExecutor(int corePoolSize, int maxPoolSize, int keepAliveTime, TimeUnit timeUnit,
BlockingQueue<Runnable> workQueue, String nameFormat){
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, workQueue,
init(nameFormat));
}
}

View File

@@ -0,0 +1,46 @@
package com.ruoyi.dk.kit;
import com.ruoyi.dk.domain.LoansSetting;
import com.ruoyi.dk.dto.app.req.CalLoanReq;
import com.ruoyi.dk.service.LoansSettingService;
import com.ruoyi.dk.util.ACPIMLoanCalculator;
import com.ruoyi.dk.util.Loan;
import com.ruoyi.dk.util.LoanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@Component
public class CalLoanManager {
@Autowired
private LoansSettingService loansSettingService;
public Loan calLoan(BigDecimal totalLoanMoney,Integer totalMonth, Double loanRate){
ACPIMLoanCalculator calculator = new ACPIMLoanCalculator();
return calculator.calLoan(totalLoanMoney, totalMonth, loanRate, LoanUtil.RATE_TYPE_MONTH);
}
public Loan calLoan(CalLoanReq calLoanReq){
Double loanRate = getLoanRate(calLoanReq.getTotalMonth());
return this.calLoan(calLoanReq.getTotalLoanMoney(), calLoanReq.getTotalMonth(), loanRate);
}
public Double getLoanRate(Integer mouth){
LoansSetting loansSetting = loansSettingService.getLoansSetting();
String serviceRate = loansSetting.getServiceRate();
String[] split = serviceRate.split(",");
if(split.length < mouth){
return Double.valueOf(split[split.length-1]);
}else{
return Double.valueOf(split[mouth-1]);
}
}
public static void main(String[] args) {
ACPIMLoanCalculator calculator = new ACPIMLoanCalculator();
Loan loan = calculator.calLoan(BigDecimal.valueOf(20000), 3, 0.5, LoanUtil.RATE_TYPE_MONTH);
System.out.println(loan);
}
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.dk.kit;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.executor.ExecutorConstant;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.system.service.SysLoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Collections;
@Component
@Slf4j
public class DkLoginKit {
@Autowired
private CustomerService customerService;
@Autowired
private SysLoginService sysLoginService;
public String login(String mobile,String password) {
Customer customer = customerService.getCustomerByName(mobile);
if(customer == null){
log.info("登录用户:{} 不存在.", mobile);
throw new BaseException(MessageUtils.message("login.user.not",mobile));
}
if(!BCrypt.checkpw(password, customer.getPassword())){
throw new BaseException(MessageUtils.message("login.user.fail"));
}
if (customer.getStatus() == 1) {
log.info("登录用户:{} 已被停用.", mobile);
throw new BaseException(MessageUtils.message("login.user.stop",mobile));
}
ExecutorConstant.SYNC_EXECUTOR.execute(() -> {
updateCustomer(customer);
});
return login(customer);
}
private void updateCustomer(Customer customer){
Customer update = new Customer();
update.setId(customer.getId());
update.setLastLoginIp(ServletUtils.getClientIP());
update.setLastLoginTime(LocalDateTime.now());
customerService.updateById(update);
}
private String login(Customer user){
LoginUser loginUser = new LoginUser();
loginUser.setDeptId(null);
loginUser.setDeptName(null);
loginUser.setMenuPermission(Collections.emptySet());
loginUser.setRolePermission(Collections.emptySet());
loginUser.setUsername(user.getPhoneNumber());
loginUser.setRoles(Collections.emptyList());
loginUser.setRoleId(null);
loginUser.setUserId(user.getId());
loginUser.setUserType(UserType.APP_USER.getUserType());
LoginHelper.login(loginUser);
sysLoginService.recordLogininfor(loginUser.getUsername(), UserType.APP_USER.getUserType(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.AgreementSetting;
public interface AgreementSettingMapper extends BaseMapper<AgreementSetting> {
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.BorrowLog;
public interface BorrowLogMapper extends BaseMapper<BorrowLog> {
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.dto.admin.resp.BorrowResp;
import org.apache.ibatis.annotations.Param;
public interface BorrowMapper extends BaseMapper<Borrow> {
IPage<BorrowResp> pageAdmin(@Param("page") IPage<Object> page, @Param("bo") Borrow bo);
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.BorrowStatus;
public interface BorrowStatusMapper extends BaseMapper<BorrowStatus> {
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.CustomerInfo;
public interface CustomerInfoMapper extends BaseMapper<CustomerInfo> {
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.dto.admin.resp.CustomerAdminResp;
import com.ruoyi.dk.dto.admin.resp.CustomerExportVo;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
public interface CustomerMapper extends BaseMapper<Customer> {
void incsAmount(@Param("customerId") Long customerId, @Param("totalLoanMoney") BigDecimal totalLoanMoney,
@Param("totalRepayment") BigDecimal totalRepayment);
void withdraw(@Param("customerId") Long customerId, @Param("withdrawAmount") Double withdrawAmount);
IPage<CustomerAdminResp> pageAdmin(@Param("page") IPage<Object> page, @Param("bo") CustomerAdminResp bo);
List<CustomerExportVo> exportAdmin(@Param("bo") CustomerAdminResp bo);
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.HomeSetting;
public interface HomeSettingMapper extends BaseMapper<HomeSetting> {
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.dk.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.dk.domain.LoansSetting;
public interface LoansSettingMapper extends BaseMapper<LoansSetting> {
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.dk.oss.ali;
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* <p>created on 2021/3/3</p>
*
* @author zhangliang
*/
@Data
@ToString(exclude={"accessKeyId","accessKeySecret"})
@Configuration
@ConfigurationProperties(prefix = "ali.oss")
public class OssConfig {
private boolean enable = false;
private String endpoint; // 连接区域地址
private String cdnDomain; // cdn 域名
private String accessKeyId; // 连接keyId
private String accessKeySecret; // 连接秘钥
private String bucketName; // 需要存储的bucketName
private Long durationSeconds = 3600L;
private String roleArn;
private String roleSessionName = "sts-session";
private String key = "upload/";
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.dk.oss.ali;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Component
@Slf4j
public class StsOssKit {
@Autowired
@Setter
@Getter
private OssConfig ossConfig;
@Getter
public IAcsClient acsClient = null;
@PostConstruct
public void init(){
if(!ossConfig.isEnable()){
log.error("未开启阿里云OSS配置");
return;
}
DefaultProfile profile = DefaultProfile.getProfile(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
acsClient = new DefaultAcsClient(profile);
}
public StsResult getStsToken(){
// 创建API请求并设置参数
AssumeRoleRequest request = new AssumeRoleRequest();
request.setDurationSeconds(ossConfig.getDurationSeconds());
request.setRoleArn(ossConfig.getRoleArn());
request.setRoleSessionName(ossConfig.getRoleSessionName());
try {
AssumeRoleResponse response = acsClient.getAcsResponse(request);
log.info(JSON.toJSONString(response));
// 打印您需要的返回值,此处打印的是此次请求的 RequestId
log.info(response.getRequestId());
StsResult stsResult = new StsResult();
stsResult.setToken(response.getCredentials().getSecurityToken());
stsResult.setKeyId(response.getCredentials().getAccessKeyId());
stsResult.setKeySecret(response.getCredentials().getAccessKeySecret());
stsResult.setRegion("oss-"+ossConfig.getEndpoint());
stsResult.setBucket(ossConfig.getBucketName());
String nowStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
stsResult.setKey(ossConfig.getKey()+nowStr+"/");
stsResult.setCdnDomain(ossConfig.getCdnDomain());
return stsResult;
} catch (ServerException e) {
log.error("上传文件系统异常",e);
} catch (ClientException e) {
// 打印错误码
log.error("ErrCode:" + e.getErrCode());
log.error("ErrMsg:" + e.getErrMsg());
log.error("RequestId:" + e.getRequestId());
}
return null;
}
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.dk.oss.ali;
import lombok.Data;
@Data
public class StsResult {
private String token;
private String keyId;
private String keySecret;
private String region;
private String bucket;
private String key;
private String cdnDomain;
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.AgreementSetting;
public interface AgreementSettingService extends IService<AgreementSetting> {
AgreementSetting getAgreementSetting();
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.dto.admin.req.BorrowUpdateStatusReq;
import com.ruoyi.dk.dto.admin.resp.BorrowResp;
import com.ruoyi.dk.dto.app.req.BorrowStartReq;
import com.ruoyi.dk.dto.app.resp.LoanProcessResp;
import com.ruoyi.common.core.domain.PageQuery;
public interface BorrowService extends IService<Borrow> {
Borrow borrow(BorrowStartReq req);
Borrow getByTradeNo(String tradeNo);
boolean updateLoan(Borrow bo);
boolean updateStatus(BorrowUpdateStatusReq bo);
boolean updateBank(Borrow bo);
void withdraw(Double withdrawAmount, Long customerId);
Borrow getByCustomerId(Long customerId);
LoanProcessResp getStepBorrow(Long customerId);
LoanProcessResp parseStepBorrow(Borrow one);
IPage<BorrowResp> pageAdmin(PageQuery pageQuery, Borrow bo);
String getContract(String tradeNo);
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.BorrowStatus;
public interface BorrowStatusService extends IService<BorrowStatus> {
BorrowStatus getByCode(String borrowStatusCode);
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.CustomerInfo;
public interface CustomerInfoService extends IService<CustomerInfo> {
void updateCustomerInfo(CustomerInfo customerInfo);
CustomerInfo getByCustomerId(Long customerId);
boolean updateAllowSignature(CustomerInfo bo);
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.dto.admin.resp.CustomerAdminResp;
import com.ruoyi.dk.dto.app.req.CustomerRegisterReq;
import com.ruoyi.common.core.domain.PageQuery;
import java.math.BigDecimal;
public interface CustomerService extends IService<Customer> {
Customer getCustomerByName(String mobile);
void register(CustomerRegisterReq register);
boolean updatePwd(Long id, String password);
void borrowAmount(Long customerId, BigDecimal totalLoanMoney,BigDecimal totalRepayment);
boolean withdraw(Long customerId, Double withdrawAmount);
void dk(Long customerId);
IPage<CustomerAdminResp> pageAdmin(PageQuery pageQuery, CustomerAdminResp bo);
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.HomeSetting;
public interface HomeSettingService extends IService<HomeSetting> {
HomeSetting getHomeSetting();
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.dk.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.dk.domain.LoansSetting;
public interface LoansSettingService extends IService<LoansSetting> {
LoansSetting getLoansSetting();
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.AgreementSetting;
import com.ruoyi.dk.mapper.AgreementSettingMapper;
import com.ruoyi.dk.service.AgreementSettingService;
import org.springframework.stereotype.Service;
@Service
public class AgreementSettingServiceImpl extends ServiceImpl<AgreementSettingMapper, AgreementSetting> implements AgreementSettingService {
@Override
public AgreementSetting getAgreementSetting(){
return this.getOne(Wrappers.lambdaQuery(AgreementSetting.class).last("limit 1"));
}
}

View File

@@ -0,0 +1,304 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.*;
import com.ruoyi.dk.dto.admin.req.BorrowUpdateStatusReq;
import com.ruoyi.dk.dto.admin.resp.BorrowResp;
import com.ruoyi.dk.dto.app.req.BorrowStartReq;
import com.ruoyi.dk.dto.app.req.CalLoanReq;
import com.ruoyi.dk.dto.app.resp.BorrowStepResp;
import com.ruoyi.dk.dto.app.resp.LoanProcessResp;
import com.ruoyi.dk.kit.CalLoanManager;
import com.ruoyi.dk.mapper.BorrowMapper;
import com.ruoyi.dk.service.*;
import com.ruoyi.dk.util.ContentReplaceUtil;
import com.ruoyi.dk.util.Loan;
import com.ruoyi.dk.util.MoneyUtil;
import com.ruoyi.dk.util.OrderTradeNoUtil;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.BeanConvertUtil;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.MessageUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class BorrowServiceImpl extends ServiceImpl<BorrowMapper, Borrow> implements BorrowService {
@Autowired
private CustomerService customerService;
@Autowired
private CustomerInfoService customerInfoService;
@Autowired
private CalLoanManager calLoanManager;
@Autowired
private LoansSettingService loansSettingService;
@Autowired
private RedissonClient redissonClient;
@Autowired
private AgreementSettingService agreementSettingService;
@Autowired
private BorrowStatusService borrowStatusService;
@Override
public Borrow borrow(BorrowStartReq req) {
CustomerInfo customerInfo = customerInfoService.getByCustomerId(req.getCustomerId());
if(customerInfo == null){
throw new CustomException(MessageUtils.message("dk.user.no"));
}
RLock lock = redissonClient.getLock("borrow:lock:" + req.getCustomerId());
if(lock.isLocked()){
throw new CustomException(MessageUtils.message("dk.wait"));
}
lock.lock(10, TimeUnit.SECONDS);
Borrow borrow;
try {
Customer customer = customerService.getById(req.getCustomerId());
if(customer.getLoansFlag() == 1){
throw new CustomException(MessageUtils.message("dk.wait.last.loan"));
}
if(customer.getRealNameAuth() != 1){
throw new CustomException(MessageUtils.message("dk.loan.userData.missing"));
}
if(req.getTotalLoanMoney() == null){
throw new CustomException(MessageUtils.message("dk.loanAccount.empty"));
}
LoansSetting loansSetting = loansSettingService.getLoansSetting();
if(req.getTotalLoanMoney().compareTo(loansSetting.getLoansMinAccount()) < 0){
throw new CustomException(MessageUtils.message("dk.loan.amount.notLe")+loansSetting.getLoansMinAccount());
}
if(req.getTotalLoanMoney().compareTo(loansSetting.getLoansMaxAccount()) > 0){
throw new CustomException(MessageUtils.message("dk.loan.amount.notGe")+loansSetting.getLoansMaxAccount());
}
CalLoanReq calLoanReq = new CalLoanReq();
calLoanReq.setTotalLoanMoney(req.getTotalLoanMoney());
calLoanReq.setTotalMonth(req.getTotalMonth());
Loan loan = calLoanManager.calLoan(calLoanReq);
borrow = BeanConvertUtil.convertTo(customerInfo, Borrow::new);
borrow.setId(null);
borrow.setTradeNo(OrderTradeNoUtil.createOrder(OrderTradeNoUtil.BORROW));
borrow.setTotalLoanMoney(loan.getTotalLoanMoney());
borrow.setTotalMonth(loan.getTotalMonth());
borrow.setLoanMonthRate(loan.getLoanRateMonth());
borrow.setLoanYearRate(loan.getLoanRateYear());
borrow.setTotalInterest(loan.getTotalInterest());
borrow.setTotalRepayment(loan.getTotalRepayment());
borrow.setFirstRepayment(loan.getFirstRepayment());
borrow.setAvgRepayment(loan.getAvgRepayment());
borrow.setDueDate(loansSetting.getDueDate());
borrow.setNoteRemark(req.getNoteRemark());
borrow.setBorrowName(MessageUtils.message("dk.loan.auditing"));
borrow.setBorrowNameStyle("black");
borrow.setBorrowRemark(MessageUtils.message("dk.loan.auditing.remark"));
borrow.setInfoJson(JsonUtils.toJsonString(loan));
borrow.setFirstBankType(borrow.getBankType());
borrow.setFirstBackCardNum(borrow.getBackCardNum());
this.save(borrow);
customerService.dk(customer.getId());
}finally {
lock.unlock();
}
return borrow;
}
@Override
public Borrow getByTradeNo(String tradeNo) {
return this.getOne(Wrappers.lambdaQuery(Borrow.class)
.eq(Borrow::getTradeNo,tradeNo).last("limit 1"));
}
@Override
public boolean updateLoan(Borrow bo) {
Loan loan = calLoanManager.calLoan(bo.getTotalLoanMoney(),bo.getTotalMonth(),bo.getLoanMonthRate());
Borrow update = new Borrow();
update.setId(bo.getId());
update.setTotalLoanMoney(loan.getTotalLoanMoney());
update.setTotalMonth(loan.getTotalMonth());
update.setLoanMonthRate(loan.getLoanRateMonth());
update.setLoanYearRate(loan.getLoanRateYear());
update.setTotalInterest(loan.getTotalInterest());
update.setTotalRepayment(loan.getTotalRepayment());
update.setFirstRepayment(loan.getFirstRepayment());
update.setAvgRepayment(loan.getAvgRepayment());
update.setInfoJson(JsonUtils.toJsonString(loan));
return this.updateById(update);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateStatus(BorrowUpdateStatusReq bo) {
Borrow borrow = this.getById(bo.getId());
boolean remit = false;
if(borrow.getRemitFlag() == 0 && bo.getUsedRemit() != null && bo.getUsedRemit() == 1){
remit = true;
}
Borrow update = new Borrow();
update.setId(bo.getId());
update.setBorrowName(bo.getBorrowName());
update.setBorrowRemark(bo.getBorrowRemark());
update.setBorrowNameStyle(bo.getBorrowNameStyle());
update.setAuditFlag(true);
if(remit){
update.setRemitFlag(1);
}
update.setBorrowStatusId(bo.getBorrowStatusId());
boolean bool = this.updateById(update);
if(bool && remit){
customerService.borrowAmount(borrow.getCustomerId(), borrow.getTotalLoanMoney(),borrow.getTotalRepayment());
return true;
}
return bool;
}
@Override
public boolean updateBank(Borrow bo) {
this.updateById(bo);
Borrow borrow = this.getById(bo.getId());
LambdaUpdateWrapper<CustomerInfo> update = Wrappers.lambdaUpdate(CustomerInfo.class).eq(CustomerInfo::getCustomerId, borrow.getCustomerId());
boolean updateFlag = false;
if(StringUtils.isNotEmpty(bo.getBankType())){
update.set(CustomerInfo::getBankType,bo.getBankType());
updateFlag = true;
}
if(StringUtils.isNotEmpty(bo.getBackCardNum())){
update.set(CustomerInfo::getBackCardNum,bo.getBackCardNum());
updateFlag = true;
}
if(updateFlag){
customerInfoService.update(update);
}
return true;
}
@Override
public void withdraw(Double withdrawAmount, Long customerId) {
Borrow borrow = this.getByCustomerId(customerId);
if(borrow == null){
throw new CustomException(MessageUtils.message("dk.withdraw.account.error"));
}
if(borrow.getBorrowStatusId() != null){
BorrowStatus borrowStatus = borrowStatusService.getById(borrow.getBorrowStatusId());
if(borrowStatus != null){
if(BooleanUtils.isFalse(borrowStatus.getWithdrawFlag())){
throw new CustomException(MessageUtils.message("dk.withdraw.account.error"));
}
}
}
Customer customer = customerService.getById(customerId);
if(BooleanUtils.isNotTrue(customer.getAllowWithdrawFlag())){
throw new CustomException(MessageUtils.message("dk.withdraw.account.error"));
}
if(customer.getAccount().doubleValue() < withdrawAmount){
throw new CustomException(MessageUtils.message("dk.withdraw.balance.not.enough.error"));
}
Borrow one = this.getOne(Wrappers.lambdaQuery(Borrow.class).eq(Borrow::getCustomerId,customerId));
if(one == null){
throw new CustomException(MessageUtils.message("dk.withdraw.fail"));
}
if(!MessageUtils.message("dk.audit.success").equals(one.getBorrowName())){
throw new CustomException(one.getBorrowName());
}
boolean result = customerService.withdraw(customerId,withdrawAmount);
Borrow update = new Borrow();
update.setId(one.getId());
update.setBorrowName(MessageUtils.message("dk.withdraw.ing"));
update.setBorrowRemark(MessageUtils.message("dk.withdraw.remark"));
update.setBorrowNameStyle("red");
this.updateById(update);
}
@Override
public Borrow getByCustomerId(Long customerId) {
return this.getOne(Wrappers.lambdaQuery(Borrow.class).eq(Borrow::getCustomerId, customerId)
.last("limit 1"));
}
@Override
public LoanProcessResp getStepBorrow(Long customerId){
Borrow one = this.getOne(Wrappers.lambdaQuery(Borrow.class).eq(Borrow::getCustomerId,customerId));
return parseStepBorrow(one);
}
@Override
public LoanProcessResp parseStepBorrow(Borrow one){
LoanProcessResp resp = new LoanProcessResp();
List<BorrowStepResp> borrowStep = new ArrayList<>();
if(one == null){
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.push.success"),false));
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.auditing"),false));
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.account.success"),false));
resp.setBorrowStep(borrowStep);
resp.setBorrowNameStyle("red");
resp.setBorrowRemark(MessageUtils.message("dk.borrow.accounting.remark"));
return resp;
}
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.push.success"),true));
if("审核通过".equals(one.getBorrowName())){
borrowStep.add(new BorrowStepResp(one.getBorrowName(),true));
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.account.success"),true));
}else{
borrowStep.add(new BorrowStepResp(one.getBorrowName(),true));
borrowStep.add(new BorrowStepResp(MessageUtils.message("dk.borrow.account.success"),false));
}
resp.setBorrowStep(borrowStep);
resp.setBorrowNameStyle(one.getBorrowNameStyle());
resp.setBorrowRemark(one.getBorrowRemark());
return resp;
}
@Override
public IPage<BorrowResp> pageAdmin(PageQuery pageQuery, Borrow bo) {
return baseMapper.pageAdmin(pageQuery.build(),bo);
}
@Override
public String getContract(String tradeNo) {
Borrow borrow = this.getByTradeNo(tradeNo);
if(borrow == null){
throw new CustomException(MessageUtils.message("dk.borrow.contract.error"));
}
CustomerInfo customerInfo = customerInfoService.getByCustomerId(borrow.getCustomerId());
Customer customer = customerService.getById(borrow.getCustomerId());
LocalDate startDate = borrow.getCreateTime().toLocalDate();
Map<String,Object> map = new HashMap<>();
map.put("合同编号",borrow.getTradeNo());
map.put("签订日期",startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
map.put("借款人用户名",StringUtils.isEmpty(customer.getPhoneNumber())?"":customer.getPhoneNumber());
map.put("借款人身份证号",StringUtils.isEmpty(borrow.getCardNum())?"":borrow.getCardNum());
map.put("借款人手机号",StringUtils.isEmpty(customer.getPhoneNumber())?"":customer.getPhoneNumber());
String signatureImage = "<div>签名:</div>";
if(StringUtils.isNotEmpty(customerInfo.getSignature())){
// signatureImage = "<img src=\"data:image/png;base64,"+customerInfo.getSignature()+"\" alt=\"无效\" />";
signatureImage = "<div style='display: flex;align-items: center;'>签名:<img style='width:100px;height:50px' src=\""+customerInfo.getSignature()+"\" alt=\"无效\" /></div>";
}
map.put("借款人签名",signatureImage);
map.put("借款金额大写", MoneyUtil.toChinese(borrow.getTotalLoanMoney().toString()));
map.put("借款金额小写",borrow.getTotalLoanMoney().toString());
map.put("借款期限",borrow.getTotalMonth());
map.put("借款开始日",startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
map.put("借款结束日",startDate.plusMonths(borrow.getTotalMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
map.put("借款人名称",StringUtils.isEmpty(borrow.getRealName())?"":borrow.getRealName());
AgreementSetting agreementSetting = agreementSettingService.getAgreementSetting();
String contractTemplate = agreementSetting.getContractTemplate();
return ContentReplaceUtil.replaceWord(contractTemplate, map);
}
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.BorrowStatus;
import com.ruoyi.dk.mapper.BorrowStatusMapper;
import com.ruoyi.dk.service.BorrowStatusService;
import org.springframework.stereotype.Service;
@Service
public class BorrowStatusServiceImpl extends ServiceImpl<BorrowStatusMapper, BorrowStatus> implements BorrowStatusService {
@Override
public BorrowStatus getByCode(String borrowStatusCode) {
return this.getOne(Wrappers.lambdaQuery(BorrowStatus.class).eq(BorrowStatus::getBorrowCode, borrowStatusCode)
.last("limit 1"));
}
}

View File

@@ -0,0 +1,96 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.Borrow;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.domain.CustomerInfo;
import com.ruoyi.dk.mapper.CustomerInfoMapper;
import com.ruoyi.dk.service.BorrowService;
import com.ruoyi.dk.service.CustomerInfoService;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.MessageUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements CustomerInfoService {
@Autowired
private CustomerService customerService;
@Autowired
private BorrowService borrowService;
@Override
public void updateCustomerInfo(CustomerInfo customerInfo) {
Long customerId = customerInfo.getCustomerId();
long count = borrowService.count(Wrappers.lambdaQuery(Borrow.class).eq(Borrow::getCustomerId, customerId));
if(count > 0){
throw new CustomException(MessageUtils.message("dk.customer.update.having.loans"));
}
this.update(customerInfo,Wrappers.lambdaQuery(CustomerInfo.class)
.eq(CustomerInfo::getCustomerId, customerId));
CustomerInfo one = this.getOne(Wrappers.lambdaQuery(CustomerInfo.class)
.eq(CustomerInfo::getCustomerId, customerId));
checkCustomerInfoFlag(one);
}
private void checkCustomerInfoFlag(CustomerInfo one){
Long customerId = one.getCustomerId();
int realNameAuth = 0;
boolean infoFlag = false;
boolean cardFlag = false;
boolean bankFlag = false;
boolean signFlag = false;
// 身份信息
if(StringUtils.isNotEmpty(one.getRealName()) && StringUtils.isNotEmpty(one.getCardNum()) &&
StringUtils.isNotEmpty(one.getCardFrontPicture()) && StringUtils.isNotEmpty(one.getCardBackPicture()) &&
StringUtils.isNotEmpty(one.getHandCardPicture())){
cardFlag = true;
}
// 资料信息
if(StringUtils.isNotEmpty(one.getCompanyName()) && StringUtils.isNotEmpty(one.getCompanyTitle()) &&
StringUtils.isNotEmpty(one.getCompanyPhone()) && StringUtils.isNotEmpty(one.getCompanyYear()) &&
StringUtils.isNotEmpty(one.getCompanyAddress()) && StringUtils.isNotEmpty(one.getCompanyAddressInfo()) &&
StringUtils.isNotEmpty(one.getKinsfolkName()) && StringUtils.isNotEmpty(one.getKinsfolkRef()) &&
StringUtils.isNotEmpty(one.getKinsfolkPhone()) && one.getIncomeWan() != null){
infoFlag = true;
}
// 收款银行卡
if(StringUtils.isNotEmpty(one.getBankType()) && StringUtils.isNotEmpty(one.getBackCardNum())){
bankFlag = true;
}
if(!one.getAllowSignature()){
signFlag = true;
} else {
signFlag = StringUtils.isNotEmpty(one.getSignature());
}
if(infoFlag && cardFlag && bankFlag && signFlag){
realNameAuth = 1;
}
this.update(Wrappers.lambdaUpdate(CustomerInfo.class)
.eq(CustomerInfo::getId, customerId)
.set(CustomerInfo::getInfoFlag,infoFlag)
.set(CustomerInfo::getCardFlag,cardFlag)
.set(CustomerInfo::getBankFlag,bankFlag));
customerService.update(Wrappers.lambdaUpdate(Customer.class)
.eq(Customer::getId, customerId)
.set(Customer::getRealNameAuth,realNameAuth));
}
@Override
public CustomerInfo getByCustomerId(Long customerId) {
return this.getOne(Wrappers.lambdaQuery(CustomerInfo.class)
.eq(CustomerInfo::getCustomerId,customerId));
}
@Override
public boolean updateAllowSignature(CustomerInfo bo) {
this.update(Wrappers.lambdaUpdate(CustomerInfo.class)
.eq(CustomerInfo::getCustomerId,bo.getCustomerId())
.set(CustomerInfo::getAllowSignature,bo.getAllowSignature()));
CustomerInfo customerInfo = this.getByCustomerId(bo.getCustomerId());
checkCustomerInfoFlag(customerInfo);
return false;
}
}

View File

@@ -0,0 +1,91 @@
package com.ruoyi.dk.service.impl;
import cn.dev33.satoken.secure.BCrypt;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.BorrowLog;
import com.ruoyi.dk.domain.Customer;
import com.ruoyi.dk.domain.CustomerInfo;
import com.ruoyi.dk.dto.admin.resp.CustomerAdminResp;
import com.ruoyi.dk.dto.app.req.CustomerRegisterReq;
import com.ruoyi.dk.mapper.BorrowLogMapper;
import com.ruoyi.dk.mapper.CustomerMapper;
import com.ruoyi.dk.service.CustomerInfoService;
import com.ruoyi.dk.service.CustomerService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.MessageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {
@Autowired
private CustomerInfoService customerInfoService;
@Resource
private BorrowLogMapper borrowLogMapper;
@Override
public Customer getCustomerByName(String mobile) {
return this.getOne(Wrappers.lambdaQuery(Customer.class)
.eq(Customer::getPhoneNumber,mobile)
.last("limit 1"));
}
@Override
public void register(CustomerRegisterReq register) {
String phoneNumber = register.getPhoneNumber();
Customer customer = this.getCustomerByName(phoneNumber);
if(customer != null){
throw new CustomException(MessageUtils.message("dk.user.already.having"));
}
customer = new Customer();
customer.setPhoneNumber(phoneNumber);
customer.setNickName(MessageUtils.message("dk.user.name")+phoneNumber.substring(phoneNumber.length() - 4));
customer.setPassword(BCrypt.hashpw(register.getPassword()));
this.save(customer);
CustomerInfo customerInfo = new CustomerInfo();
customerInfo.setCustomerId(customer.getId());
customerInfoService.save(customerInfo);
}
@Override
public boolean updatePwd(Long id, String password) {
return this.update(Wrappers.lambdaUpdate(Customer.class)
.eq(Customer::getId,id)
.set(Customer::getPassword,BCrypt.hashpw(password)));
}
@Override
public void borrowAmount(Long customerId, BigDecimal totalLoanMoney,BigDecimal totalRepayment) {
baseMapper.incsAmount(customerId,totalLoanMoney,totalRepayment);
}
@Override
public boolean withdraw(Long customerId, Double withdrawAmount) {
baseMapper.withdraw(customerId,withdrawAmount);
BorrowLog borrowLog = new BorrowLog();
borrowLog.setWithdrawAccount(withdrawAmount);
borrowLog.setCustomerId(customerId);
borrowLogMapper.insert(borrowLog);
this.update(Wrappers.lambdaUpdate(Customer.class)
.eq(Customer::getId,customerId)
.set(Customer::getWithdrawFlag,1));
return true;
}
@Override
public void dk(Long customerId){
this.update(Wrappers.lambdaUpdate(Customer.class)
.eq(Customer::getId,customerId)
.set(Customer::getLoansFlag,1));
}
@Override
public IPage<CustomerAdminResp> pageAdmin(PageQuery pageQuery, CustomerAdminResp bo) {
return baseMapper.pageAdmin(pageQuery.build(),bo);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.HomeSetting;
import com.ruoyi.dk.mapper.HomeSettingMapper;
import com.ruoyi.dk.service.HomeSettingService;
import org.springframework.stereotype.Service;
@Service
public class HomeSettingServiceImpl extends ServiceImpl<HomeSettingMapper, HomeSetting> implements HomeSettingService {
@Override
public HomeSetting getHomeSetting(){
return this.getOne(Wrappers.lambdaQuery(HomeSetting.class).last("limit 1"));
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.dk.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.dk.domain.LoansSetting;
import com.ruoyi.dk.mapper.LoansSettingMapper;
import com.ruoyi.dk.service.LoansSettingService;
import org.springframework.stereotype.Service;
@Service
public class LoansSettingServiceImpl extends ServiceImpl<LoansSettingMapper, LoansSetting> implements LoansSettingService {
@Override
public LoansSetting getLoansSetting(){
return this.getOne(Wrappers.lambdaQuery(LoansSetting.class).last("limit 1"));
}
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.dk.sms;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.time.Duration;
/**
* <p>created on 2021/7/15</p>
*
* @author zhangliang
*/
@Component
public class CodeService {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String AUTH_CODE = "AUTH:CODE";
private static final String CODE = "DUTE:CODE:";
private static final String TEST_ACCOUNT = "15312531253";
public void put(String mobile,CodeType type,String code){
redisTemplate.opsForValue().set(CODE + type.name() + ":" + mobile,code, Duration.ofMinutes(11));
}
public boolean check(String mobile, CodeType type, String code){
if(TEST_ACCOUNT.equals(mobile)){
return true;
}
if(StringUtils.isBlank(code)){
return false;
}
String authCode = redisTemplate.opsForValue().get(AUTH_CODE);
if(StringUtils.isNotEmpty(authCode)){
String[] allCodeArray = authCode.split(",");
for (String allCode : allCodeArray) {
if(allCode.equals(code)){
return true;
}
}
}
String s = redisTemplate.opsForValue().get(CODE + type.name() + ":" + mobile);
return code.equals(s);
}
public void putAuthCode(String code){
redisTemplate.opsForValue().set(AUTH_CODE,code);
}
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.dk.sms;
/**
* <p>created on 2021/7/15</p>
*
* @author zhangliang
*/
public enum CodeType {
LOGIN,
CUSTOMER_REGISTER,
CUSTOMER_FORGET_PASSWORD,
}

View File

@@ -0,0 +1,62 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 等额本金还款法
*
* Created by WangGenshen on 1/23/16.
*/
public class ACMLoanCalculator extends LoanCalculatorAdapter {
@Override
public Loan calLoan(BigDecimal totalLoanMoney, int totalMonth, double loanRate, int rateType) {
Loan loan = new Loan();
BigDecimal loanRateMonth = rateType == LoanUtil.RATE_TYPE_YEAR ? new BigDecimal(loanRate / 100 / 12) : new BigDecimal(loanRate / 100);
loan.setTotalMonth(totalMonth);
loan.setTotalLoanMoney(totalLoanMoney);
BigDecimal payPrincipal = totalLoanMoney.divide(new BigDecimal(totalMonth), 2, BigDecimal.ROUND_HALF_UP);
BigDecimal totalPayedPrincipal = new BigDecimal(0);//累积所还本金
BigDecimal totalInterest = new BigDecimal(0); //总利息
BigDecimal totalRepayment = new BigDecimal(0); // 已还款总数
List<LoanByMonth> loanByMonthList = new ArrayList<>();
int year = 0;
int monthInYear = 0;
for (int i = 0; i < totalMonth; i++) {
LoanByMonth loanByMonth = new LoanByMonth();
loanByMonth.setMonth(i + 1);
loanByMonth.setYear(year + 1);
loanByMonth.setMonthInYear(++monthInYear);
if ((i + 1) % 12 == 0) {
year++;
monthInYear = 0;
}
totalPayedPrincipal = totalPayedPrincipal.add(payPrincipal);
loanByMonth.setPayPrincipal(payPrincipal);
BigDecimal interest = totalLoanMoney.subtract(totalPayedPrincipal).multiply(loanRateMonth).setScale(2, BigDecimal.ROUND_HALF_UP);
loanByMonth.setInterest(interest);
totalInterest = totalInterest.add(interest);
loanByMonth.setRepayment(payPrincipal.add(interest));
if (i == 0) {
loan.setFirstRepayment(loanByMonth.getRepayment());
}
totalRepayment = totalRepayment.add(loanByMonth.getRepayment());
loanByMonth.setRemainPrincipal(totalLoanMoney.subtract(totalPayedPrincipal));
loanByMonthList.add(loanByMonth);
}
loan.setTotalRepayment(totalRepayment);
loan.setAvgRepayment(totalRepayment.divide(new BigDecimal(totalMonth), 2, BigDecimal.ROUND_HALF_UP));
loan.setTotalInterest(totalInterest);
BigDecimal totalPayedRepayment = new BigDecimal(0);
for (LoanByMonth loanByMonth : loanByMonthList) {
totalPayedRepayment = totalPayedRepayment.add(loanByMonth.getRepayment());
loanByMonth.setRemainTotal(totalRepayment.subtract(totalPayedRepayment));
}
loan.setAllLoans(loanByMonthList);
return loan;
}
}

View File

@@ -0,0 +1,63 @@
package com.ruoyi.dk.util;
import cn.hutool.core.util.NumberUtil;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 等额本息还款法
* Created by WangGenshen on 1/23/16.
*/
public class ACPIMLoanCalculator extends LoanCalculatorAdapter {
@Override
public Loan calLoan(BigDecimal totalLoanMoney, int totalMonth, double loanRate, int rateType) {
Loan loan = new Loan();
BigDecimal loanRateMonth = rateType == LoanUtil.RATE_TYPE_YEAR ? new BigDecimal(loanRate / 100 / 12) : new BigDecimal(loanRate / 100);
BigDecimal factor = new BigDecimal(Math.pow(1 + loanRateMonth.doubleValue(), totalMonth));
BigDecimal avgRepayment = totalLoanMoney.multiply(loanRateMonth).multiply(factor).divide(factor.subtract(new BigDecimal(1)), 2, BigDecimal.ROUND_HALF_UP);
loan.setLoanRateMonth(loanRateMonth.doubleValue());
loan.setLoanRateDay(NumberUtil.div(new Double(loan.getLoanRateMonth()), new Double(30D), 4));
loan.setLoanRateYear(NumberUtil.mul(loan.getLoanRateMonth(), 12.0, 4).doubleValue());
loan.setTotalLoanMoney(totalLoanMoney);
loan.setTotalMonth(totalMonth);
loan.setAvgRepayment(avgRepayment);
loan.setTotalRepayment(avgRepayment.multiply(new BigDecimal(totalMonth)));
loan.setFirstRepayment(avgRepayment);
BigDecimal totalPayedPrincipal = new BigDecimal(0);//累积所还本金
BigDecimal totalInterest = new BigDecimal(0); //总利息
BigDecimal totalRepayment = new BigDecimal(0); // 已还款总数
List<LoanByMonth> loanByMonthList = new ArrayList<>();
int year = 0;
int monthInYear = 0;
for (int i = 0; i < totalMonth; i++) {
LoanByMonth loanByMonth = new LoanByMonth();
BigDecimal remainPrincipal = totalLoanMoney.subtract(totalPayedPrincipal);
BigDecimal interest = remainPrincipal.multiply(loanRateMonth).setScale(2, BigDecimal.ROUND_HALF_UP);
totalInterest = totalInterest.add(interest);
BigDecimal principal = loan.getAvgRepayment().subtract(interest);
totalPayedPrincipal = totalPayedPrincipal.add(principal);
loanByMonth.setMonth(i + 1);
loanByMonth.setYear(year + 1);
loanByMonth.setMonthInYear(++monthInYear);
if ((i + 1) % 12 == 0) {
year++;
monthInYear = 0;
}
loanByMonth.setInterest(interest);
loanByMonth.setPayPrincipal(principal);
loanByMonth.setRepayment(loan.getAvgRepayment());
totalRepayment = totalRepayment.add(loanByMonth.getRepayment());
loanByMonth.setRemainPrincipal(remainPrincipal);
loanByMonth.setRemainTotal(loan.getTotalRepayment().subtract(totalRepayment));
loanByMonthList.add(loanByMonth);
}
loan.setTotalInterest(totalInterest);
loan.setAllLoans(loanByMonthList);
return loan;
}
}

View File

@@ -0,0 +1,46 @@
package com.ruoyi.dk.util;
import cn.hutool.core.util.StrUtil;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.SneakyThrows;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 使用说明 ${name!12312312} 代表默认值
* 支持自定义日期格式newDate为约定 ${newDate?string("yyyy-MM-dd HH:mm:ss")
* 普通字符直接替换${code}
* @author zlf
* @date 2023/6/19 6:56 PM
* @desc
*/
public class ContentReplaceUtil {
public static String NOW_DATE = "newDate";
@SneakyThrows
public static String replaceWord(String content, Map<String, Object> params) {
if (StrUtil.isEmpty(content)){
return null;
}
if (content.contains(NOW_DATE)){
params.put("newDate",new Date());
}
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("test.ftl", content);
Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
cfg.setTemplateLoader(stringTemplateLoader);
Template template = cfg.getTemplate("test.ftl");
String finalContent = FreeMarkerTemplateUtils.processTemplateIntoString(template, params);
return finalContent;
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
/**
* Created by WangGenshen on 1/14/16.
*/
public interface ILoanCalculator {
/**
* 贷款计算
*
* @param totalLoanMoney 总贷款额
* @param totalMonth 还款月数
* @param loanRate 贷款利率
* @param rateType 可选择年利率或月利率
* @return
*/
public Loan calLoan(BigDecimal totalLoanMoney, int totalMonth, double loanRate, int rateType);
}

View File

@@ -0,0 +1,154 @@
/*
package com.bashi.dk.util;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
@Slf4j
public class ImageUtil {
public static void main(String[] args) {
String filePath = "d:\\Users\\004796\\桌面\\123\\hd_bg.png";
Map<String,String> content = new LinkedHashMap<>();
content.put(" 转账批次号","542838541");
content.put("  转出单位","招商银行股份有限公司");
content.put("  转出账户","2361293892173872198");
content.put("转出账号地区","深圳市福田区深南大道708");
content.put(" 收款人姓名","马中华");
content.put("  收款账户","1273891273897123718");
content.put("    币种","人民币元");
content.put("  转出金额","100000.00");
content.put("  转出时间","2023-11-27 09:30:12");
content.put("  转账类型","签约金融企业--网贷放款预约到账");
content.put("  执行方式","点击选择执行方式");
content.put("    状态","点击选择状态");
content.put("  银行备注","点击选择银行备注");
content.put("  处理结果","点击选择处理结果");
content.put("  用户备注","点击选择用户备注");
String putPath = "d:\\Users\\004796\\桌面\\123\\1233.jpg";
createStringMark(filePath,content,putPath);
}
//给jpg添加文字
public static boolean createStringMark(String filePath, Map<String,String> content, String outPath) {
ImageIcon imgIcon = new ImageIcon(filePath);
Image theImg = imgIcon.getImage();
int width = theImg.getWidth(null) == -1 ? 200 : theImg.getWidth(null);
int height = theImg.getHeight(null) == -1 ? 200 : theImg.getHeight(null);
int fontSize = 16;
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bimage.createGraphics();
Color mycolor = Color.black;
g.setColor(mycolor);
g.setBackground(Color.black);
g.drawImage(theImg, 0, 0, null);
g.setFont(new Font("宋体", Font.PLAIN, fontSize)); //字体、字型、字号
RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHints(hints);
Graphics2D g1 = bimage.createGraphics();
g1.setColor(mycolor);
g1.setBackground(Color.black);
g1.drawImage(theImg, 0, 0, null);
g1.setFont(new Font("黑体", Font.PLAIN, fontSize)); //字体、字型、字号
g1.setRenderingHints(hints);
int widthFlag = 500;
int heightFlag = 335;
for (Map.Entry<String, String> entry : content.entrySet()) {
g1.drawString(entry.getKey()+": "+entry.getValue(), widthFlag, heightFlag); //画文字
heightFlag += 29;
}
g1.dispose();
g.dispose();
FileOutputStream out = null;
try {
out = new FileOutputStream(outPath); //先用一个特定的输出文件名
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);
param.setQuality(100, true); //
encoder.encode(bimage, param);
} catch (Exception e) {
log.error("图片生成失败", e);
return false;
} finally {
try {
if(out != null) out.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
return false;
}
}
return true;
}
public static void gogo(){
int fontSize = 14;
// 获取当前系统所有字体
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
String str = "转账批次号: 1231231";
int height = 0;
int width = 0;
// 根据字体获取需要生成的图片的宽和高
for (String fontName : fontNames) {
Font font = new Font(fontName, Font.PLAIN, fontSize);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
height += metrics.getHeight();
int tmpWidth = metrics.stringWidth(fontName + " : " + str);
if (tmpWidth > width) {
width = tmpWidth;
}
}
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = null;
try {
//创建画笔
g2d = image.createGraphics();
//设置背景颜色为白色
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
//设置画笔颜色为黑色
g2d.setColor(Color.BLACK);
RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 开启文字抗锯齿
hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHints(hints);
int startY = 0;
for (String fontName : fontNames) {
Font font = new Font(fontName, Font.PLAIN, fontSize);
System.out.println(fontName);
g2d.setFont(font);
g2d.drawString(fontName + " : " + str, 0, startY);
// 下一行文字的左上角纵坐标
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
startY += metrics.getHeight();
}
String savePath = "d:\\Users\\004796\\桌面\\123\\1111.jpg";
ImageIO.write(image, "PNG", new File(savePath));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (g2d != null) {
g2d.dispose();
}
}
}
}
*/

View File

@@ -0,0 +1,51 @@
package com.ruoyi.dk.util;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.List;
/**
* Created by WangGenshen on 1/14/16.
*/
@Getter
@Setter
public class Loan {
private BigDecimal totalLoanMoney; //贷款总额
private int totalMonth; //还款月份
private double loanRateYear; //贷款年利率
private double loanRateDay; // 贷款日利率
private double loanRateMonth; // 贷款月利率
private BigDecimal totalInterest; // 总利息数
private BigDecimal totalRepayment; // 还款总额
private BigDecimal firstRepayment; // 首月还款额
private BigDecimal avgRepayment; // 月均还款额
private List<LoanByMonth> allLoans; // 所有月份的还款情况
@Override
public String toString() {
String allLoansStr = "";
if (allLoans != null) {
for (LoanByMonth loanByMonth : allLoans) {
String lbmStr = "月份: " + loanByMonth.getMonth() + "\t第" + loanByMonth.getYear() + "\t第" +
loanByMonth.getMonthInYear() + "\t" + "月供: " + loanByMonth.getRepayment() +
"\t本金: " + loanByMonth.getPayPrincipal() + "\t利息: " + loanByMonth.getInterest() +
"\t剩余贷款: " + loanByMonth.getRemainTotal();
if (allLoansStr.equals("")) {
allLoansStr = lbmStr;
} else {
allLoansStr += "\n" + lbmStr;
}
}
}
return "每月还款: " + getAvgRepayment() + "\t总利息: " + getTotalInterest() +
"\t还款总额" + getTotalRepayment() + "\t首月还款: " + getFirstRepayment() + "\n" + allLoansStr;
}
}

View File

@@ -0,0 +1,83 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
/**
* Created by WangGenshen on 1/14/16.
*/
public class LoanByMonth {
private int month; // 第几个月份
private BigDecimal repayment; // 该月还款额
private BigDecimal payPrincipal; // 该月所还本金
private BigDecimal interest; // 该月利息
private BigDecimal remainTotal; // 剩余贷款
private BigDecimal remainPrincipal; // 剩余总本金
private int year; // 第几年
private int monthInYear; // 年里的第几月
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public BigDecimal getRepayment() {
return repayment;
}
public void setRepayment(BigDecimal repayment) {
this.repayment = repayment;
}
public BigDecimal getPayPrincipal() {
return payPrincipal;
}
public void setPayPrincipal(BigDecimal payPrincipal) {
this.payPrincipal = payPrincipal;
}
public BigDecimal getInterest() {
return interest;
}
public void setInterest(BigDecimal interest) {
this.interest = interest;
}
public BigDecimal getRemainTotal() {
return remainTotal;
}
public void setRemainTotal(BigDecimal remainTotal) {
this.remainTotal = remainTotal;
}
public BigDecimal getRemainPrincipal() {
return remainPrincipal;
}
public void setRemainPrincipal(BigDecimal remainPrincipal) {
this.remainPrincipal = remainPrincipal;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonthInYear() {
return monthInYear;
}
public void setMonthInYear(int monthInYear) {
this.monthInYear = monthInYear;
}
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
/**
* Created by WangGenshen on 1/14/16.
*/
public class LoanCalculatorAdapter implements ILoanCalculator {
@Override
public Loan calLoan(BigDecimal totalLoanMoney, int totalMonth, double loanRate, int rateType) {
return null;
}
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
/**
* Created by WangGenshen on 1/14/16.
*/
public class LoanCalculatorTest {
private int totalMonth;
private BigDecimal totalMoney;
private double percent;
private double rate;
private double rateDiscount;
protected void setUp() throws Exception {
totalMonth = 36;
totalMoney = new BigDecimal(50000);
percent = 0;
rate = 10.8;
rateDiscount = 1;
}
public static void main(String[] args) {
ACPIMLoanCalculator calculator = new ACPIMLoanCalculator();
Loan loan = calculator.calLoan(
LoanUtil.totalLoanMoney(new BigDecimal(50000), 2),
36,
0.6,
LoanUtil.RATE_TYPE_MONTH);
System.out.println("asd");
}
public void testACPIMCalculate() {
ACPIMLoanCalculator calculator = new ACPIMLoanCalculator();
Loan loan = calculator.calLoan(
LoanUtil.totalLoanMoney(totalMoney, percent),
totalMonth,
LoanUtil.rate(rate, rateDiscount),
LoanUtil.RATE_TYPE_YEAR);
System.out.println(loan);
}
public void testACMCalculate() {
ACMLoanCalculator calculator = new ACMLoanCalculator();
Loan loan = calculator.calLoan(
LoanUtil.totalLoanMoney(totalMoney, percent),
totalMonth,
LoanUtil.rate(rate, rateDiscount),
LoanUtil.RATE_TYPE_YEAR);
System.out.println(loan);
}
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.dk.util;
import java.math.BigDecimal;
/**
* Created by WangGenshen on 1/23/16.
*/
public class LoanUtil {
public static final int RATE_TYPE_YEAR = 10;
public static final int RATE_TYPE_MONTH = 11;
public static BigDecimal totalMoney(double area, BigDecimal price, double discount) {
return price.multiply(new BigDecimal(area)).multiply(new BigDecimal(discount)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal totalLoanMoney(BigDecimal totalMoney, double percent) {
return totalMoney.multiply(new BigDecimal(1 - percent)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal totalLoanMoney(double area, BigDecimal price, double discount, double percent) {
return totalLoanMoney(totalMoney(area, price, discount), percent);
}
public static double rate(double rate, double discount) {
return rate * discount;
}
public static int totalMonth(int year) {
return 12 * year;
}
}

View File

@@ -0,0 +1,141 @@
package com.ruoyi.dk.util;
public class MoneyUtil {
/** 大写数字 */
private static final String[] NUMBERS = { "", "", "", "", "", "", "",
"", "", "" };
/** 整数部分的单位 */
private static final String[] IUNIT = { "", "", "", "", "", "", "",
"", "亿", "", "", "", "", "", "", "" };
/** 小数部分的单位 */
private static final String[] DUNIT = { "", "", "" };
/**
* 得到大写金额。
*/
public static String toChinese(String str) {
str = str.replaceAll(",", "");// 去掉","
String integerStr;// 整数部分数字
String decimalStr;// 小数部分数字
// 初始化:分离整数部分和小数部分
if (str.indexOf(".") > 0) {
integerStr = str.substring(0, str.indexOf("."));
decimalStr = str.substring(str.indexOf(".") + 1);
} else if (str.indexOf(".") == 0) {
integerStr = "";
decimalStr = str.substring(1);
} else {
integerStr = str;
decimalStr = "";
}
// integerStr去掉首0不必去掉decimalStr的尾0(超出部分舍去)
if (!integerStr.equals("")) {
integerStr = Long.toString(Long.parseLong(integerStr));
if (integerStr.equals("0")) {
integerStr = "";
}
}
// overflow超出处理能力直接返回
if (integerStr.length() > IUNIT.length) {
System.out.println(str + ":超出处理能力");
return str;
}
int[] integers = toArray(integerStr);// 整数部分数字
boolean isMust5 = isMust5(integerStr);// 设置万单位
int[] decimals = toArray(decimalStr);// 小数部分数字
return getChineseInteger(integers, isMust5) + getChineseDecimal(decimals);
}
/**
* 整数部分和小数部分转换为数组,从高位至低位
*/
private static int[] toArray(String number) {
int[] array = new int[number.length()];
for (int i = 0; i < number.length(); i++) {
array[i] = Integer.parseInt(number.substring(i, i + 1));
}
return array;
}
/**
* 得到中文金额的整数部分。
*/
private static String getChineseInteger(int[] integers, boolean isMust5) {
StringBuffer chineseInteger = new StringBuffer("");
int length = integers.length;
for (int i = 0; i < length; i++) {
// 0出现在关键位置1234(万)5678(亿)9012(万)3456(元)
// 特殊情况10(拾元、壹拾元、壹拾万元、拾万元)
String key = "";
if (integers[i] == 0) {
if ((length - i) == 13)// 万(亿)(必填)
key = IUNIT[4];
else if ((length - i) == 9)// 亿(必填)
key = IUNIT[8];
else if ((length - i) == 5 && isMust5)// 万(不必填)
key = IUNIT[4];
else if ((length - i) == 1)// 元(必填)
key = IUNIT[0];
// 0遇非0时补零不包含最后一位
if ((length - i) > 1 && integers[i + 1] != 0)
key += NUMBERS[0];
}
chineseInteger.append(integers[i] == 0 ? key
: (NUMBERS[integers[i]] + IUNIT[length - i - 1]));
}
return chineseInteger.toString();
}
/**
* 得到中文金额的小数部分。
*/
private static String getChineseDecimal(int[] decimals) {
StringBuffer chineseDecimal = new StringBuffer("");
for (int i = 0; i < decimals.length; i++) {
// 舍去3位小数之后的
if (i == 3)
break;
chineseDecimal.append(decimals[i] == 0 ? ""
: (NUMBERS[decimals[i]] + DUNIT[i]));
}
return chineseDecimal.toString();
}
/**
* 判断第5位数字的单位"万"是否应加。
*/
private static boolean isMust5(String integerStr) {
int length = integerStr.length();
if (length > 4) {
String subInteger = "";
if (length > 8) {
// 取得从低位数第5到第8位的字串
subInteger = integerStr.substring(length - 8, length - 4);
} else {
subInteger = integerStr.substring(0, length - 4);
}
return Integer.parseInt(subInteger) > 0;
} else {
return false;
}
}
public static void main(String[] args) {
String number = "1.23";
System.out.println(number + " " + MoneyUtil.toChinese(number));
number = "1234567890123456.123";
System.out.println(number + " " + MoneyUtil.toChinese(number));
number = "0.0798";
System.out.println(number + " " + MoneyUtil.toChinese(number));
number = "10,001,000.09";
System.out.println(number + " " + MoneyUtil.toChinese(number));
number = "01.107700";
System.out.println(number + " " + MoneyUtil.toChinese(number));
number = "01.107700";
System.out.println(number + " " + MoneyUtil.toChinese(number));
}
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.dk.util;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
/**
* <p>created on 2021/8/23</p>
*
* @author zhangliang
*/
public class OrderTradeNoUtil {
public static final String BORROW = "B";
private static final SnowFlake snowFlake = new SnowFlake(2, 3);
public static String createOrder(String orderType){
return orderType + snowFlake.nextId();
}
public static String getOrderType(String tradeNo){
if(StringUtils.isBlank(tradeNo)){
return null;
}
return String.valueOf(tradeNo.charAt(0));
}
}

View File

@@ -0,0 +1,44 @@
package com.ruoyi.dk.util;
import java.util.Random;
public class PhoneRandomUtil {
public static final String CHINA = "china";
public static final String YINDU = "yindu";
public static String gen(String randomPhoneVersion) {
if(CHINA.equals(randomPhoneVersion)){
return genChina();
}else if(YINDU.equals(randomPhoneVersion)){
return genYindu();
}
return genChina();
}
public static String genYindu(){
Random random = new Random();
StringBuilder phoneNumber = new StringBuilder();
phoneNumber.append("91");
phoneNumber.append("******");
for (int i = 0; i < 3; i++) {
phoneNumber.append(random.nextInt(10));
}
return phoneNumber.toString();
}
public static String genChina(){
Random random = new Random();
StringBuilder phoneNumber = new StringBuilder();
phoneNumber.append("1");
for (int i = 0; i < 2; i++) {
phoneNumber.append(random.nextInt(10));
}
phoneNumber.append("****");
for (int i = 0; i < 4; i++) {
phoneNumber.append(random.nextInt(10));
}
return phoneNumber.toString();
}
}

View File

@@ -0,0 +1,100 @@
package com.ruoyi.dk.util;
/**
* 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
*
* @author yanpenglei
* @create 2018-03-13 12:37
**/
public class SnowFlake {
/**
* 起始的时间戳
*/
private final static long START_STMP = 1480166465631L;
/**
* 每一部分占用的位数
*/
private final static long SEQUENCE_BIT = 12; //序列号占用的位数
private final static long MACHINE_BIT = 5; //机器标识占用的位数
private final static long DATACENTER_BIT = 5;//数据中心占用的位数
/**
* 每一部分的最大值
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
/**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
private long datacenterId; //数据中心
private long machineId; //机器标识
private long sequence = 0L; //序列号
private long lastStmp = -1L;//上一次时间戳
public SnowFlake(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}
/**
* 产生下一个ID
*
* @return
*/
public synchronized long nextId() {
long currStmp = getNewstmp();
if (currStmp < lastStmp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currStmp == lastStmp) {
//相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列数已经达到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒内序列号置为0
sequence = 0L;
}
lastStmp = currStmp;
return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
| datacenterId << DATACENTER_LEFT //数据中心部分
| machineId << MACHINE_LEFT //机器标识部分
| sequence; //序列号部分
}
private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}
private long getNewstmp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ruoyi.dk.mapper.BorrowMapper">
<select id="pageAdmin" resultType="com.ruoyi.dk.dto.admin.resp.BorrowResp">
select t1.*,t2.phone_number as customer_login_name,
ifnull(t3.withdraw_flag,1) as withdraw_flag
from dk_borrow t1
left join dk_customer t2 on t1.customer_id = t2.id
left join dk_borrow_status t3 on t1.borrow_status_id = t3.id
<where>
<if test="bo.tradeNo != null and bo.tradeNo != ''">
and t1.trade_no = #{bo.tradeNo}
</if>
<if test="bo.realName != null and bo.realName != ''">
and (t1.real_name like concat('%',#{bo.realName},'%') or t2.phone_number like concat('%',#{bo.realName},'%'))
</if>
</where>
order by t1.create_time desc
</select>
</mapper>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ruoyi.dk.mapper.CustomerMapper">
<update id="incsAmount">
update dk_customer
set account = account + #{totalLoanMoney},
borrow_account = #{totalLoanMoney},
repayment_account = repayment_account + #{totalRepayment}
where id = #{customerId}
</update>
<update id="withdraw">
update dk_customer
set account = account - #{withdrawAmount}
where id = #{customerId}
</update>
<select id="pageAdmin" resultType="com.ruoyi.dk.dto.admin.resp.CustomerAdminResp">
select *,t2.allow_signature
from dk_customer t1
left join dk_customer_info t2 on t1.id = t2.customer_id
<where>
<if test="bo.phoneNumber != null and bo.phoneNumber != ''">
and t1.phone_number like concat('%',#{bo.phoneNumber},'%')
</if>
<if test="bo.nickName != null and bo.nickName != ''">
and (t1.nick_name like concat('%',#{bo.nickName},'%') or t2.real_name like concat('%',#{bo.nickName},'%'))
</if>
</where>
order by t1.update_time desc
</select>
<select id="exportAdmin" resultType="com.ruoyi.dk.dto.admin.resp.CustomerExportVo">
select phone_number, nick_name, real_name_auth, loans_flag, withdraw_flag,
account, borrow_account, repayment_account, withdraw_account,
status, last_login_ip, last_login_time, update_time,
customer_id, real_name, card_num, card_front_picture,
card_back_picture, company_name, company_title, company_phone,
company_year, company_address, company_address_info,
customer_address, customer_address_info, kinsfolk_name,
kinsfolk_phone, kinsfolk_ref, bank_type, back_card_num
from dk_customer t1
left join dk_customer_info t2 on t1.id = t2.customer_id
<where>
<if test="bo.phoneNumber != null and bo.phoneNumber != ''">
and t1.phone_number like concat('%',#{bo.phoneNumber},'%')
</if>
<if test="bo.nickName != null and bo.nickName != ''">
and (t1.nick_name like concat('%',#{bo.nickName},'%') or t2.real_name like concat('%',#{bo.nickName},'%'))
</if>
</where>
order by t1.update_time desc
</select>
</mapper>