1、新增评分量化表

2、新增费用项
3、新增币种
4、新增客商类型
5、其他bug修复
This commit is contained in:
2026-07-16 17:04:46 +08:00
parent 29bbd5144d
commit 0eba4ca98d
57 changed files with 4740 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.excel.CreditScoreQuantificationExcel;
import org.springblade.transport.excel.CreditScoreQuantificationImporter;
import org.springblade.transport.pojo.entity.CreditScoreQuantification;
import org.springblade.transport.pojo.vo.CreditScoreQuantificationVO;
import org.springblade.transport.service.ICreditScoreQuantificationService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
/**
* 评分量化表 控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "credit_score_quantification")
@RequestMapping("/credit-score-quantification")
@Tag(name = "评分量化表", description = "评分量化表")
public class CreditScoreQuantificationController extends BladeController {
private final ICreditScoreQuantificationService creditScoreQuantificationService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入id")
public R<CreditScoreQuantificationVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(creditScoreQuantificationService.detail(id));
}
/**
* 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入creditScoreQuantification")
public R<IPage<CreditScoreQuantificationVO>> list(CreditScoreQuantificationVO creditScoreQuantification, Query query) {
IPage<CreditScoreQuantificationVO> pages = creditScoreQuantificationService.selectCreditScoreQuantificationPage(Condition.getPage(query), creditScoreQuantification);
return R.data(pages);
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增或修改", description = "传入creditScoreQuantification")
public R submit(@RequestBody CreditScoreQuantificationVO creditScoreQuantification) {
return R.status(creditScoreQuantificationService.submit(creditScoreQuantification));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 4)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(creditScoreQuantificationService.removeDraft(ids));
}
/**
* 发布
*/
@PostMapping("/publish")
@ApiOperationSupport(order = 5)
@Operation(summary = "发布", description = "传入id")
public R publish(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(creditScoreQuantificationService.publish(id));
}
/**
* 启用或停用
*/
@PostMapping("/status")
@ApiOperationSupport(order = 6)
@Operation(summary = "启用或停用", description = "传入id和status")
public R status(@Parameter(description = "主键", required = true) @RequestParam Long id,
@Parameter(description = "状态", required = true) @RequestParam Integer status) {
return R.status(creditScoreQuantificationService.changeStatus(id, status));
}
/**
* 导入评分量化表
*/
@PostMapping("/import-credit-score-quantification")
@ApiOperationSupport(order = 7)
@Operation(summary = "导入评分量化表", description = "传入excel")
public R importCreditScoreQuantification(MultipartFile file) {
CreditScoreQuantificationImporter importer = new CreditScoreQuantificationImporter(creditScoreQuantificationService);
ExcelUtil.save(file, importer, CreditScoreQuantificationExcel.class);
return R.success("操作成功");
}
/**
* 导出评分量化表
*/
@GetMapping("/export-credit-score-quantification")
@ApiOperationSupport(order = 8)
@Operation(summary = "导出评分量化表")
public void exportCreditScoreQuantification(CreditScoreQuantificationVO creditScoreQuantification,
@RequestParam(required = false) String ids,
HttpServletResponse response) {
List<CreditScoreQuantificationExcel> list = creditScoreQuantificationService.exportCreditScoreQuantification(buildExportQuery(creditScoreQuantification, ids));
ExcelUtil.export(response, "评分量化表" + DateUtil.time(), "评分量化表", list, CreditScoreQuantificationExcel.class);
}
/**
* 导出模板
*/
@GetMapping("/export-template")
@ApiOperationSupport(order = 9)
@Operation(summary = "导出模板")
public void exportTemplate(HttpServletResponse response) {
List<CreditScoreQuantificationExcel> list = new ArrayList<>();
ExcelUtil.export(response, "评分量化表模板", "评分量化表", list, CreditScoreQuantificationExcel.class);
}
private LambdaQueryWrapper<CreditScoreQuantification> buildExportQuery(CreditScoreQuantificationVO creditScoreQuantification, String ids) {
LambdaQueryWrapper<CreditScoreQuantification> queryWrapper = Wrappers.<CreditScoreQuantification>lambdaQuery()
.eq(CreditScoreQuantification::getIsDeleted, 0)
.orderByDesc(CreditScoreQuantification::getCreateTime);
if (Func.isNotEmpty(ids)) {
queryWrapper.in(CreditScoreQuantification::getId, Func.toLongList(ids));
}
if (Func.isNotEmpty(creditScoreQuantification.getName())) {
queryWrapper.like(CreditScoreQuantification::getName, creditScoreQuantification.getName());
}
if (Func.isNotEmpty(creditScoreQuantification.getStatus())) {
queryWrapper.eq(CreditScoreQuantification::getStatus, creditScoreQuantification.getStatus());
}
if (Func.isNotEmpty(creditScoreQuantification.getCreateTimeStart())) {
queryWrapper.ge(CreditScoreQuantification::getCreateTime, creditScoreQuantification.getCreateTimeStart());
}
if (Func.isNotEmpty(creditScoreQuantification.getCreateTimeEnd())) {
queryWrapper.le(CreditScoreQuantification::getCreateTime, creditScoreQuantification.getCreateTimeEnd());
}
return queryWrapper;
}
}

View File

