新增流程列表编辑功能
This commit is contained in:
@@ -69,6 +69,46 @@ public class LoanPricingWorkflowController extends BaseController
|
||||
return success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询利率定价流程编辑数据
|
||||
*/
|
||||
@Operation(summary = "查询利率定价流程编辑数据")
|
||||
@GetMapping("/{serialNum}/edit")
|
||||
public AjaxResult getEditInfo(
|
||||
@Parameter(description = "业务方流水号")
|
||||
@PathVariable("serialNum") String serialNum)
|
||||
{
|
||||
return success(loanPricingWorkflowService.selectEditableLoanPricingBySerialNum(serialNum));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑个人客户利率定价流程
|
||||
*/
|
||||
@Operation(summary = "编辑个人客户利率定价流程")
|
||||
@Log(title = "个人客户利率定价流程", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{serialNum}/personal")
|
||||
public AjaxResult updatePersonal(
|
||||
@Parameter(description = "业务方流水号")
|
||||
@PathVariable("serialNum") String serialNum,
|
||||
@Validated @RequestBody PersonalLoanPricingCreateDTO dto)
|
||||
{
|
||||
return success(loanPricingWorkflowService.updatePersonalLoanPricing(serialNum, dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑企业客户利率定价流程
|
||||
*/
|
||||
@Operation(summary = "编辑企业客户利率定价流程")
|
||||
@Log(title = "企业客户利率定价流程", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{serialNum}/corporate")
|
||||
public AjaxResult updateCorporate(
|
||||
@Parameter(description = "业务方流水号")
|
||||
@PathVariable("serialNum") String serialNum,
|
||||
@Validated @RequestBody CorporateLoanPricingCreateDTO dto)
|
||||
{
|
||||
return success(loanPricingWorkflowService.updateCorporateLoanPricing(serialNum, dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人客户号映射
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,32 @@ public interface ILoanPricingWorkflowService
|
||||
*/
|
||||
public LoanPricingWorkflow createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 查询利率定价流程编辑数据
|
||||
*
|
||||
* @param serialNum 业务方流水号
|
||||
* @return 编辑用流程数据
|
||||
*/
|
||||
public LoanPricingWorkflow selectEditableLoanPricingBySerialNum(String serialNum);
|
||||
|
||||
/**
|
||||
* 编辑个人客户利率定价流程
|
||||
*
|
||||
* @param serialNum 业务方流水号
|
||||
* @param dto 个人客户编辑DTO
|
||||
* @return 更新后的流程数据
|
||||
*/
|
||||
public LoanPricingWorkflow updatePersonalLoanPricing(String serialNum, PersonalLoanPricingCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 编辑企业客户利率定价流程
|
||||
*
|
||||
* @param serialNum 业务方流水号
|
||||
* @param dto 企业客户编辑DTO
|
||||
* @return 更新后的流程数据
|
||||
*/
|
||||
public LoanPricingWorkflow updateCorporateLoanPricing(String serialNum, CorporateLoanPricingCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 查询利率定价流程列表
|
||||
*
|
||||
|
||||
@@ -40,6 +40,14 @@ public class LoanPricingModelService {
|
||||
private SensitiveFieldCryptoService sensitiveFieldCryptoService;
|
||||
|
||||
public void invokeModelAsync(Long workflowId) {
|
||||
invokeModelAndSave(workflowId, false);
|
||||
}
|
||||
|
||||
public void reinvokeModelAndOverwrite(Long workflowId) {
|
||||
invokeModelAndSave(workflowId, true);
|
||||
}
|
||||
|
||||
private void invokeModelAndSave(Long workflowId, boolean overwriteModelOutput) {
|
||||
LoanPricingWorkflow loanPricingWorkflow = loanPricingWorkflowMapper.selectById(workflowId);
|
||||
if (Objects.isNull(loanPricingWorkflow)){
|
||||
log.error("未找到对应的流程信息,未调用模型服务");
|
||||
@@ -68,26 +76,43 @@ public class LoanPricingModelService {
|
||||
if (loanPricingWorkflow.getCustType().equals("个人")){
|
||||
// 个人模型
|
||||
ModelRetailOutputFields modelRetailOutputFields = modelService.invokePersonalModel(modelInvokeDTO);
|
||||
modelRetailOutputFieldsMapper.insert(modelRetailOutputFields);
|
||||
if (overwriteModelOutput && Objects.nonNull(loanPricingWorkflow.getModelOutputId()))
|
||||
{
|
||||
modelRetailOutputFields.setId(loanPricingWorkflow.getModelOutputId());
|
||||
modelRetailOutputFieldsMapper.updateById(modelRetailOutputFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
modelRetailOutputFieldsMapper.insert(modelRetailOutputFields);
|
||||
}
|
||||
log.info("个人模型调用成功");
|
||||
LoanPricingWorkflow workflowToUpdate = new LoanPricingWorkflow();
|
||||
workflowToUpdate.setId(loanPricingWorkflow.getId());
|
||||
workflowToUpdate.setModelOutputId(modelRetailOutputFields.getId());
|
||||
loanPricingWorkflowMapper.updateById(workflowToUpdate);
|
||||
log.info("更新流程信息成功");
|
||||
updateWorkflowModelOutputId(loanPricingWorkflow, modelRetailOutputFields.getId());
|
||||
}else if (loanPricingWorkflow.getCustType().equals("企业")){
|
||||
// 企业模型
|
||||
ModelCorpOutputFields modelCorpOutputFields = modelService.invokeCorporateModel(modelInvokeDTO);
|
||||
modelCorpOutputFieldsMapper.insert(modelCorpOutputFields);
|
||||
if (overwriteModelOutput && Objects.nonNull(loanPricingWorkflow.getModelOutputId()))
|
||||
{
|
||||
modelCorpOutputFields.setId(loanPricingWorkflow.getModelOutputId());
|
||||
modelCorpOutputFieldsMapper.updateById(modelCorpOutputFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
modelCorpOutputFieldsMapper.insert(modelCorpOutputFields);
|
||||
}
|
||||
log.info("企业模型调用成功");
|
||||
LoanPricingWorkflow workflowToUpdate = new LoanPricingWorkflow();
|
||||
workflowToUpdate.setId(loanPricingWorkflow.getId());
|
||||
workflowToUpdate.setModelOutputId(modelCorpOutputFields.getId());
|
||||
loanPricingWorkflowMapper.updateById(workflowToUpdate);
|
||||
log.info("更新流程信息成功");
|
||||
updateWorkflowModelOutputId(loanPricingWorkflow, modelCorpOutputFields.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWorkflowModelOutputId(LoanPricingWorkflow loanPricingWorkflow, Long modelOutputId)
|
||||
{
|
||||
LoanPricingWorkflow workflowToUpdate = new LoanPricingWorkflow();
|
||||
workflowToUpdate.setId(loanPricingWorkflow.getId());
|
||||
workflowToUpdate.setModelOutputId(modelOutputId);
|
||||
loanPricingWorkflowMapper.updateById(workflowToUpdate);
|
||||
log.info("更新流程信息成功");
|
||||
}
|
||||
|
||||
private void normalizePersonalModelInvokeDTO(ModelInvokeDTO modelInvokeDTO)
|
||||
{
|
||||
modelInvokeDTO.setBizProof(toZeroOne(modelInvokeDTO.getBizProof()));
|
||||
@@ -98,6 +123,7 @@ public class LoanPricingModelService {
|
||||
private void normalizeCorporateModelInvokeDTO(ModelInvokeDTO modelInvokeDTO)
|
||||
{
|
||||
modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty()));
|
||||
modelInvokeDTO.setResCover(toZeroOne(modelInvokeDTO.getResCover()));
|
||||
modelInvokeDTO.setIsGreenLoan(toZeroOne(modelInvokeDTO.getIsGreenLoan()));
|
||||
modelInvokeDTO.setIsTradeBuildEnt(toZeroOne(modelInvokeDTO.getIsTradeBuildEnt()));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.loanpricing.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
@@ -47,6 +48,10 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
||||
|
||||
private static final String WORKFLOW_ADMIN_ROLE_KEY = "headAdmin";
|
||||
|
||||
private static final String WORKFLOW_BRANCH_ADMIN_ROLE_NAME = "支行管理员";
|
||||
|
||||
private static final String WORKFLOW_BRANCH_ADMIN_ROLE_KEY = "branchAdmin";
|
||||
|
||||
@Resource
|
||||
private LoanPricingWorkflowMapper loanPricingWorkflowMapper;
|
||||
|
||||
@@ -93,6 +98,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
||||
loanPricingWorkflow.setRunType("1");
|
||||
}
|
||||
|
||||
loanPricingWorkflow.setDeptId(SecurityUtils.getDeptId());
|
||||
loanPricingWorkflow.setCustName(sensitiveFieldCryptoService.encrypt(loanPricingWorkflow.getCustName()));
|
||||
loanPricingWorkflow.setIdNum(sensitiveFieldCryptoService.encrypt(loanPricingWorkflow.getIdNum()));
|
||||
loanPricingWorkflowMapper.insert(loanPricingWorkflow);
|
||||
@@ -193,6 +199,97 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
||||
return createLoanPricing(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanPricingWorkflow selectEditableLoanPricingBySerialNum(String serialNum)
|
||||
{
|
||||
LoanPricingWorkflow workflow = selectWorkflowBySerialNum(serialNum);
|
||||
assertCurrentUserIsCreator(workflow);
|
||||
workflow.setCustName(sensitiveFieldCryptoService.decrypt(workflow.getCustName()));
|
||||
workflow.setIdNum(sensitiveFieldCryptoService.decrypt(workflow.getIdNum()));
|
||||
return workflow;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public LoanPricingWorkflow updatePersonalLoanPricing(String serialNum, PersonalLoanPricingCreateDTO dto)
|
||||
{
|
||||
LoanPricingWorkflow editingWorkflow = LoanPricingConverter.toEntity(dto);
|
||||
return updateLoanPricing(serialNum, editingWorkflow, "个人");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public LoanPricingWorkflow updateCorporateLoanPricing(String serialNum, CorporateLoanPricingCreateDTO dto)
|
||||
{
|
||||
LoanPricingWorkflow editingWorkflow = LoanPricingConverter.toEntity(dto);
|
||||
return updateLoanPricing(serialNum, editingWorkflow, "企业");
|
||||
}
|
||||
|
||||
private LoanPricingWorkflow updateLoanPricing(String serialNum, LoanPricingWorkflow editingWorkflow, String expectedCustType)
|
||||
{
|
||||
LoanPricingWorkflow existingWorkflow = selectWorkflowBySerialNum(serialNum);
|
||||
assertCurrentUserIsCreator(existingWorkflow);
|
||||
if (!expectedCustType.equals(existingWorkflow.getCustType()))
|
||||
{
|
||||
throw new ServiceException("客户类型不匹配,不能编辑该流程");
|
||||
}
|
||||
|
||||
editingWorkflow.setId(existingWorkflow.getId());
|
||||
editingWorkflow.setSerialNum(existingWorkflow.getSerialNum());
|
||||
editingWorkflow.setCustType(existingWorkflow.getCustType());
|
||||
editingWorkflow.setModelOutputId(existingWorkflow.getModelOutputId());
|
||||
validateBusinessTypeAndHistoryRate(editingWorkflow);
|
||||
validateCollateralTypeAndCouponRate(editingWorkflow);
|
||||
|
||||
String encryptedCustName = sensitiveFieldCryptoService.encrypt(editingWorkflow.getCustName());
|
||||
String encryptedIdNum = sensitiveFieldCryptoService.encrypt(editingWorkflow.getIdNum());
|
||||
LambdaUpdateWrapper<LoanPricingWorkflow> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(LoanPricingWorkflow::getId, existingWorkflow.getId())
|
||||
.set(LoanPricingWorkflow::getCustIsn, editingWorkflow.getCustIsn())
|
||||
.set(LoanPricingWorkflow::getCustName, encryptedCustName)
|
||||
.set(LoanPricingWorkflow::getIdType, editingWorkflow.getIdType())
|
||||
.set(LoanPricingWorkflow::getIdNum, encryptedIdNum)
|
||||
.set(LoanPricingWorkflow::getGuarType, editingWorkflow.getGuarType())
|
||||
.set(LoanPricingWorkflow::getApplyAmt, editingWorkflow.getApplyAmt())
|
||||
.set(LoanPricingWorkflow::getBusinessType, editingWorkflow.getBusinessType())
|
||||
.set(LoanPricingWorkflow::getLoanRateHistory, editingWorkflow.getLoanRateHistory())
|
||||
.set(LoanPricingWorkflow::getCouponRate, editingWorkflow.getCouponRate())
|
||||
.set(LoanPricingWorkflow::getLoanTerm, editingWorkflow.getLoanTerm())
|
||||
.set(LoanPricingWorkflow::getCollType, editingWorkflow.getCollType())
|
||||
.set(LoanPricingWorkflow::getCollThirdParty, editingWorkflow.getCollThirdParty())
|
||||
.set(LoanPricingWorkflow::getLoanLoop, editingWorkflow.getLoanLoop())
|
||||
.set(LoanPricingWorkflow::getResCover, editingWorkflow.getResCover())
|
||||
.set(LoanPricingWorkflow::getRepayMethod, editingWorkflow.getRepayMethod())
|
||||
.set(LoanPricingWorkflow::getIsGreenLoan, editingWorkflow.getIsGreenLoan())
|
||||
.set(LoanPricingWorkflow::getIsTradeBuildEnt, editingWorkflow.getIsTradeBuildEnt())
|
||||
.set(LoanPricingWorkflow::getUpdateBy, buildCurrentCreateBy(SecurityUtils.getLoginUser()))
|
||||
.set(LoanPricingWorkflow::getUpdateTime, new Date());
|
||||
loanPricingWorkflowMapper.update(null, updateWrapper);
|
||||
loanPricingModelService.reinvokeModelAndOverwrite(existingWorkflow.getId());
|
||||
return selectEditableLoanPricingBySerialNum(serialNum);
|
||||
}
|
||||
|
||||
private LoanPricingWorkflow selectWorkflowBySerialNum(String serialNum)
|
||||
{
|
||||
LambdaQueryWrapper<LoanPricingWorkflow> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(LoanPricingWorkflow::getSerialNum, serialNum);
|
||||
LoanPricingWorkflow workflow = loanPricingWorkflowMapper.selectOne(wrapper);
|
||||
if (workflow == null)
|
||||
{
|
||||
throw new ServiceException("记录不存在");
|
||||
}
|
||||
return workflow;
|
||||
}
|
||||
|
||||
private void assertCurrentUserIsCreator(LoanPricingWorkflow workflow)
|
||||
{
|
||||
String currentCreateBy = buildCurrentCreateBy(SecurityUtils.getLoginUser());
|
||||
if (!currentCreateBy.equals(workflow.getCreateBy()))
|
||||
{
|
||||
throw new ServiceException("只有创建者可以编辑该流程");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询利率定价流程列表
|
||||
*
|
||||
@@ -306,7 +403,15 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
||||
{
|
||||
LoanPricingWorkflow scopedQuery = query == null ? new LoanPricingWorkflow() : query;
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (!canViewAllWorkflows(loginUser))
|
||||
if (canViewAllWorkflows(loginUser))
|
||||
{
|
||||
return scopedQuery;
|
||||
}
|
||||
if (canViewBranchWorkflows(loginUser))
|
||||
{
|
||||
scopedQuery.setDataScopeDeptId(loginUser.getDeptId() == null ? -1L : loginUser.getDeptId());
|
||||
}
|
||||
else
|
||||
{
|
||||
scopedQuery.setDataScopeCreateBy(buildCurrentCreateBy(loginUser));
|
||||
}
|
||||
@@ -331,6 +436,19 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
|
||||
|| WORKFLOW_ADMIN_ROLE_KEY.equals(role.getRoleKey())));
|
||||
}
|
||||
|
||||
private boolean canViewBranchWorkflows(LoginUser loginUser)
|
||||
{
|
||||
List<SysRole> roles = loginUser.getUser().getRoles();
|
||||
if (roles == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return roles.stream().anyMatch(role -> role != null
|
||||
&& UserConstants.ROLE_NORMAL.equals(role.getStatus())
|
||||
&& (WORKFLOW_BRANCH_ADMIN_ROLE_NAME.equals(role.getRoleName())
|
||||
|| WORKFLOW_BRANCH_ADMIN_ROLE_KEY.equals(role.getRoleKey())));
|
||||
}
|
||||
|
||||
private String buildCurrentCreateBy(LoginUser loginUser)
|
||||
{
|
||||
SysUser user = loginUser.getUser();
|
||||
|
||||
@@ -57,6 +57,7 @@ class LoanPricingModelServiceTest
|
||||
workflow.setCustName("cipher-name");
|
||||
workflow.setIdNum("cipher-id");
|
||||
workflow.setRepayMethod("分期");
|
||||
workflow.setResCover("true");
|
||||
workflow.setIsGreenLoan("true");
|
||||
workflow.setIsTradeBuildEnt("false");
|
||||
workflow.setCollThirdParty("true");
|
||||
@@ -67,6 +68,7 @@ class LoanPricingModelServiceTest
|
||||
|
||||
ModelInvokeDTO request = context.modelService.corporateRequest;
|
||||
assertEquals("分期", request.getRepayMethod());
|
||||
assertEquals("1", request.getResCover());
|
||||
assertEquals("1", request.getIsGreenLoan());
|
||||
assertEquals("0", request.getIsTradeBuildEnt());
|
||||
assertEquals("1", request.getCollThirdParty());
|
||||
@@ -77,6 +79,24 @@ class LoanPricingModelServiceTest
|
||||
assertEquals(1, context.corpInsertCount.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldOverwriteExistingCorporateModelOutputWhenReinvokingModel() throws Exception
|
||||
{
|
||||
LoanPricingWorkflow workflow = new LoanPricingWorkflow();
|
||||
workflow.setId(4L);
|
||||
workflow.setModelOutputId(88L);
|
||||
workflow.setCustType("企业");
|
||||
workflow.setCustName("cipher-name");
|
||||
workflow.setIdNum("cipher-id");
|
||||
TestContext context = createContext(workflow);
|
||||
|
||||
context.service.reinvokeModelAndOverwrite(4L);
|
||||
|
||||
assertEquals(1, context.modelService.corporateCalls.get());
|
||||
assertEquals(0, context.corpInsertCount.get());
|
||||
assertEquals(1, context.corpUpdateCount.get());
|
||||
}
|
||||
|
||||
private static LoanPricingWorkflow personalWorkflow(Long id)
|
||||
{
|
||||
LoanPricingWorkflow workflow = new LoanPricingWorkflow();
|
||||
@@ -96,15 +116,17 @@ class LoanPricingModelServiceTest
|
||||
context.workflow = workflow;
|
||||
context.updatedWorkflow = new AtomicReference<>();
|
||||
context.retailInsertCount = new AtomicInteger();
|
||||
context.retailUpdateCount = new AtomicInteger();
|
||||
context.corpInsertCount = new AtomicInteger();
|
||||
context.corpUpdateCount = new AtomicInteger();
|
||||
|
||||
setField(context.service, "modelService", context.modelService);
|
||||
setField(context.service, "loanPricingWorkflowMapper",
|
||||
workflowMapper(context.workflow, context.updatedWorkflow));
|
||||
setField(context.service, "modelRetailOutputFieldsMapper",
|
||||
insertCountingMapper(ModelRetailOutputFieldsMapper.class, context.retailInsertCount));
|
||||
savingMapper(ModelRetailOutputFieldsMapper.class, context.retailInsertCount, context.retailUpdateCount));
|
||||
setField(context.service, "modelCorpOutputFieldsMapper",
|
||||
insertCountingMapper(ModelCorpOutputFieldsMapper.class, context.corpInsertCount));
|
||||
savingMapper(ModelCorpOutputFieldsMapper.class, context.corpInsertCount, context.corpUpdateCount));
|
||||
setField(context.service, "sensitiveFieldCryptoService", new TestSensitiveFieldCryptoService());
|
||||
return context;
|
||||
}
|
||||
@@ -126,7 +148,7 @@ class LoanPricingModelServiceTest
|
||||
});
|
||||
}
|
||||
|
||||
private static <T> T insertCountingMapper(Class<T> mapperClass, AtomicInteger insertCount)
|
||||
private static <T> T savingMapper(Class<T> mapperClass, AtomicInteger insertCount, AtomicInteger updateCount)
|
||||
{
|
||||
return proxy(mapperClass, (proxy, method, args) -> {
|
||||
if ("insert".equals(method.getName()))
|
||||
@@ -134,6 +156,11 @@ class LoanPricingModelServiceTest
|
||||
insertCount.incrementAndGet();
|
||||
return 1;
|
||||
}
|
||||
if ("updateById".equals(method.getName()))
|
||||
{
|
||||
updateCount.incrementAndGet();
|
||||
return 1;
|
||||
}
|
||||
return defaultValue(method);
|
||||
});
|
||||
}
|
||||
@@ -172,7 +199,9 @@ class LoanPricingModelServiceTest
|
||||
private LoanPricingWorkflow workflow;
|
||||
private AtomicReference<LoanPricingWorkflow> updatedWorkflow;
|
||||
private AtomicInteger retailInsertCount;
|
||||
private AtomicInteger retailUpdateCount;
|
||||
private AtomicInteger corpInsertCount;
|
||||
private AtomicInteger corpUpdateCount;
|
||||
}
|
||||
|
||||
private static class CapturingModelService extends ModelService
|
||||
|
||||
@@ -11,6 +11,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -100,6 +101,7 @@ class LoanPricingWorkflowServiceImplTest
|
||||
verify(loanPricingWorkflowMapper).insert(argThat((LoanPricingWorkflow entity) ->
|
||||
Objects.equals("cipher-name", entity.getCustName())
|
||||
&& Objects.equals("cipher-id", entity.getIdNum())
|
||||
&& Objects.equals(100L, entity.getDeptId())
|
||||
&& Objects.equals("CUST001", entity.getCustIsn())));
|
||||
}
|
||||
|
||||
@@ -148,6 +150,7 @@ class LoanPricingWorkflowServiceImplTest
|
||||
verify(loanPricingWorkflowMapper).selectWorkflowPageWithRates(any(), queryCaptor.capture());
|
||||
|
||||
assertNull(queryCaptor.getValue().getDataScopeCreateBy());
|
||||
assertNull(queryCaptor.getValue().getDataScopeDeptId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,6 +165,40 @@ class LoanPricingWorkflowServiceImplTest
|
||||
verify(loanPricingWorkflowMapper).selectWorkflowPageWithRates(any(), queryCaptor.capture());
|
||||
|
||||
assertNull(queryCaptor.getValue().getDataScopeCreateBy());
|
||||
assertNull(queryCaptor.getValue().getDataScopeDeptId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetCurrentDeptForBranchAdminWhenReturningPagedWorkflowList()
|
||||
{
|
||||
setLoginUser(102L, 101L, "8920100", "测试支行管理员", role(102L, "支行管理员", "branchAdmin"));
|
||||
when(loanPricingWorkflowMapper.selectWorkflowPageWithRates(any(), any())).thenReturn(emptyPageResult());
|
||||
|
||||
loanPricingWorkflowService.selectLoanPricingPage(new Page<>(1, 10), new LoanPricingWorkflow());
|
||||
|
||||
ArgumentCaptor<LoanPricingWorkflow> queryCaptor = ArgumentCaptor.forClass(LoanPricingWorkflow.class);
|
||||
verify(loanPricingWorkflowMapper).selectWorkflowPageWithRates(any(), queryCaptor.capture());
|
||||
|
||||
assertEquals(101L, queryCaptor.getValue().getDataScopeDeptId());
|
||||
assertNull(queryCaptor.getValue().getDataScopeCreateBy());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldKeepBranchAdminWithinDeptDataScopeWhenCreateByQueryIsProvided()
|
||||
{
|
||||
setLoginUser(102L, 101L, "8920100", "测试支行管理员", role(102L, "支行管理员", "branchAdmin"));
|
||||
LoanPricingWorkflow query = new LoanPricingWorkflow();
|
||||
query.setCreateBy("8920001");
|
||||
when(loanPricingWorkflowMapper.selectWorkflowPageWithRates(any(), any())).thenReturn(emptyPageResult());
|
||||
|
||||
loanPricingWorkflowService.selectLoanPricingPage(new Page<>(1, 10), query);
|
||||
|
||||
ArgumentCaptor<LoanPricingWorkflow> queryCaptor = ArgumentCaptor.forClass(LoanPricingWorkflow.class);
|
||||
verify(loanPricingWorkflowMapper).selectWorkflowPageWithRates(any(), queryCaptor.capture());
|
||||
|
||||
assertEquals("8920001", queryCaptor.getValue().getCreateBy());
|
||||
assertEquals(101L, queryCaptor.getValue().getDataScopeDeptId());
|
||||
assertNull(queryCaptor.getValue().getDataScopeCreateBy());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -193,6 +230,7 @@ class LoanPricingWorkflowServiceImplTest
|
||||
|
||||
assertEquals("若依-admin", queryCaptor.getValue().getCreateBy());
|
||||
assertEquals("测试客户经理-8920001", queryCaptor.getValue().getDataScopeCreateBy());
|
||||
assertNull(queryCaptor.getValue().getDataScopeDeptId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -336,15 +374,151 @@ class LoanPricingWorkflowServiceImplTest
|
||||
dto.setLoanTerm("3");
|
||||
dto.setCollType("存单质押");
|
||||
dto.setCouponRate("2.35");
|
||||
dto.setResCover("1");
|
||||
|
||||
loanPricingWorkflowService.createCorporateLoanPricing(dto);
|
||||
|
||||
verify(loanPricingWorkflowMapper).insert(argThat((LoanPricingWorkflow entity) ->
|
||||
Objects.equals("企业", entity.getCustType())
|
||||
&& Objects.equals("新增", entity.getBusinessType())
|
||||
&& Objects.equals("1", entity.getResCover())
|
||||
&& Objects.equals("2.35", entity.getCouponRate())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEditableWorkflowWithPlainSensitiveFieldsForCreator()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("个人", "若依-admin");
|
||||
workflow.setCustName("cipher-name");
|
||||
workflow.setIdNum("cipher-id");
|
||||
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三");
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001011234");
|
||||
|
||||
LoanPricingWorkflow result = loanPricingWorkflowService.selectEditableLoanPricingBySerialNum("P20260525001");
|
||||
|
||||
assertEquals("张三", result.getCustName());
|
||||
assertEquals("110101199001011234", result.getIdNum());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectEditableWorkflowWhenCurrentUserIsNotCreator()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("个人", "其他用户-8920001");
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> loanPricingWorkflowService.selectEditableLoanPricingBySerialNum("P20260525001"));
|
||||
|
||||
assertEquals("只有创建者可以编辑该流程", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdatePersonalWorkflowAndReinvokeModelForCreator()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("个人", "若依-admin");
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
when(sensitiveFieldCryptoService.encrypt("张三")).thenReturn("cipher-name-new");
|
||||
when(sensitiveFieldCryptoService.encrypt("110101199001019999")).thenReturn("cipher-id-new");
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("张三");
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("110101199001019999");
|
||||
|
||||
PersonalLoanPricingCreateDTO dto = new PersonalLoanPricingCreateDTO();
|
||||
dto.setCustIsn("CUST001");
|
||||
dto.setCustName("张三");
|
||||
dto.setIdType("身份证");
|
||||
dto.setIdNum("110101199001019999");
|
||||
dto.setGuarType("信用");
|
||||
dto.setApplyAmt("200000");
|
||||
dto.setBusinessType("新增");
|
||||
dto.setLoanTerm("3");
|
||||
dto.setLoanLoop("1");
|
||||
|
||||
loanPricingWorkflowService.updatePersonalLoanPricing("P20260525001", dto);
|
||||
|
||||
ArgumentCaptor<LambdaUpdateWrapper> updateWrapperCaptor = ArgumentCaptor.forClass(LambdaUpdateWrapper.class);
|
||||
verify(loanPricingWorkflowMapper).update(any(), updateWrapperCaptor.capture());
|
||||
assertTrue(updateWrapperCaptor.getValue().getSqlSet().contains("apply_amt"));
|
||||
verify(loanPricingModelService).reinvokeModelAndOverwrite(101L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateCorporateWorkflowAndReinvokeModelForCreator()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("企业", "若依-admin");
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
when(sensitiveFieldCryptoService.encrypt("测试科技有限公司")).thenReturn("cipher-corp-name");
|
||||
when(sensitiveFieldCryptoService.encrypt("91110000100000000X")).thenReturn("cipher-corp-id");
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("测试科技有限公司");
|
||||
when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("91110000100000000X");
|
||||
|
||||
CorporateLoanPricingCreateDTO dto = new CorporateLoanPricingCreateDTO();
|
||||
dto.setCustIsn("CORP001");
|
||||
dto.setCustName("测试科技有限公司");
|
||||
dto.setIdType("统一社会信用代码");
|
||||
dto.setIdNum("91110000100000000X");
|
||||
dto.setGuarType("质押");
|
||||
dto.setApplyAmt("300000");
|
||||
dto.setBusinessType("新增");
|
||||
dto.setLoanTerm("5");
|
||||
dto.setCollType("存单质押");
|
||||
dto.setCollThirdParty("1");
|
||||
dto.setCouponRate("2.35");
|
||||
dto.setResCover("1");
|
||||
dto.setIsGreenLoan("1");
|
||||
dto.setIsTradeBuildEnt("0");
|
||||
|
||||
loanPricingWorkflowService.updateCorporateLoanPricing("C20260525001", dto);
|
||||
|
||||
ArgumentCaptor<LambdaUpdateWrapper> updateWrapperCaptor = ArgumentCaptor.forClass(LambdaUpdateWrapper.class);
|
||||
verify(loanPricingWorkflowMapper).update(any(), updateWrapperCaptor.capture());
|
||||
String sqlSet = updateWrapperCaptor.getValue().getSqlSet();
|
||||
assertTrue(sqlSet.contains("res_cover"), sqlSet);
|
||||
assertTrue(sqlSet.contains("is_green_loan"), sqlSet);
|
||||
assertTrue(sqlSet.contains("is_trade_construction"), sqlSet);
|
||||
assertTrue(sqlSet.contains("coll_third_party"), sqlSet);
|
||||
verify(loanPricingModelService).reinvokeModelAndOverwrite(101L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectUpdateWhenCustomerTypeDoesNotMatch()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("个人", "若依-admin");
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
|
||||
CorporateLoanPricingCreateDTO dto = new CorporateLoanPricingCreateDTO();
|
||||
dto.setCustIsn("CORP001");
|
||||
dto.setGuarType("信用");
|
||||
dto.setApplyAmt("300000");
|
||||
dto.setBusinessType("新增");
|
||||
dto.setLoanTerm("5");
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> loanPricingWorkflowService.updateCorporateLoanPricing("P20260525001", dto));
|
||||
|
||||
assertEquals("客户类型不匹配,不能编辑该流程", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectUpdateWhenCurrentUserIsNotCreator()
|
||||
{
|
||||
LoanPricingWorkflow workflow = editableWorkflow("个人", "其他用户-8920001");
|
||||
when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow);
|
||||
|
||||
PersonalLoanPricingCreateDTO dto = new PersonalLoanPricingCreateDTO();
|
||||
dto.setCustIsn("CUST001");
|
||||
dto.setGuarType("信用");
|
||||
dto.setApplyAmt("200000");
|
||||
dto.setBusinessType("新增");
|
||||
dto.setLoanTerm("3");
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> loanPricingWorkflowService.updatePersonalLoanPricing("P20260525001", dto));
|
||||
|
||||
assertEquals("只有创建者可以编辑该流程", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseRetailModelOutputFinalCalculateRateForWorkflowDetail()
|
||||
{
|
||||
@@ -479,6 +653,25 @@ class LoanPricingWorkflowServiceImplTest
|
||||
return workflow;
|
||||
}
|
||||
|
||||
private LoanPricingWorkflow editableWorkflow(String custType, String createBy)
|
||||
{
|
||||
LoanPricingWorkflow workflow = new LoanPricingWorkflow();
|
||||
workflow.setId(101L);
|
||||
workflow.setSerialNum("个人".equals(custType) ? "P20260525001" : "C20260525001");
|
||||
workflow.setModelOutputId(201L);
|
||||
workflow.setCustIsn("CUST001");
|
||||
workflow.setCustType(custType);
|
||||
workflow.setCustName("cipher-name");
|
||||
workflow.setIdType("身份证");
|
||||
workflow.setIdNum("cipher-id");
|
||||
workflow.setGuarType("信用");
|
||||
workflow.setApplyAmt("100000");
|
||||
workflow.setBusinessType("新增");
|
||||
workflow.setLoanTerm("3");
|
||||
workflow.setCreateBy(createBy);
|
||||
return workflow;
|
||||
}
|
||||
|
||||
private Page<LoanPricingWorkflowListVO> emptyPageResult()
|
||||
{
|
||||
Page<LoanPricingWorkflowListVO> pageResult = new Page<>(1, 10);
|
||||
@@ -487,13 +680,19 @@ class LoanPricingWorkflowServiceImplTest
|
||||
}
|
||||
|
||||
private void setLoginUser(Long userId, String username, String nickName, SysRole... roles)
|
||||
{
|
||||
setLoginUser(userId, 100L, username, nickName, roles);
|
||||
}
|
||||
|
||||
private void setLoginUser(Long userId, Long deptId, String username, String nickName, SysRole... roles)
|
||||
{
|
||||
SysUser user = new SysUser();
|
||||
user.setUserId(userId);
|
||||
user.setDeptId(deptId);
|
||||
user.setUserName(username);
|
||||
user.setNickName(nickName);
|
||||
user.setRoles(java.util.Arrays.asList(roles));
|
||||
LoginUser loginUser = new LoginUser(userId, 100L, user, Collections.emptySet());
|
||||
LoginUser loginUser = new LoginUser(userId, deptId, user, Collections.emptySet());
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
Reference in New Issue
Block a user