修改抵押物类型自动判断逻辑

This commit is contained in:
wkc
2026-08-10 15:53:41 +08:00
parent 739a73c6ee
commit 3667a3cf78
7 changed files with 335 additions and 37 deletions

View File

@@ -65,8 +65,8 @@ public class CorporateLoanPricingCreateDTO implements Serializable {
@Schema(description = "贸易和建筑业企业标识", example = "0")
private String isTradeBuildEnt;
@Schema(description = "抵质押类型", example = "一类", allowableValues = {"一类", "二类", "三类", "四类", "排污权抵押", "设备等其他不动产抵押", "存单质押", "股权质押", "其他质押"})
@Pattern(regexp = "^(一类|二类|三类|四类|排污权抵押|设备等其他不动产抵押|存单质押|股权质押|其他质押)$", message = "抵质押类型必须是:一类、二类、三类、四类、排污权抵押、设备等其他不动产抵押、存单质押、股权质押、其他质押之一")
@Schema(description = "抵质押类型", example = "一类", allowableValues = {"一类", "二类", "三类", "排污权抵押", "其他不动产抵押", "存单质押", "股权质押", "其他质押"})
@Pattern(regexp = "^(一类|二类|三类|排污权抵押|其他不动产抵押|存单质押|股权质押|其他质押)$", message = "抵质押类型必须是:一类、二类、三类、排污权抵押、其他不动产抵押、存单质押、股权质押、其他质押之一")
private String collType;
@Schema(description = "抵质押物是否三方所有", example = "0")

View File

@@ -56,7 +56,7 @@ public class PersonalLoanPricingCreateDTO implements Serializable {
@Schema(description = "循环功能", example = "0")
private String loanLoop;
@Schema(description = "抵质押类型", example = "一类", allowableValues = {"线", "", "二类", "三类", "存单质押", "其他质押"})
@Schema(description = "抵质押类型", example = "一类", allowableValues = {"一类", "二类", "三类", "四类", "存单质押", "其他质押"})
private String collType;
@Schema(description = "抵质押物是否三方所有", example = "0")

View File

@@ -139,8 +139,8 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
private void validatePersonalCollateralType(LoanPricingWorkflow workflow) {
if ("抵押".equals(workflow.getGuarType())
&& !isOneOf(workflow.getCollType(), "线", "", "二类", "三类")) {
throw new ServiceException("个人抵押抵质押类型必须是:一线、一类、二类、三类之一");
&& !isOneOf(workflow.getCollType(), "一类", "二类", "三类", "四类")) {
throw new ServiceException("个人抵押抵质押类型必须是:一类、二类、三类、四类之一");
}
if ("质押".equals(workflow.getGuarType())
&& !isOneOf(workflow.getCollType(), "存单质押", "其他质押")) {
@@ -150,8 +150,8 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi
private void validateCorporateCollateralType(LoanPricingWorkflow workflow) {
if ("抵押".equals(workflow.getGuarType())
&& !isOneOf(workflow.getCollType(), "一类", "二类", "三类", "四类", "排污权抵押", "设备等其他不动产抵押")) {
throw new ServiceException("企业抵押抵质押类型必须是:一类、二类、三类、四类、排污权抵押、设备等其他不动产抵押之一");
&& !isOneOf(workflow.getCollType(), "一类", "二类", "三类", "排污权抵押", "其他不动产抵押")) {
throw new ServiceException("企业抵押抵质押类型必须是:一类、二类、三类、排污权抵押、其他不动产抵押之一");
}
if ("质押".equals(workflow.getGuarType())
&& !isOneOf(workflow.getCollType(), "存单质押", "股权质押", "其他质押")) {

View File

@@ -290,36 +290,67 @@ class LoanPricingWorkflowServiceImplTest
}
@Test
void shouldAllowPersonalMortgageOneLineAndRejectOldOther()
void shouldAllowPersonalMortgageFourthCategoryAndRejectOldFirstLine()
{
LoanPricingWorkflow allowedWorkflow = validWorkflow();
allowedWorkflow.setCustType("个人");
allowedWorkflow.setGuarType("抵押");
allowedWorkflow.setCollType("一线");
allowedWorkflow.setCollType("四类");
loanPricingWorkflowService.createLoanPricing(allowedWorkflow);
LoanPricingWorkflow rejectedWorkflow = validWorkflow();
rejectedWorkflow.setCustType("个人");
rejectedWorkflow.setGuarType("抵押");
rejectedWorkflow.setCollType("其他");
rejectedWorkflow.setCollType("一线");
ServiceException exception = assertThrows(ServiceException.class,
() -> loanPricingWorkflowService.createLoanPricing(rejectedWorkflow));
assertEquals("个人抵押抵质押类型必须是:一线、一类、二类、三类之一", exception.getMessage());
assertEquals("个人抵押抵质押类型必须是:一类、二类、三类、四类之一", exception.getMessage());
}
@Test
void shouldAllowCorporateMortgagePollutionRightAndPledgeEquity()
void shouldAllowCorporateNewMortgageTypesAndRejectOldMortgageTypes()
{
LoanPricingWorkflow mortgageWorkflow = validWorkflow();
mortgageWorkflow.setCustType("企业");
mortgageWorkflow.setGuarType("抵押");
mortgageWorkflow.setCollType("排污权抵押");
LoanPricingWorkflow pollutionRightWorkflow = validWorkflow();
pollutionRightWorkflow.setCustType("企业");
pollutionRightWorkflow.setGuarType("抵押");
pollutionRightWorkflow.setCollType("排污权抵押");
loanPricingWorkflowService.createLoanPricing(mortgageWorkflow);
loanPricingWorkflowService.createLoanPricing(pollutionRightWorkflow);
LoanPricingWorkflow otherRealEstateWorkflow = validWorkflow();
otherRealEstateWorkflow.setCustType("企业");
otherRealEstateWorkflow.setGuarType("抵押");
otherRealEstateWorkflow.setCollType("其他不动产抵押");
loanPricingWorkflowService.createLoanPricing(otherRealEstateWorkflow);
LoanPricingWorkflow oldFourthCategoryWorkflow = validWorkflow();
oldFourthCategoryWorkflow.setCustType("企业");
oldFourthCategoryWorkflow.setGuarType("抵押");
oldFourthCategoryWorkflow.setCollType("四类");
ServiceException fourthCategoryException = assertThrows(ServiceException.class,
() -> loanPricingWorkflowService.createLoanPricing(oldFourthCategoryWorkflow));
LoanPricingWorkflow oldOtherRealEstateWorkflow = validWorkflow();
oldOtherRealEstateWorkflow.setCustType("企业");
oldOtherRealEstateWorkflow.setGuarType("抵押");
oldOtherRealEstateWorkflow.setCollType("设备等其他不动产抵押");
ServiceException otherRealEstateException = assertThrows(ServiceException.class,
() -> loanPricingWorkflowService.createLoanPricing(oldOtherRealEstateWorkflow));
String expectedMessage = "企业抵押抵质押类型必须是:一类、二类、三类、排污权抵押、其他不动产抵押之一";
assertEquals(expectedMessage, fourthCategoryException.getMessage());
assertEquals(expectedMessage, otherRealEstateException.getMessage());
}
@Test
void shouldKeepCorporatePledgeTypesUnchanged()
{
LoanPricingWorkflow pledgeWorkflow = validWorkflow();
pledgeWorkflow.setCustType("企业");
pledgeWorkflow.setGuarType("质押");

View File

@@ -100,7 +100,33 @@
<!-- 抵质押信息 -->
<el-divider v-if="isCollateralGuarantee" content-position="left">抵质押信息</el-divider>
<el-row v-if="isCollateralGuarantee">
<el-col :span="12">
<template v-if="isMortgage">
<el-col :span="12">
<el-form-item label="抵押物性质" prop="collateralNature">
<el-select v-model="form.collateralNature" placeholder="请选择抵押物性质" style="width: 100%">
<el-option v-for="item in collateralNatureOptions" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否属于九地" prop="isNineArea">
<div class="nine-area-control">
<el-select
v-model="form.isNineArea"
:disabled="!requiresNineArea"
:placeholder="requiresNineArea ? '请选择是否属于九地' : '无需选择'"
>
<el-option label="是" value="是"/>
<el-option label="否" value="否"/>
</el-select>
<el-tooltip content="九地是指绍兴、杭州、宁波、上海、北京、广州、深圳、南京、苏州" placement="top">
<i class="el-icon-question nine-area-help" tabindex="0" aria-label="查看九地说明"></i>
</el-tooltip>
</div>
</el-form-item>
</el-col>
</template>
<el-col :span="12" v-if="isPledge">
<el-form-item label="抵质押类型" prop="collType">
<el-select v-model="form.collType" placeholder="请选择抵质押类型" style="width: 100%">
<el-option v-for="item in collateralTypeOptions" :key="item" :label="item" :value="item"/>
@@ -181,6 +207,30 @@ export default {
callback()
}
const validateCollateralType = (rule, value, callback) => {
if (this.isPledge && !value) {
callback(new Error('请选择抵质押类型'))
return
}
callback()
}
const validateCollateralNature = (rule, value, callback) => {
if (this.isMortgage && !value) {
callback(new Error('请选择抵押物性质'))
return
}
callback()
}
const validateNineArea = (rule, value, callback) => {
if (this.requiresNineArea && !value) {
callback(new Error('请选择是否属于九地'))
return
}
callback()
}
// 贷款期限验证
const validateLoanTerm = (rule, value, callback) => {
if (!value && value !== 0) {
@@ -221,6 +271,8 @@ export default {
isGreenLoan: false,
isTradeBuildEnt: false,
collType: undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: false,
couponRate: undefined
},
@@ -255,7 +307,13 @@ export default {
{required: true, message: "请选择历史贷款合同", trigger: "change"}
],
collType: [
{required: true, message: "请选择抵质押类型", trigger: "change"}
{validator: validateCollateralType, trigger: "change"}
],
collateralNature: [
{validator: validateCollateralNature, trigger: "change"}
],
isNineArea: [
{validator: validateNineArea, trigger: "change"}
],
couponRate: [
{validator: validateCouponRate, trigger: "blur"}
@@ -275,6 +333,15 @@ export default {
isCollateralGuarantee() {
return this.form.guarType === '抵押' || this.form.guarType === '质押'
},
isMortgage() {
return this.form.guarType === '抵押'
},
isPledge() {
return this.form.guarType === '质押'
},
requiresNineArea() {
return this.isMortgage && ['普通住宅、土地、厂房', '商业性质不动产'].includes(this.form.collateralNature)
},
isStockTransfer() {
return this.form.businessType === '存量转贷'
},
@@ -288,13 +355,13 @@ export default {
return this.isEdit ? '编辑企业利率定价流程' : '新增企业利率定价流程'
},
collateralTypeOptions() {
if (this.form.guarType === '抵押') {
return ['一类', '二类', '三类', '四类', '排污权抵押', '设备等其他不动产抵押']
}
if (this.form.guarType === '质押') {
if (this.isPledge) {
return ['存单质押', '股权质押', '其他质押']
}
return []
},
collateralNatureOptions() {
return ['普通住宅、土地、厂房', '商业性质不动产', '排污权', '其他不动产']
}
},
watch: {
@@ -316,6 +383,12 @@ export default {
return
}
this.resetCouponRateIfNotCertificatePledge()
},
'form.collateralNature'(val, oldVal) {
if (this.resettingForm || val === oldVal) {
return
}
this.handleCollateralNatureChange()
}
},
methods: {
@@ -353,7 +426,9 @@ export default {
resCover: this.isOne(this.editData.resCover),
isGreenLoan: this.isOne(this.editData.isGreenLoan),
isTradeBuildEnt: this.isOne(this.editData.isTradeBuildEnt),
collType: this.editData.collType,
collType: this.editData.guarType === '质押' ? this.editData.collType : undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: this.isOne(this.editData.collThirdParty),
couponRate: this.editData.couponRate
}
@@ -374,6 +449,8 @@ export default {
isGreenLoan: false,
isTradeBuildEnt: false,
collType: undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: false,
couponRate: undefined
}
@@ -393,14 +470,38 @@ export default {
/** 清空抵质押字段 */
resetCollateralFields() {
this.form.collType = undefined
this.form.collateralNature = undefined
this.form.isNineArea = undefined
this.form.collThirdParty = false
this.resetCouponRateIfNotCertificatePledge()
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate(['collType', 'collThirdParty', 'couponRate'])
this.$refs.form.clearValidate(['collType', 'collateralNature', 'isNineArea', 'collThirdParty', 'couponRate'])
}
})
},
handleCollateralNatureChange() {
this.form.isNineArea = undefined
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate(['isNineArea'])
}
})
},
resolveMortgageCollateralType() {
if (this.form.collateralNature === '普通住宅、土地、厂房') {
return this.form.isNineArea === '是' ? '一类' : '二类'
}
if (this.form.collateralNature === '商业性质不动产') {
return this.form.isNineArea === '是' ? '二类' : '三类'
}
if (this.form.collateralNature === '排污权') {
return '排污权抵押'
}
if (this.form.collateralNature === '其他不动产') {
return '其他不动产抵押'
}
},
resetCouponRateIfNotCertificatePledge() {
if (!this.isCertificatePledge) {
this.form.couponRate = undefined
@@ -472,6 +573,11 @@ export default {
isGreenLoan: this.form.isGreenLoan ? '1' : '0',
isTradeBuildEnt: this.form.isTradeBuildEnt ? '1' : '0'
}
if (this.isMortgage) {
data.collType = this.resolveMortgageCollateralType()
}
delete data.collateralNature
delete data.isNineArea
if (this.isCollateralGuarantee) {
data.collThirdParty = this.form.collThirdParty ? '1' : '0'
} else {
@@ -512,6 +618,24 @@ export default {
font-size: 14px;
}
.nine-area-control {
display: flex;
align-items: center;
gap: 8px;
}
.nine-area-control .el-select {
flex: 1;
min-width: 0;
}
.nine-area-help {
flex: 0 0 auto;
color: #909399;
cursor: help;
font-size: 16px;
}
@media screen and (max-width: 768px) {
.workflow-create-form .el-col {
width: 100% !important;

View File

@@ -87,7 +87,33 @@
<!-- 抵质押信息 -->
<el-divider v-if="isCollateralGuarantee" content-position="left">抵质押信息</el-divider>
<el-row v-if="isCollateralGuarantee">
<el-col :span="12">
<template v-if="isMortgage">
<el-col :span="12">
<el-form-item label="抵押物性质" prop="collateralNature">
<el-select v-model="form.collateralNature" placeholder="请选择抵押物性质" style="width: 100%">
<el-option v-for="item in collateralNatureOptions" :key="item" :label="item" :value="item"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否属于九地" prop="isNineArea">
<div class="nine-area-control">
<el-select
v-model="form.isNineArea"
:disabled="!requiresNineArea"
:placeholder="requiresNineArea ? '请选择是否属于九地' : '无需选择'"
>
<el-option label="是" value="是"/>
<el-option label="否" value="否"/>
</el-select>
<el-tooltip content="九地是指绍兴、杭州、宁波、上海、北京、广州、深圳、南京、苏州" placement="top">
<i class="el-icon-question nine-area-help" tabindex="0" aria-label="查看九地说明"></i>
</el-tooltip>
</div>
</el-form-item>
</el-col>
</template>
<el-col :span="12" v-if="isPledge">
<el-form-item label="抵质押类型" prop="collType">
<el-select v-model="form.collType" placeholder="请选择抵质押类型" style="width: 100%">
<el-option v-for="item in collateralTypeOptions" :key="item" :label="item" :value="item"/>
@@ -168,6 +194,30 @@ export default {
callback()
}
const validateCollateralType = (rule, value, callback) => {
if (this.isPledge && !value) {
callback(new Error('请选择抵质押类型'))
return
}
callback()
}
const validateCollateralNature = (rule, value, callback) => {
if (this.isMortgage && !value) {
callback(new Error('请选择抵押物性质'))
return
}
callback()
}
const validateNineArea = (rule, value, callback) => {
if (this.requiresNineArea && !value) {
callback(new Error('请选择是否属于九地'))
return
}
callback()
}
return {
loanTermOptions: [
'1', '2', '3', '4', '5', '6'
@@ -192,6 +242,8 @@ export default {
loanRateHistory: undefined,
loanLoop: false,
collType: undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: false,
couponRate: undefined
},
@@ -226,7 +278,13 @@ export default {
{required: true, message: "请选择历史贷款合同", trigger: "change"}
],
collType: [
{required: true, message: "请选择抵质押类型", trigger: "change"}
{validator: validateCollateralType, trigger: "change"}
],
collateralNature: [
{validator: validateCollateralNature, trigger: "change"}
],
isNineArea: [
{validator: validateNineArea, trigger: "change"}
],
couponRate: [
{validator: validateCouponRate, trigger: "blur"}
@@ -246,6 +304,15 @@ export default {
isCollateralGuarantee() {
return this.form.guarType === '抵押' || this.form.guarType === '质押'
},
isMortgage() {
return this.form.guarType === '抵押'
},
isPledge() {
return this.form.guarType === '质押'
},
requiresNineArea() {
return this.isMortgage && ['普通住宅、土地、厂房', '商业性质不动产'].includes(this.form.collateralNature)
},
isStockTransfer() {
return this.form.businessType === '存量转贷'
},
@@ -259,13 +326,13 @@ export default {
return this.isEdit ? '编辑个人利率定价流程' : '新增个人利率定价流程'
},
collateralTypeOptions() {
if (this.form.guarType === '抵押') {
return ['一线', '一类', '二类', '三类']
}
if (this.form.guarType === '质押') {
if (this.isPledge) {
return ['存单质押', '其他质押']
}
return []
},
collateralNatureOptions() {
return ['普通住宅、土地、厂房', '商业性质不动产', '其他抵押财产']
}
},
watch: {
@@ -287,6 +354,12 @@ export default {
return
}
this.resetCouponRateIfNotCertificatePledge()
},
'form.collateralNature'(val, oldVal) {
if (this.resettingForm || val === oldVal) {
return
}
this.handleCollateralNatureChange()
}
},
methods: {
@@ -322,7 +395,9 @@ export default {
businessType: this.editData.businessType,
loanRateHistory: this.editData.loanRateHistory,
loanLoop: this.isOne(this.editData.loanLoop),
collType: this.editData.collType,
collType: this.editData.guarType === '质押' ? this.editData.collType : undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: this.isOne(this.editData.collThirdParty),
couponRate: this.editData.couponRate
}
@@ -341,6 +416,8 @@ export default {
loanRateHistory: undefined,
loanLoop: false,
collType: undefined,
collateralNature: undefined,
isNineArea: undefined,
collThirdParty: false,
couponRate: undefined
}
@@ -360,14 +437,35 @@ export default {
/** 清空抵质押字段 */
resetCollateralFields() {
this.form.collType = undefined
this.form.collateralNature = undefined
this.form.isNineArea = undefined
this.form.collThirdParty = false
this.resetCouponRateIfNotCertificatePledge()
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate(['collType', 'collThirdParty', 'couponRate'])
this.$refs.form.clearValidate(['collType', 'collateralNature', 'isNineArea', 'collThirdParty', 'couponRate'])
}
})
},
handleCollateralNatureChange() {
this.form.isNineArea = undefined
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate(['isNineArea'])
}
})
},
resolveMortgageCollateralType() {
if (this.form.collateralNature === '普通住宅、土地、厂房') {
return this.form.isNineArea === '是' ? '一类' : '二类'
}
if (this.form.collateralNature === '商业性质不动产') {
return this.form.isNineArea === '是' ? '二类' : '三类'
}
if (this.form.collateralNature === '其他抵押财产') {
return '四类'
}
},
resetCouponRateIfNotCertificatePledge() {
if (!this.isCertificatePledge) {
this.form.couponRate = undefined
@@ -437,6 +535,11 @@ export default {
...this.form,
loanLoop: this.form.loanLoop ? '1' : '0'
}
if (this.isMortgage) {
data.collType = this.resolveMortgageCollateralType()
}
delete data.collateralNature
delete data.isNineArea
if (this.isCollateralGuarantee) {
data.collThirdParty = this.form.collThirdParty ? '1' : '0'
} else {
@@ -477,6 +580,24 @@ export default {
font-size: 14px;
}
.nine-area-control {
display: flex;
align-items: center;
gap: 8px;
}
.nine-area-control .el-select {
flex: 1;
min-width: 0;
}
.nine-area-help {
flex: 0 0 auto;
color: #909399;
cursor: help;
font-size: 16px;
}
@media screen and (max-width: 768px) {
.workflow-create-form .el-col {
width: 100% !important;

View File

@@ -52,14 +52,33 @@ assert(
assert(
personalCreateDialog.includes('collateralTypeOptions') &&
personalCreateDialog.includes("return ['一线', '一类', '二类', '三类']") &&
personalCreateDialog.includes("return ['存单质押', '其他质押']"),
'个人新增弹窗质押类型选项未按担保方式动态切换'
'个人新增弹窗应保留质押类型选项'
)
assert(
personalCreateDialog.includes('{required: true, message: "请选择抵质押类型", trigger: "change"}'),
'个人新增弹窗抵质押类型应为必填'
personalCreateDialog.includes('label="抵押物性质"') &&
personalCreateDialog.includes('prop="collateralNature"') &&
personalCreateDialog.includes("return ['普通住宅、土地、厂房', '商业性质不动产', '其他抵押财产']") &&
personalCreateDialog.includes('label="是否属于九地"') &&
personalCreateDialog.includes('九地是指绍兴、杭州、宁波、上海、北京、广州、深圳、南京、苏州') &&
personalCreateDialog.includes(':disabled="!requiresNineArea"') &&
personalCreateDialog.includes("'无需选择'"),
'个人新增弹窗缺少抵押物性质、九地选择或九地说明'
)
assert(
personalCreateDialog.includes("return this.form.isNineArea === '是' ? '一类' : '二类'") &&
personalCreateDialog.includes("return this.form.isNineArea === '是' ? '二类' : '三类'") &&
personalCreateDialog.includes("return '四类'"),
'个人新增弹窗抵押物类型映射不完整'
)
assert(
personalCreateDialog.includes("if (this.isPledge && !value)") &&
personalCreateDialog.includes("if (this.isMortgage && !value)") &&
personalCreateDialog.includes("if (this.requiresNineArea && !value)"),
'个人新增弹窗缺少抵押和质押的条件校验'
)
assert(
@@ -68,6 +87,9 @@ assert(
!personalCreateDialog.includes('bizProof:') &&
personalCreateDialog.includes("loanLoop: this.form.loanLoop ? '1' : '0'") &&
personalCreateDialog.includes("data.collThirdParty = this.form.collThirdParty ? '1' : '0'") &&
personalCreateDialog.includes('data.collType = this.resolveMortgageCollateralType()') &&
personalCreateDialog.includes('delete data.collateralNature') &&
personalCreateDialog.includes('delete data.isNineArea') &&
personalCreateDialog.includes('delete data.collType') &&
personalCreateDialog.includes('delete data.collThirdParty'),
'个人新增弹窗开关字段或非抵质押提交字段处理不正确'