@@ -0,0 +1,109 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 评分量化表 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(20)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CreditScoreQuantificationExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("评定表名称")
private String tableName;
@ExcelProperty("数据类型")
private String rowType;
@ExcelProperty("量表备注")
private String remark;
@ExcelProperty("量表标准说明")
private String tableStandardDescription;
@ExcelProperty("状态")
private String statusName;
@ExcelProperty("评分分类")
private String categoryName;
@ExcelProperty("评分项目")
private String itemName;
@ExcelProperty("得分说明")
private String scoreDescription;
@ExcelProperty("选项描述")
private String optionDescription;
@ExcelProperty("档位选项")
private String optionName;
@ExcelProperty("分值")
private BigDecimal score;
@ExcelProperty("信用等级")
private String creditLevel;
@ExcelProperty("得分率下限")
private Integer scoreRateLower;
@ExcelProperty("得分率上限")
private Integer scoreRateUpper;
@ExcelProperty("得分率每增加")
private Integer scoreRateIncrease;
@ExcelProperty("额度下限(万元)")
private BigDecimal creditLimitLower;
@ExcelProperty("额度上限(万元)")
private BigDecimal creditLimitUpper;
@ExcelProperty("额度增加(万元)")
private BigDecimal creditLimitIncrease;
@ExcelProperty("评估标准说明")
private String ratingStandardDescription;
@ExcelProperty("报错文案")
private String errorMessage;
}

View File

@@ -0,0 +1,43 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import lombok.RequiredArgsConstructor;
import org.springblade.core.excel.support.ExcelImporter;
import org.springblade.transport.service.ICreditScoreQuantificationService;
import java.util.List;
/**
* 评分量化表导入类
*
* @author Chill
*/
@RequiredArgsConstructor
public class CreditScoreQuantificationImporter implements ExcelImporter<CreditScoreQuantificationExcel> {
private final ICreditScoreQuantificationService service;
@Override
public void save(List<CreditScoreQuantificationExcel> data) {
service.importCreditScoreQuantification(data);
}
}

View File

@@ -0,0 +1,34 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.CreditRatingStandard;
/**
* 信用等级评估标准 Mapper 接口
*
* @author Chill
*/
public interface CreditRatingStandardMapper extends BaseMapper<CreditRatingStandard> {
}

View File

@@ -0,0 +1,4 @@
<?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="org.springblade.transport.mapper.CreditRatingStandardMapper">
</mapper>

View File

@@ -0,0 +1,37 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.CreditScoreCategory;
/**
* 评分分类 Mapper 接口
*
* @author Chill
*/
public interface CreditScoreCategoryMapper extends BaseMapper<CreditScoreCategory> {
}

View File

@@ -0,0 +1,4 @@
<?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="org.springblade.transport.mapper.CreditScoreCategoryMapper">
</mapper>

View File

@@ -0,0 +1,37 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.CreditScoreItem;
/**
* 评分项目 Mapper 接口
*
* @author Chill
*/
public interface CreditScoreItemMapper extends BaseMapper<CreditScoreItem> {
}

View File

@@ -0,0 +1,4 @@
<?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="org.springblade.transport.mapper.CreditScoreItemMapper">
</mapper>

View File

@@ -0,0 +1,34 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.CreditScoreItemOption;
/**
* 评分项目选项 Mapper 接口
*
* @author Chill
*/
public interface CreditScoreItemOptionMapper extends BaseMapper<CreditScoreItemOption> {
}

View File

@@ -0,0 +1,4 @@
<?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="org.springblade.transport.mapper.CreditScoreItemOptionMapper">
</mapper>

View File

@@ -0,0 +1,52 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.springblade.transport.pojo.entity.CreditScoreQuantification;
import org.springblade.transport.pojo.vo.CreditScoreQuantificationVO;
import java.util.List;
/**
* 评分量化表 Mapper 接口
*
* @author Chill
*/
public interface CreditScoreQuantificationMapper extends BaseMapper<CreditScoreQuantification> {
/**
* 自定义分页
*
* @param page 分页参数
* @param quantification 查询参数
* @return 评分量化表列表
*/
List<CreditScoreQuantificationVO> selectCreditScoreQuantificationPage(IPage<CreditScoreQuantificationVO> page, @Param("quantification") CreditScoreQuantificationVO quantification);
}

View File

@@ -0,0 +1,54 @@
<?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="org.springblade.transport.mapper.CreditScoreQuantificationMapper">
<resultMap id="creditScoreQuantificationResultMap" type="org.springblade.transport.pojo.vo.CreditScoreQuantificationVO">
<result column="id" property="id"/>
<result column="tenant_id" property="tenantId"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
<result column="name" property="name"/>
<result column="remark" property="remark"/>
<result column="standard_description" property="standardDescription"/>
</resultMap>
<select id="selectCreditScoreQuantificationPage" resultMap="creditScoreQuantificationResultMap">
SELECT
id,
tenant_id,
create_user,
create_dept,
create_time,
update_user,
update_time,
status,
is_deleted,
name,
remark,
standard_description
FROM
blade_credit_score_quantification
WHERE
is_deleted = 0
<if test="quantification.name != null and quantification.name != ''">
<bind name="nameLike" value="'%' + quantification.name + '%'"/>
AND name LIKE #{nameLike}
</if>
<if test="quantification.status != null">
AND status = #{quantification.status}
</if>
<if test="quantification.createTimeStart != null and quantification.createTimeStart != ''">
AND create_time &gt;= #{quantification.createTimeStart}
</if>
<if test="quantification.createTimeEnd != null and quantification.createTimeEnd != ''">
AND create_time &lt;= #{quantification.createTimeEnd}
</if>
ORDER BY create_time DESC
</select>
</mapper>

View File

@@ -0,0 +1,109 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import org.springblade.core.mp.base.BaseService;
import org.springblade.transport.excel.CreditScoreQuantificationExcel;
import org.springblade.transport.pojo.entity.CreditScoreQuantification;
import org.springblade.transport.pojo.vo.CreditScoreQuantificationVO;
import java.util.List;
/**
* 评分量化表 服务类
*
* @author Chill
*/
public interface ICreditScoreQuantificationService extends BaseService<CreditScoreQuantification> {
/**
* 自定义分页
*
* @param page 分页参数
* @param quantification 查询参数
* @return 评分量化表分页
*/
IPage<CreditScoreQuantificationVO> selectCreditScoreQuantificationPage(IPage<CreditScoreQuantificationVO> page, CreditScoreQuantificationVO quantification);
/**
* 聚合详情
*
* @param id 主键
* @return 评分量化表详情
*/
CreditScoreQuantificationVO detail(Long id);
/**
* 新增或修改评分量化表全部配置
*
* @param quantification 评分量化表
* @return 是否成功
*/
boolean submit(CreditScoreQuantificationVO quantification);
/**
* 发布评分量化表
*
* @param id 主键
* @return 是否成功
*/
boolean publish(Long id);
/**
* 启用或停用
*
* @param id 主键
* @param status 状态
* @return 是否成功
*/
boolean changeStatus(Long id, Integer status);
/**
* 删除草稿量表
*
* @param ids 主键集合
* @return 是否成功
*/
boolean removeDraft(String ids);
/**
* 导入评分量化表
*
* @param data 导入数据
*/
void importCreditScoreQuantification(List<CreditScoreQuantificationExcel> data);
/**
* 导出评分量化表
*
* @param queryWrapper 查询条件
* @return 导出数据
*/
List<CreditScoreQuantificationExcel> exportCreditScoreQuantification(Wrapper<CreditScoreQuantification> queryWrapper);
}

View File

@@ -0,0 +1,698 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.excel.CreditScoreQuantificationExcel;
import org.springblade.transport.mapper.CreditRatingStandardMapper;
import org.springblade.transport.mapper.CreditScoreCategoryMapper;
import org.springblade.transport.mapper.CreditScoreItemMapper;
import org.springblade.transport.mapper.CreditScoreItemOptionMapper;
import org.springblade.transport.mapper.CreditScoreQuantificationMapper;
import org.springblade.transport.pojo.entity.CreditRatingStandard;
import org.springblade.transport.pojo.entity.CreditScoreCategory;
import org.springblade.transport.pojo.entity.CreditScoreItem;
import org.springblade.transport.pojo.entity.CreditScoreItemOption;
import org.springblade.transport.pojo.entity.CreditScoreQuantification;
import org.springblade.transport.pojo.vo.CreditRatingStandardVO;
import org.springblade.transport.pojo.vo.CreditScoreCategoryVO;
import org.springblade.transport.pojo.vo.CreditScoreItemOptionVO;
import org.springblade.transport.pojo.vo.CreditScoreItemVO;
import org.springblade.transport.pojo.vo.CreditScoreQuantificationVO;
import org.springblade.transport.service.ICreditScoreQuantificationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 评分量化表 服务实现类
*
* @author Chill
*/
@Service
@RequiredArgsConstructor
public class CreditScoreQuantificationServiceImpl extends BaseServiceImpl<CreditScoreQuantificationMapper, CreditScoreQuantification> implements ICreditScoreQuantificationService {
private static final int STATUS_NORMAL = 1;
private static final int STATUS_DISABLED = 2;
private static final int STATUS_DRAFT = 3;
private static final int NAME_MAX_LENGTH = 30;
private static final int REMARK_MAX_LENGTH = 500;
private static final int ITEM_NAME_MAX_LENGTH = 20;
private static final int SCORE_DESCRIPTION_MAX_LENGTH = 300;
private static final int OPTION_NAME_MAX_LENGTH = 100;
private static final int STANDARD_DESCRIPTION_MAX_LENGTH = 500;
private static final String CATEGORY_BASIC = "basic";
private static final String CATEGORY_PLUS = "plus";
private static final String CATEGORY_MINUS = "minus";
private static final String ROW_TYPE_MAIN = "主表";
private static final String ROW_TYPE_ITEM = "评分项目";
private static final String ROW_TYPE_OPTION = "选项";
private static final String ROW_TYPE_STANDARD = "评估标准";
private final CreditScoreCategoryMapper categoryMapper;
private final CreditScoreItemMapper itemMapper;
private final CreditScoreItemOptionMapper optionMapper;
private final CreditRatingStandardMapper standardMapper;
@Override
public IPage<CreditScoreQuantificationVO> selectCreditScoreQuantificationPage(IPage<CreditScoreQuantificationVO> page, CreditScoreQuantificationVO quantification) {
return page.setRecords(baseMapper.selectCreditScoreQuantificationPage(page, quantification));
}
@Override
public CreditScoreQuantificationVO detail(Long id) {
if (Func.isEmpty(id)) {
throw new ServiceException("主键不能为空");
}
CreditScoreQuantification quantification = getById(id);
if (Func.isEmpty(quantification) || Objects.equals(quantification.getIsDeleted(), 1)) {
throw new ServiceException("评分量化表不存在");
}
CreditScoreQuantificationVO detail = Objects.requireNonNull(BeanUtil.copyProperties(quantification, CreditScoreQuantificationVO.class));
detail.setCategories(loadCategories(id));
detail.setStandards(loadStandards(id));
return detail;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean submit(CreditScoreQuantificationVO quantification) {
prepare(quantification);
validateBase(quantification);
boolean fullValidate = Objects.equals(quantification.getStatus(), STATUS_NORMAL);
validateDetail(quantification, fullValidate);
CreditScoreQuantification entity = Objects.requireNonNull(BeanUtil.copyProperties(quantification, CreditScoreQuantification.class));
if (Func.isEmpty(entity.getStatus())) {
entity.setStatus(STATUS_DRAFT);
}
boolean result = saveOrUpdate(entity);
replaceDetail(entity.getId(), quantification);
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean publish(Long id) {
CreditScoreQuantificationVO detail = detail(id);
detail.setStatus(STATUS_NORMAL);
validateDetail(detail, true);
CreditScoreQuantification update = new CreditScoreQuantification();
update.setId(id);
update.setStatus(STATUS_NORMAL);
return updateById(update);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean changeStatus(Long id, Integer status) {
if (Func.isEmpty(id)) {
throw new ServiceException("主键不能为空");
}
if (!Objects.equals(status, STATUS_NORMAL) && !Objects.equals(status, STATUS_DISABLED)) {
throw new ServiceException("启停状态不正确");
}
CreditScoreQuantification detail = getById(id);
if (Func.isEmpty(detail) || Objects.equals(detail.getIsDeleted(), 1)) {
throw new ServiceException("评分量化表不存在");
}
if (Objects.equals(detail.getStatus(), STATUS_DRAFT)) {
throw new ServiceException("草稿量表请先发布");
}
if (Objects.equals(status, STATUS_NORMAL)) {
validateDetail(detail(id), true);
}
CreditScoreQuantification update = new CreditScoreQuantification();
update.setId(id);
update.setStatus(status);
return updateById(update);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean removeDraft(String ids) {
List<Long> idList = Func.toLongList(ids);
if (Func.isEmpty(idList)) {
throw new ServiceException("请选择需要删除的数据");
}
List<CreditScoreQuantification> list = listByIds(idList);
for (CreditScoreQuantification quantification : list) {
if (!Objects.equals(quantification.getStatus(), STATUS_DRAFT)) {
throw new ServiceException("仅草稿状态量表可删除");
}
}
deleteDetail(idList);
return deleteLogic(idList);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void importCreditScoreQuantification(List<CreditScoreQuantificationExcel> data) {
if (Func.isEmpty(data)) {
throw new ServiceException("导入数据不能为空");
}
Map<String, List<CreditScoreQuantificationExcel>> dataMap = data.stream()
.filter(row -> Func.isNotEmpty(trimToNull(row.getTableName())))
.collect(Collectors.groupingBy(row -> trimToEmpty(row.getTableName()), java.util.LinkedHashMap::new, Collectors.toList()));
if (Func.isEmpty(dataMap)) {
throw new ServiceException("评定表名称不能为空");
}
List<String> errorList = new ArrayList<>();
dataMap.forEach((tableName, rows) -> {
try {
submit(buildImportVO(tableName, rows));
} catch (Exception exception) {
errorList.add(tableName + "" + exception.getMessage());
}
});
if (Func.isNotEmpty(errorList)) {
throw new ServiceException(String.join("", errorList));
}
}
@Override
public List<CreditScoreQuantificationExcel> exportCreditScoreQuantification(Wrapper<CreditScoreQuantification> queryWrapper) {
List<CreditScoreQuantificationExcel> excelList = new ArrayList<>();
List<CreditScoreQuantification> quantificationList = list(queryWrapper);
for (CreditScoreQuantification quantification : quantificationList) {
CreditScoreQuantificationVO detail = detail(quantification.getId());
excelList.add(buildMainExcel(detail));
for (CreditScoreCategoryVO category : detail.getCategories()) {
for (CreditScoreItemVO item : category.getItems()) {
excelList.add(buildItemExcel(detail, category, item));
for (CreditScoreItemOptionVO option : item.getOptions()) {
excelList.add(buildOptionExcel(detail, category, item, option));
}
}
}
for (CreditRatingStandardVO standard : detail.getStandards()) {
excelList.add(buildStandardExcel(detail, standard));
}
}
return excelList;
}
private List<CreditScoreCategoryVO> loadCategories(Long quantificationId) {
List<CreditScoreCategory> categories = categoryMapper.selectList(Wrappers.<CreditScoreCategory>lambdaQuery()
.eq(CreditScoreCategory::getQuantificationId, quantificationId)
.eq(CreditScoreCategory::getIsDeleted, 0)
.orderByAsc(CreditScoreCategory::getSort));
if (Func.isEmpty(categories)) {
return defaultCategories();
}
List<CreditScoreItem> items = itemMapper.selectList(Wrappers.<CreditScoreItem>lambdaQuery()
.eq(CreditScoreItem::getQuantificationId, quantificationId)
.eq(CreditScoreItem::getIsDeleted, 0)
.orderByAsc(CreditScoreItem::getSort));
List<CreditScoreItemOption> options = optionMapper.selectList(Wrappers.<CreditScoreItemOption>lambdaQuery()
.eq(CreditScoreItemOption::getQuantificationId, quantificationId)
.eq(CreditScoreItemOption::getIsDeleted, 0)
.orderByAsc(CreditScoreItemOption::getSort));
Map<Long, List<CreditScoreItemOptionVO>> optionMap = options.stream()
.map(option -> Objects.requireNonNull(BeanUtil.copyProperties(option, CreditScoreItemOptionVO.class)))
.collect(Collectors.groupingBy(CreditScoreItemOptionVO::getItemId));
Map<Long, List<CreditScoreItemVO>> itemMap = items.stream().map(item -> {
CreditScoreItemVO itemVO = Objects.requireNonNull(BeanUtil.copyProperties(item, CreditScoreItemVO.class));
itemVO.setOptions(optionMap.getOrDefault(item.getId(), new ArrayList<>()));
return itemVO;
}).collect(Collectors.groupingBy(CreditScoreItemVO::getCategoryId));
return categories.stream().map(category -> {
CreditScoreCategoryVO categoryVO = Objects.requireNonNull(BeanUtil.copyProperties(category, CreditScoreCategoryVO.class));
categoryVO.setItems(itemMap.getOrDefault(category.getId(), new ArrayList<>()));
return categoryVO;
}).toList();
}
private List<CreditRatingStandardVO> loadStandards(Long quantificationId) {
return standardMapper.selectList(Wrappers.<CreditRatingStandard>lambdaQuery()
.eq(CreditRatingStandard::getQuantificationId, quantificationId)
.eq(CreditRatingStandard::getIsDeleted, 0)
.orderByDesc(CreditRatingStandard::getScoreRateLower)
.orderByAsc(CreditRatingStandard::getSort))
.stream()
.map(standard -> Objects.requireNonNull(BeanUtil.copyProperties(standard, CreditRatingStandardVO.class)))
.toList();
}
private CreditScoreQuantificationVO buildImportVO(String tableName, List<CreditScoreQuantificationExcel> rows) {
CreditScoreQuantificationVO quantification = new CreditScoreQuantificationVO();
CreditScoreQuantification existed = getOne(Wrappers.<CreditScoreQuantification>lambdaQuery()
.eq(CreditScoreQuantification::getName, tableName)
.eq(CreditScoreQuantification::getIsDeleted, 0), false);
if (Func.isNotEmpty(existed)) {
quantification.setId(existed.getId());
}
quantification.setName(tableName);
quantification.setStatus(STATUS_DRAFT);
quantification.setCategories(defaultCategories());
quantification.setStandards(new ArrayList<>());
Map<String, CreditScoreItemVO> itemMap = new HashMap<>();
for (CreditScoreQuantificationExcel row : rows) {
String rowType = trimToEmpty(row.getRowType());
if (Func.isEmpty(rowType) || ROW_TYPE_MAIN.equals(rowType)) {
quantification.setRemark(trimToNull(row.getRemark()));
quantification.setStandardDescription(trimToNull(row.getTableStandardDescription()));
quantification.setStatus(parseStatus(row.getStatusName()));
} else if (ROW_TYPE_ITEM.equals(rowType)) {
CreditScoreCategoryVO category = findCategory(quantification.getCategories(), row.getCategoryName());
CreditScoreItemVO item = new CreditScoreItemVO();
item.setItemName(trimToEmpty(row.getItemName()));
item.setScoreDescription(trimToNull(row.getScoreDescription()));
item.setOptionDescription(trimToNull(row.getOptionDescription()));
item.setOptions(new ArrayList<>());
category.getItems().add(item);
itemMap.put(itemKey(category.getCategoryName(), item.getItemName()), item);
} else if (ROW_TYPE_OPTION.equals(rowType)) {
CreditScoreCategoryVO category = findCategory(quantification.getCategories(), row.getCategoryName());
CreditScoreItemVO item = findOrCreateItem(category, row, itemMap);
CreditScoreItemOptionVO option = new CreditScoreItemOptionVO();
option.setOptionName(trimToEmpty(row.getOptionName()));
option.setScore(row.getScore());
item.getOptions().add(option);
} else if (ROW_TYPE_STANDARD.equals(rowType)) {
CreditRatingStandardVO standard = new CreditRatingStandardVO();
standard.setCreditLevel(trimToEmpty(row.getCreditLevel()));
standard.setScoreRateLower(row.getScoreRateLower());
standard.setScoreRateUpper(row.getScoreRateUpper());
standard.setScoreRateIncrease(row.getScoreRateIncrease());
standard.setCreditLimitLower(row.getCreditLimitLower());
standard.setCreditLimitUpper(row.getCreditLimitUpper());
standard.setCreditLimitIncrease(row.getCreditLimitIncrease());
standard.setStandardDescription(trimToNull(row.getRatingStandardDescription()));
quantification.getStandards().add(standard);
} else {
throw new ServiceException("数据类型仅支持主表、评分项目、选项、评估标准");
}
}
return quantification;
}
private CreditScoreCategoryVO findCategory(List<CreditScoreCategoryVO> categories, String categoryName) {
String trimCategoryName = trimToEmpty(categoryName);
for (CreditScoreCategoryVO category : categories) {
if (Objects.equals(category.getCategoryName(), trimCategoryName) || Objects.equals(category.getCategoryCode(), trimCategoryName)) {
return category;
}
}
throw new ServiceException("评分分类仅支持基础得分项、加分项目、减分项目");
}
private CreditScoreItemVO findOrCreateItem(CreditScoreCategoryVO category, CreditScoreQuantificationExcel row, Map<String, CreditScoreItemVO> itemMap) {
String itemName = trimToEmpty(row.getItemName());
String key = itemKey(category.getCategoryName(), itemName);
CreditScoreItemVO item = itemMap.get(key);
if (Func.isNotEmpty(item)) {
return item;
}
item = new CreditScoreItemVO();
item.setItemName(itemName);
item.setScoreDescription(trimToNull(row.getScoreDescription()));
item.setOptionDescription(trimToNull(row.getOptionDescription()));
item.setOptions(new ArrayList<>());
category.getItems().add(item);
itemMap.put(key, item);
return item;
}
private String itemKey(String categoryName, String itemName) {
return trimToEmpty(categoryName) + "#" + trimToEmpty(itemName);
}
private Integer parseStatus(String statusName) {
String trimStatusName = trimToNull(statusName);
if (Func.isEmpty(trimStatusName) || "草稿".equals(trimStatusName)) {
return STATUS_DRAFT;
}
if ("正常".equals(trimStatusName) || "发布".equals(trimStatusName)) {
return STATUS_NORMAL;
}
if ("停用".equals(trimStatusName)) {
return STATUS_DISABLED;
}
throw new ServiceException("状态仅支持正常、停用、草稿");
}
private CreditScoreQuantificationExcel buildMainExcel(CreditScoreQuantificationVO detail) {
CreditScoreQuantificationExcel excel = new CreditScoreQuantificationExcel();
excel.setTableName(detail.getName());
excel.setRowType(ROW_TYPE_MAIN);
excel.setRemark(detail.getRemark());
excel.setTableStandardDescription(detail.getStandardDescription());
excel.setStatusName(statusName(detail.getStatus()));
return excel;
}
private CreditScoreQuantificationExcel buildItemExcel(CreditScoreQuantificationVO detail, CreditScoreCategoryVO category, CreditScoreItemVO item) {
CreditScoreQuantificationExcel excel = new CreditScoreQuantificationExcel();
excel.setTableName(detail.getName());
excel.setRowType(ROW_TYPE_ITEM);
excel.setCategoryName(category.getCategoryName());
excel.setItemName(item.getItemName());
excel.setScoreDescription(item.getScoreDescription());
excel.setOptionDescription(item.getOptionDescription());
return excel;
}
private CreditScoreQuantificationExcel buildOptionExcel(CreditScoreQuantificationVO detail, CreditScoreCategoryVO category, CreditScoreItemVO item, CreditScoreItemOptionVO option) {
CreditScoreQuantificationExcel excel = buildItemExcel(detail, category, item);
excel.setRowType(ROW_TYPE_OPTION);
excel.setOptionName(option.getOptionName());
excel.setScore(option.getScore());
return excel;
}
private CreditScoreQuantificationExcel buildStandardExcel(CreditScoreQuantificationVO detail, CreditRatingStandardVO standard) {
CreditScoreQuantificationExcel excel = new CreditScoreQuantificationExcel();
excel.setTableName(detail.getName());
excel.setRowType(ROW_TYPE_STANDARD);
excel.setCreditLevel(standard.getCreditLevel());
excel.setScoreRateLower(standard.getScoreRateLower());
excel.setScoreRateUpper(standard.getScoreRateUpper());
excel.setScoreRateIncrease(standard.getScoreRateIncrease());
excel.setCreditLimitLower(standard.getCreditLimitLower());
excel.setCreditLimitUpper(standard.getCreditLimitUpper());
excel.setCreditLimitIncrease(standard.getCreditLimitIncrease());
excel.setRatingStandardDescription(standard.getStandardDescription());
return excel;
}
private String statusName(Integer status) {
if (Objects.equals(status, STATUS_NORMAL)) {
return "正常";
}
if (Objects.equals(status, STATUS_DISABLED)) {
return "停用";
}
return "草稿";
}
private void prepare(CreditScoreQuantificationVO quantification) {
quantification.setName(trimToEmpty(quantification.getName()));
quantification.setRemark(trimToNull(quantification.getRemark()));
quantification.setStandardDescription(trimToNull(quantification.getStandardDescription()));
if (Func.isEmpty(quantification.getStatus())) {
quantification.setStatus(STATUS_DRAFT);
}
quantification.setCategories(normalizeCategories(quantification.getCategories()));
quantification.setStandards(quantification.getStandards() == null ? new ArrayList<>() : quantification.getStandards());
}
private void validateBase(CreditScoreQuantificationVO quantification) {
if (Func.isEmpty(quantification.getName())) {
throw new ServiceException("评定表名称不能为空");
}
validateLength(quantification.getName(), NAME_MAX_LENGTH, "评定表名称最多30字符");
validateLength(quantification.getRemark(), REMARK_MAX_LENGTH, "备注最多500字符");
validateLength(quantification.getStandardDescription(), REMARK_MAX_LENGTH, "标准说明最多500字符");
LambdaQueryWrapper<CreditScoreQuantification> queryWrapper = Wrappers.<CreditScoreQuantification>lambdaQuery()
.eq(CreditScoreQuantification::getName, quantification.getName())
.eq(CreditScoreQuantification::getIsDeleted, 0);
if (Func.isNotEmpty(quantification.getId())) {
queryWrapper.ne(CreditScoreQuantification::getId, quantification.getId());
}
if (count(queryWrapper) > 0L) {
throw new ServiceException("评定表名称已存在");
}
}
private void validateDetail(CreditScoreQuantificationVO quantification, boolean fullValidate) {
Map<String, List<CreditScoreItemVO>> itemMap = new HashMap<>();
for (CreditScoreCategoryVO category : quantification.getCategories()) {
List<CreditScoreItemVO> items = category.getItems() == null ? new ArrayList<>() : category.getItems();
validateItems(category, items, fullValidate);
itemMap.put(category.getCategoryCode(), items);
}
if (fullValidate && Func.isEmpty(itemMap.get(CATEGORY_BASIC))) {
throw new ServiceException("发布前至少配置1个基础得分项目");
}
validateStandards(quantification.getStandards(), fullValidate);
}
private void validateItems(CreditScoreCategoryVO category, List<CreditScoreItemVO> items, boolean fullValidate) {
Set<String> itemNames = new HashSet<>();
for (CreditScoreItemVO item : items) {
item.setItemName(trimToEmpty(item.getItemName()));
item.setScoreDescription(trimToNull(item.getScoreDescription()));
item.setOptionDescription(trimToNull(item.getOptionDescription()));
if (Func.isEmpty(item.getItemName())) {
throw new ServiceException(category.getCategoryName() + "评分项目不能为空");
}
validateLength(item.getItemName(), ITEM_NAME_MAX_LENGTH, "评分项目最多20汉字");
validateLength(item.getScoreDescription(), SCORE_DESCRIPTION_MAX_LENGTH, "得分说明最多300字符");
validateLength(item.getOptionDescription(), OPTION_NAME_MAX_LENGTH, "选项描述最多100字符");
if (!itemNames.add(item.getItemName())) {
throw new ServiceException(category.getCategoryName() + "下评分项目名称不能重复");
}
List<CreditScoreItemOptionVO> options = item.getOptions() == null ? new ArrayList<>() : item.getOptions();
if (fullValidate && Func.isEmpty(options)) {
throw new ServiceException(item.getItemName() + "至少存在1条档位选项");
}
for (CreditScoreItemOptionVO option : options) {
option.setOptionName(trimToEmpty(option.getOptionName()));
if (Func.isEmpty(option.getOptionName())) {
throw new ServiceException(item.getItemName() + "选项描述不能为空");
}
validateLength(option.getOptionName(), OPTION_NAME_MAX_LENGTH, "选项描述最多100字符");
if (Func.isEmpty(option.getScore())) {
throw new ServiceException(item.getItemName() + "分值不能为空");
}
if (option.getScore().compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException(item.getItemName() + "分值不能小于0");
}
}
}
}
private void validateStandards(List<CreditRatingStandardVO> standards, boolean fullValidate) {
if (!fullValidate && Func.isEmpty(standards)) {
return;
}
if (Func.isEmpty(standards)) {
throw new ServiceException("发布前至少配置1条完整信用等级评估标准");
}
Set<String> creditLevels = new HashSet<>();
List<CreditRatingStandardVO> sortedStandards = standards.stream()
.sorted(Comparator.comparing(CreditRatingStandardVO::getScoreRateLower))
.toList();
int expectedLower = 0;
for (CreditRatingStandardVO standard : sortedStandards) {
prepareStandard(standard);
if (!creditLevels.add(standard.getCreditLevel())) {
throw new ServiceException("信用等级不能重复");
}
if (standard.getScoreRateLower() < 0 || standard.getScoreRateUpper() > 100) {
throw new ServiceException("得分率区间必须在0到100之间");
}
if (standard.getScoreRateLower() >= standard.getScoreRateUpper()) {
throw new ServiceException("得分率下限必须小于上限");
}
if (standard.getScoreRateLower() != expectedLower) {
throw new ServiceException("信用等级得分率区间必须连续无断层");
}
expectedLower = standard.getScoreRateUpper();
validateNonNegative(standard.getCreditLimitLower(), "最大资金使用额度下限不能小于0");
validateNonNegative(standard.getCreditLimitUpper(), "最大资金使用额度上限不能小于0");
validateNonNegative(standard.getCreditLimitIncrease(), "额度增加不能小于0");
if (standard.getCreditLimitUpper().compareTo(standard.getCreditLimitLower()) < 0) {
throw new ServiceException("最大资金使用额度上限不能小于下限");
}
validateLength(standard.getStandardDescription(), STANDARD_DESCRIPTION_MAX_LENGTH, "标准说明最多500字符");
}
if (expectedLower != 100) {
throw new ServiceException("信用等级得分率区间必须覆盖0到100");
}
}
private void prepareStandard(CreditRatingStandardVO standard) {
standard.setCreditLevel(trimToEmpty(standard.getCreditLevel()));
standard.setStandardDescription(trimToNull(standard.getStandardDescription()));
if (Func.isEmpty(standard.getCreditLevel())) {
throw new ServiceException("信用等级不能为空");
}
validateLength(standard.getCreditLevel(), NAME_MAX_LENGTH, "信用等级最多30字符");
if (Func.isEmpty(standard.getScoreRateLower()) || Func.isEmpty(standard.getScoreRateUpper())) {
throw new ServiceException("得分率上下限不能为空");
}
if (Func.isEmpty(standard.getScoreRateIncrease()) || standard.getScoreRateIncrease() < 0) {
throw new ServiceException("得分率每增加必须为大于等于0的整数");
}
if (Func.isEmpty(standard.getCreditLimitLower())) {
standard.setCreditLimitLower(BigDecimal.ZERO);
}
if (Func.isEmpty(standard.getCreditLimitUpper())) {
standard.setCreditLimitUpper(BigDecimal.ZERO);
}
if (Func.isEmpty(standard.getCreditLimitIncrease())) {
standard.setCreditLimitIncrease(BigDecimal.ZERO);
}
}
private void replaceDetail(Long quantificationId, CreditScoreQuantificationVO quantification) {
deleteDetail(List.of(quantificationId));
Map<String, Long> categoryIdMap = new HashMap<>();
for (CreditScoreCategoryVO categoryVO : quantification.getCategories()) {
Long categoryId = IdWorker.getId();
categoryIdMap.put(categoryVO.getCategoryCode(), categoryId);
CreditScoreCategory category = Objects.requireNonNull(BeanUtil.copyProperties(categoryVO, CreditScoreCategory.class));
category.setId(categoryId);
category.setQuantificationId(quantificationId);
category.setStatus(STATUS_NORMAL);
categoryMapper.insert(category);
}
for (CreditScoreCategoryVO categoryVO : quantification.getCategories()) {
List<CreditScoreItemVO> items = categoryVO.getItems() == null ? new ArrayList<>() : categoryVO.getItems();
for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) {
CreditScoreItemVO itemVO = items.get(itemIndex);
Long itemId = IdWorker.getId();
CreditScoreItem item = Objects.requireNonNull(BeanUtil.copyProperties(itemVO, CreditScoreItem.class));
item.setId(itemId);
item.setQuantificationId(quantificationId);
item.setCategoryId(categoryIdMap.get(categoryVO.getCategoryCode()));
item.setCategoryCode(categoryVO.getCategoryCode());
item.setSort(itemIndex + 1);
item.setStatus(STATUS_NORMAL);
itemMapper.insert(item);
insertOptions(quantificationId, itemId, itemVO);
}
}
insertStandards(quantificationId, quantification.getStandards());
}
private void insertOptions(Long quantificationId, Long itemId, CreditScoreItemVO itemVO) {
List<CreditScoreItemOptionVO> options = itemVO.getOptions() == null ? new ArrayList<>() : itemVO.getOptions();
for (int optionIndex = 0; optionIndex < options.size(); optionIndex++) {
CreditScoreItemOption option = Objects.requireNonNull(BeanUtil.copyProperties(options.get(optionIndex), CreditScoreItemOption.class));
option.setId(IdWorker.getId());
option.setQuantificationId(quantificationId);
option.setItemId(itemId);
option.setSort(optionIndex + 1);
option.setStatus(STATUS_NORMAL);
optionMapper.insert(option);
}
}
private void insertStandards(Long quantificationId, List<CreditRatingStandardVO> standards) {
if (Func.isEmpty(standards)) {
return;
}
List<CreditRatingStandardVO> sortedStandards = standards.stream()
.sorted(Comparator.comparing(CreditRatingStandardVO::getScoreRateLower).reversed())
.toList();
for (int index = 0; index < sortedStandards.size(); index++) {
CreditRatingStandard standard = Objects.requireNonNull(BeanUtil.copyProperties(sortedStandards.get(index), CreditRatingStandard.class));
standard.setId(IdWorker.getId());
standard.setQuantificationId(quantificationId);
standard.setSort(index + 1);
standard.setStatus(STATUS_NORMAL);
standardMapper.insert(standard);
}
}
private void deleteDetail(List<Long> quantificationIds) {
if (Func.isEmpty(quantificationIds)) {
return;
}
categoryMapper.update(null, Wrappers.<CreditScoreCategory>lambdaUpdate()
.set(CreditScoreCategory::getIsDeleted, 1)
.in(CreditScoreCategory::getQuantificationId, quantificationIds));
itemMapper.update(null, Wrappers.<CreditScoreItem>lambdaUpdate()
.set(CreditScoreItem::getIsDeleted, 1)
.in(CreditScoreItem::getQuantificationId, quantificationIds));
optionMapper.update(null, Wrappers.<CreditScoreItemOption>lambdaUpdate()
.set(CreditScoreItemOption::getIsDeleted, 1)
.in(CreditScoreItemOption::getQuantificationId, quantificationIds));
standardMapper.update(null, Wrappers.<CreditRatingStandard>lambdaUpdate()
.set(CreditRatingStandard::getIsDeleted, 1)
.in(CreditRatingStandard::getQuantificationId, quantificationIds));
}
private List<CreditScoreCategoryVO> normalizeCategories(List<CreditScoreCategoryVO> categories) {
Map<String, CreditScoreCategoryVO> categoryMap = categories == null ? new HashMap<>() : categories.stream()
.filter(category -> Func.isNotEmpty(category.getCategoryCode()))
.collect(Collectors.toMap(CreditScoreCategoryVO::getCategoryCode, category -> category, (first, second) -> first));
List<CreditScoreCategoryVO> normalized = new ArrayList<>();
normalized.add(normalizeCategory(categoryMap.get(CATEGORY_BASIC), CATEGORY_BASIC, "基础得分项", 1));
normalized.add(normalizeCategory(categoryMap.get(CATEGORY_PLUS), CATEGORY_PLUS, "加分项目", 2));
normalized.add(normalizeCategory(categoryMap.get(CATEGORY_MINUS), CATEGORY_MINUS, "减分项目", 3));
return normalized;
}
private CreditScoreCategoryVO normalizeCategory(CreditScoreCategoryVO category, String code, String name, Integer sort) {
CreditScoreCategoryVO normalized = category == null ? new CreditScoreCategoryVO() : category;
normalized.setCategoryCode(code);
normalized.setCategoryName(name);
normalized.setSort(sort);
if (normalized.getItems() == null) {
normalized.setItems(new ArrayList<>());
}
return normalized;
}
private List<CreditScoreCategoryVO> defaultCategories() {
return normalizeCategories(new ArrayList<>());
}
private void validateLength(String value, int maxLength, String message) {
if (Func.isNotEmpty(value) && value.length() > maxLength) {
throw new ServiceException(message);
}
}
private void validateNonNegative(BigDecimal value, String message) {
if (Func.isNotEmpty(value) && value.compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException(message);
}
}
private String trimToEmpty(String value) {
return value == null ? "" : value.trim();
}
private String trimToNull(String value) {
String trimValue = trimToEmpty(value);
return trimValue.isEmpty() ? null : trimValue;
}
}

View File

@@ -0,0 +1,48 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.wrapper;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.transport.pojo.entity.CreditScoreQuantification;
import org.springblade.transport.pojo.vo.CreditScoreQuantificationVO;
import java.util.Objects;
/**
* 评分量化表包装类
*
* @author Chill
*/
public class CreditScoreQuantificationWrapper extends BaseEntityWrapper<CreditScoreQuantification, CreditScoreQuantificationVO> {
public static CreditScoreQuantificationWrapper build() {
return new CreditScoreQuantificationWrapper();
}
@Override
public CreditScoreQuantificationVO entityVO(CreditScoreQuantification quantification) {
return Objects.requireNonNull(BeanUtil.copyProperties(quantification, CreditScoreQuantificationVO.class));
}
}