添加银行端后端接口
This commit is contained in:
111
bank-backend/models/AuditRecord.js
Normal file
111
bank-backend/models/AuditRecord.js
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 审核记录模型
|
||||
* @file AuditRecord.js
|
||||
* @description 银行系统贷款申请审核记录数据模型
|
||||
*/
|
||||
const { DataTypes } = require('sequelize');
|
||||
const BaseModel = require('./BaseModel');
|
||||
|
||||
class AuditRecord extends BaseModel {
|
||||
/**
|
||||
* 获取审核动作文本
|
||||
* @returns {String} 动作文本
|
||||
*/
|
||||
getActionText() {
|
||||
const actionMap = {
|
||||
submit: '提交申请',
|
||||
approve: '审核通过',
|
||||
reject: '审核拒绝',
|
||||
review: '初审',
|
||||
verification: '核验',
|
||||
binding: '绑定'
|
||||
};
|
||||
return actionMap[this.action] || this.action;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审核动作颜色
|
||||
* @returns {String} 颜色
|
||||
*/
|
||||
getActionColor() {
|
||||
const colorMap = {
|
||||
submit: 'blue',
|
||||
approve: 'green',
|
||||
reject: 'red',
|
||||
review: 'orange',
|
||||
verification: 'purple',
|
||||
binding: 'cyan'
|
||||
};
|
||||
return colorMap[this.action] || 'default';
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化AuditRecord模型
|
||||
AuditRecord.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
applicationId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '申请ID',
|
||||
references: {
|
||||
model: 'bank_loan_applications',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
action: {
|
||||
type: DataTypes.ENUM(
|
||||
'submit',
|
||||
'approve',
|
||||
'reject',
|
||||
'review',
|
||||
'verification',
|
||||
'binding'
|
||||
),
|
||||
allowNull: false,
|
||||
comment: '审核动作'
|
||||
},
|
||||
auditor: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '审核人'
|
||||
},
|
||||
auditorId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '审核人ID'
|
||||
},
|
||||
comment: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '审核意见'
|
||||
},
|
||||
auditTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '审核时间'
|
||||
},
|
||||
previousStatus: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
comment: '审核前状态'
|
||||
},
|
||||
newStatus: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
comment: '审核后状态'
|
||||
}
|
||||
}, {
|
||||
sequelize: require('../config/database').sequelize,
|
||||
modelName: 'AuditRecord',
|
||||
tableName: 'bank_audit_records',
|
||||
timestamps: true,
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
});
|
||||
|
||||
module.exports = AuditRecord;
|
||||
109
bank-backend/models/CompletedSupervision.js
Normal file
109
bank-backend/models/CompletedSupervision.js
Normal file
@@ -0,0 +1,109 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
const CompletedSupervision = sequelize.define('CompletedSupervision', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
comment: '主键ID'
|
||||
},
|
||||
applicationNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '申请单号'
|
||||
},
|
||||
contractNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '放款合同编号'
|
||||
},
|
||||
productName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '产品名称'
|
||||
},
|
||||
customerName: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '客户姓名'
|
||||
},
|
||||
idType: {
|
||||
type: DataTypes.ENUM('ID_CARD', 'PASSPORT', 'OTHER'),
|
||||
allowNull: false,
|
||||
defaultValue: 'ID_CARD',
|
||||
comment: '证件类型'
|
||||
},
|
||||
idNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '证件号码'
|
||||
},
|
||||
assetType: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '养殖生资种类'
|
||||
},
|
||||
assetQuantity: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '监管生资数量'
|
||||
},
|
||||
totalRepaymentPeriods: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '总还款期数'
|
||||
},
|
||||
settlementStatus: {
|
||||
type: DataTypes.ENUM('settled', 'unsettled', 'partial'),
|
||||
allowNull: false,
|
||||
defaultValue: 'unsettled',
|
||||
comment: '结清状态'
|
||||
},
|
||||
settlementDate: {
|
||||
type: DataTypes.DATEONLY,
|
||||
allowNull: true,
|
||||
comment: '结清日期'
|
||||
},
|
||||
importTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
comment: '结清任务导入时间'
|
||||
},
|
||||
settlementAmount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: true,
|
||||
comment: '结清金额'
|
||||
},
|
||||
remainingAmount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: true,
|
||||
comment: '剩余金额'
|
||||
},
|
||||
settlementNotes: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '结清备注'
|
||||
},
|
||||
createdBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '创建人ID'
|
||||
},
|
||||
updatedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '更新人ID'
|
||||
}
|
||||
}, {
|
||||
tableName: 'completed_supervisions',
|
||||
timestamps: true,
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt',
|
||||
comment: '监管任务已结项表'
|
||||
});
|
||||
|
||||
module.exports = CompletedSupervision;
|
||||
107
bank-backend/models/InstallationTask.js
Normal file
107
bank-backend/models/InstallationTask.js
Normal file
@@ -0,0 +1,107 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
const InstallationTask = sequelize.define('InstallationTask', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
comment: '主键ID'
|
||||
},
|
||||
applicationNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '申请单号'
|
||||
},
|
||||
contractNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '放款合同编号'
|
||||
},
|
||||
productName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '产品名称'
|
||||
},
|
||||
customerName: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '客户姓名'
|
||||
},
|
||||
idType: {
|
||||
type: DataTypes.ENUM('ID_CARD', 'PASSPORT', 'OTHER'),
|
||||
allowNull: false,
|
||||
defaultValue: 'ID_CARD',
|
||||
comment: '证件类型'
|
||||
},
|
||||
idNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '证件号码'
|
||||
},
|
||||
assetType: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '养殖生资种类'
|
||||
},
|
||||
equipmentToInstall: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '待安装设备'
|
||||
},
|
||||
installationStatus: {
|
||||
type: DataTypes.ENUM('pending', 'in-progress', 'completed', 'failed'),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending',
|
||||
comment: '安装状态'
|
||||
},
|
||||
taskGenerationTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
comment: '生成安装任务时间'
|
||||
},
|
||||
completionTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '安装完成生效时间'
|
||||
},
|
||||
installationNotes: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '安装备注'
|
||||
},
|
||||
installerName: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
comment: '安装员姓名'
|
||||
},
|
||||
installerPhone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: true,
|
||||
comment: '安装员电话'
|
||||
},
|
||||
installationAddress: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: true,
|
||||
comment: '安装地址'
|
||||
},
|
||||
createdBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '创建人ID'
|
||||
},
|
||||
updatedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '更新人ID'
|
||||
}
|
||||
}, {
|
||||
tableName: 'installation_tasks',
|
||||
timestamps: true,
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt',
|
||||
comment: '待安装任务表'
|
||||
});
|
||||
|
||||
module.exports = InstallationTask;
|
||||
194
bank-backend/models/LoanApplication.js
Normal file
194
bank-backend/models/LoanApplication.js
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 贷款申请模型
|
||||
* @file LoanApplication.js
|
||||
* @description 银行系统贷款申请数据模型
|
||||
*/
|
||||
const { DataTypes } = require('sequelize');
|
||||
const BaseModel = require('./BaseModel');
|
||||
|
||||
class LoanApplication extends BaseModel {
|
||||
/**
|
||||
* 获取申请状态文本
|
||||
* @returns {String} 状态文本
|
||||
*/
|
||||
getStatusText() {
|
||||
const statusMap = {
|
||||
pending_review: '待初审',
|
||||
verification_pending: '核验待放款',
|
||||
pending_binding: '待绑定',
|
||||
approved: '已通过',
|
||||
rejected: '已拒绝'
|
||||
};
|
||||
return statusMap[this.status] || this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取申请类型文本
|
||||
* @returns {String} 类型文本
|
||||
*/
|
||||
getTypeText() {
|
||||
const typeMap = {
|
||||
personal: '个人贷款',
|
||||
business: '企业贷款',
|
||||
mortgage: '抵押贷款'
|
||||
};
|
||||
return typeMap[this.type] || this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化申请金额
|
||||
* @returns {String} 格式化后的金额
|
||||
*/
|
||||
getFormattedAmount() {
|
||||
return `${this.amount.toFixed(2)}元`;
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化LoanApplication模型
|
||||
LoanApplication.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
applicationNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '申请单号'
|
||||
},
|
||||
productName: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: false,
|
||||
comment: '贷款产品名称'
|
||||
},
|
||||
farmerName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '申请养殖户姓名'
|
||||
},
|
||||
borrowerName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '贷款人姓名'
|
||||
},
|
||||
borrowerIdNumber: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
comment: '贷款人身份证号'
|
||||
},
|
||||
assetType: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '生资种类'
|
||||
},
|
||||
applicationQuantity: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '申请数量'
|
||||
},
|
||||
amount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: false,
|
||||
comment: '申请额度'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM(
|
||||
'pending_review',
|
||||
'verification_pending',
|
||||
'pending_binding',
|
||||
'approved',
|
||||
'rejected'
|
||||
),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending_review',
|
||||
comment: '申请状态'
|
||||
},
|
||||
type: {
|
||||
type: DataTypes.ENUM('personal', 'business', 'mortgage'),
|
||||
allowNull: false,
|
||||
defaultValue: 'personal',
|
||||
comment: '申请类型'
|
||||
},
|
||||
term: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '申请期限(月)'
|
||||
},
|
||||
interestRate: {
|
||||
type: DataTypes.DECIMAL(5, 2),
|
||||
allowNull: false,
|
||||
comment: '预计利率'
|
||||
},
|
||||
phone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
comment: '联系电话'
|
||||
},
|
||||
purpose: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '申请用途'
|
||||
},
|
||||
remark: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '备注'
|
||||
},
|
||||
applicationTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '申请时间'
|
||||
},
|
||||
approvedTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '审批通过时间'
|
||||
},
|
||||
rejectedTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '审批拒绝时间'
|
||||
},
|
||||
approvedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '审批人ID'
|
||||
},
|
||||
rejectedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '拒绝人ID'
|
||||
},
|
||||
rejectionReason: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '拒绝原因'
|
||||
}
|
||||
}, {
|
||||
sequelize: require('../config/database').sequelize,
|
||||
modelName: 'LoanApplication',
|
||||
tableName: 'bank_loan_applications',
|
||||
timestamps: true,
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt',
|
||||
hooks: {
|
||||
beforeCreate: (application) => {
|
||||
// 生成申请单号
|
||||
if (!application.applicationNumber) {
|
||||
const now = new Date();
|
||||
const timestamp = now.getFullYear().toString() +
|
||||
(now.getMonth() + 1).toString().padStart(2, '0') +
|
||||
now.getDate().toString().padStart(2, '0') +
|
||||
now.getHours().toString().padStart(2, '0') +
|
||||
now.getMinutes().toString().padStart(2, '0') +
|
||||
now.getSeconds().toString().padStart(2, '0');
|
||||
const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
|
||||
application.applicationNumber = timestamp + random;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = LoanApplication;
|
||||
235
bank-backend/models/LoanContract.js
Normal file
235
bank-backend/models/LoanContract.js
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* 贷款合同模型
|
||||
* @file LoanContract.js
|
||||
* @description 银行系统贷款合同数据模型
|
||||
*/
|
||||
const { DataTypes } = require('sequelize');
|
||||
const BaseModel = require('./BaseModel');
|
||||
|
||||
class LoanContract extends BaseModel {
|
||||
/**
|
||||
* 获取合同状态文本
|
||||
* @returns {String} 状态文本
|
||||
*/
|
||||
getStatusText() {
|
||||
const statusMap = {
|
||||
active: '已放款',
|
||||
pending: '待放款',
|
||||
completed: '已完成',
|
||||
defaulted: '违约',
|
||||
cancelled: '已取消'
|
||||
};
|
||||
return statusMap[this.status] || this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合同类型文本
|
||||
* @returns {String} 类型文本
|
||||
*/
|
||||
getTypeText() {
|
||||
const typeMap = {
|
||||
livestock_collateral: '畜禽活体抵押',
|
||||
farmer_loan: '惠农贷',
|
||||
business_loan: '商业贷款',
|
||||
personal_loan: '个人贷款'
|
||||
};
|
||||
return typeMap[this.type] || this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化合同金额
|
||||
* @returns {String} 格式化后的金额
|
||||
*/
|
||||
getFormattedAmount() {
|
||||
return `${this.amount.toFixed(2)}元`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算剩余还款金额
|
||||
* @returns {Number} 剩余金额
|
||||
*/
|
||||
getRemainingAmount() {
|
||||
return this.amount - (this.paidAmount || 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算还款进度百分比
|
||||
* @returns {Number} 进度百分比
|
||||
*/
|
||||
getRepaymentProgress() {
|
||||
if (this.amount <= 0) return 0;
|
||||
return Math.round(((this.paidAmount || 0) / this.amount) * 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化LoanContract模型
|
||||
LoanContract.init({
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
contractNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '合同编号'
|
||||
},
|
||||
applicationNumber: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '申请单号'
|
||||
},
|
||||
productName: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: false,
|
||||
comment: '贷款产品名称'
|
||||
},
|
||||
farmerName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '申请养殖户姓名'
|
||||
},
|
||||
borrowerName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '贷款人姓名'
|
||||
},
|
||||
borrowerIdNumber: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
comment: '贷款人身份证号'
|
||||
},
|
||||
assetType: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
comment: '生资种类'
|
||||
},
|
||||
applicationQuantity: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '申请数量'
|
||||
},
|
||||
amount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: false,
|
||||
comment: '合同金额'
|
||||
},
|
||||
paidAmount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '已还款金额'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM(
|
||||
'active',
|
||||
'pending',
|
||||
'completed',
|
||||
'defaulted',
|
||||
'cancelled'
|
||||
),
|
||||
allowNull: false,
|
||||
defaultValue: 'pending',
|
||||
comment: '合同状态'
|
||||
},
|
||||
type: {
|
||||
type: DataTypes.ENUM(
|
||||
'livestock_collateral',
|
||||
'farmer_loan',
|
||||
'business_loan',
|
||||
'personal_loan'
|
||||
),
|
||||
allowNull: false,
|
||||
comment: '合同类型'
|
||||
},
|
||||
term: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '合同期限(月)'
|
||||
},
|
||||
interestRate: {
|
||||
type: DataTypes.DECIMAL(5, 2),
|
||||
allowNull: false,
|
||||
comment: '利率'
|
||||
},
|
||||
phone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
comment: '联系电话'
|
||||
},
|
||||
purpose: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '贷款用途'
|
||||
},
|
||||
remark: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '备注'
|
||||
},
|
||||
contractTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW,
|
||||
comment: '合同签订时间'
|
||||
},
|
||||
disbursementTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '放款时间'
|
||||
},
|
||||
maturityTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '到期时间'
|
||||
},
|
||||
completedTime: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
comment: '完成时间'
|
||||
},
|
||||
createdBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '创建人ID',
|
||||
references: {
|
||||
model: 'bank_users',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
updatedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '更新人ID',
|
||||
references: {
|
||||
model: 'bank_users',
|
||||
key: 'id'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
sequelize: require('../config/database').sequelize,
|
||||
modelName: 'LoanContract',
|
||||
tableName: 'bank_loan_contracts',
|
||||
timestamps: true,
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt',
|
||||
hooks: {
|
||||
beforeCreate: (contract) => {
|
||||
// 生成合同编号
|
||||
if (!contract.contractNumber) {
|
||||
const now = new Date();
|
||||
const timestamp = now.getFullYear().toString() +
|
||||
(now.getMonth() + 1).toString().padStart(2, '0') +
|
||||
now.getDate().toString().padStart(2, '0') +
|
||||
now.getHours().toString().padStart(2, '0') +
|
||||
now.getMinutes().toString().padStart(2, '0') +
|
||||
now.getSeconds().toString().padStart(2, '0');
|
||||
const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
|
||||
contract.contractNumber = 'HT' + timestamp + random;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = LoanContract;
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* 贷款产品模型
|
||||
* @file LoanProduct.js
|
||||
* @description 贷款产品数据模型
|
||||
*/
|
||||
const { DataTypes } = require('sequelize');
|
||||
const { sequelize } = require('../config/database');
|
||||
|
||||
@@ -10,84 +5,115 @@ const LoanProduct = sequelize.define('LoanProduct', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
autoIncrement: true,
|
||||
comment: '主键ID'
|
||||
},
|
||||
name: {
|
||||
productName: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: false,
|
||||
comment: '贷款产品名称'
|
||||
},
|
||||
loanAmount: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false,
|
||||
comment: '产品名称'
|
||||
comment: '贷款额度'
|
||||
},
|
||||
code: {
|
||||
type: DataTypes.STRING(50),
|
||||
loanTerm: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '产品代码'
|
||||
comment: '贷款周期(月)'
|
||||
},
|
||||
type: {
|
||||
type: DataTypes.ENUM('personal', 'business', 'mortgage', 'credit'),
|
||||
interestRate: {
|
||||
type: DataTypes.DECIMAL(5, 2),
|
||||
allowNull: false,
|
||||
comment: '产品类型:个人贷款、企业贷款、抵押贷款、信用贷款'
|
||||
comment: '贷款利率(%)'
|
||||
},
|
||||
description: {
|
||||
serviceArea: {
|
||||
type: DataTypes.STRING(200),
|
||||
allowNull: false,
|
||||
comment: '服务区域'
|
||||
},
|
||||
servicePhone: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
comment: '服务电话'
|
||||
},
|
||||
totalCustomers: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '服务客户总数量'
|
||||
},
|
||||
supervisionCustomers: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '监管中客户数量'
|
||||
},
|
||||
completedCustomers: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '已结项客户数量'
|
||||
},
|
||||
onSaleStatus: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true,
|
||||
comment: '在售状态'
|
||||
},
|
||||
productDescription: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '产品描述'
|
||||
},
|
||||
min_amount: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '最小贷款金额(分)'
|
||||
},
|
||||
max_amount: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '最大贷款金额(分)'
|
||||
},
|
||||
interest_rate: {
|
||||
type: DataTypes.DECIMAL(5, 4),
|
||||
allowNull: false,
|
||||
comment: '年化利率'
|
||||
},
|
||||
term_min: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '最短期限(月)'
|
||||
},
|
||||
term_max: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '最长期限(月)'
|
||||
},
|
||||
requirements: {
|
||||
type: DataTypes.JSON,
|
||||
applicationRequirements: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '申请要求(JSON格式)'
|
||||
comment: '申请条件'
|
||||
},
|
||||
status: {
|
||||
type: DataTypes.ENUM('draft', 'active', 'inactive'),
|
||||
allowNull: false,
|
||||
defaultValue: 'draft',
|
||||
comment: '产品状态:草稿、启用、停用'
|
||||
requiredDocuments: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '所需材料'
|
||||
},
|
||||
created_at: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW
|
||||
approvalProcess: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
comment: '审批流程'
|
||||
},
|
||||
updated_at: {
|
||||
type: DataTypes.DATE,
|
||||
riskLevel: {
|
||||
type: DataTypes.ENUM('LOW', 'MEDIUM', 'HIGH'),
|
||||
allowNull: false,
|
||||
defaultValue: DataTypes.NOW
|
||||
defaultValue: 'MEDIUM',
|
||||
comment: '风险等级'
|
||||
},
|
||||
minLoanAmount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: true,
|
||||
comment: '最小贷款金额'
|
||||
},
|
||||
maxLoanAmount: {
|
||||
type: DataTypes.DECIMAL(15, 2),
|
||||
allowNull: true,
|
||||
comment: '最大贷款金额'
|
||||
},
|
||||
createdBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
comment: '创建人ID'
|
||||
},
|
||||
updatedBy: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
comment: '更新人ID'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
tableName: 'bank_loan_products',
|
||||
modelName: 'LoanProduct',
|
||||
tableName: 'loan_products',
|
||||
timestamps: true,
|
||||
createdAt: 'created_at',
|
||||
updatedAt: 'updated_at'
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt',
|
||||
comment: '贷款商品表'
|
||||
});
|
||||
|
||||
module.exports = LoanProduct;
|
||||
module.exports = LoanProduct;
|
||||
@@ -15,7 +15,13 @@ class User extends BaseModel {
|
||||
* @returns {Promise<Boolean>} 验证结果
|
||||
*/
|
||||
async validPassword(password) {
|
||||
return await bcrypt.compare(password, this.password);
|
||||
try {
|
||||
const bcrypt = require('bcryptjs');
|
||||
return await bcrypt.compare(password, this.password);
|
||||
} catch (error) {
|
||||
console.error('密码验证错误:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,11 @@ const Position = require('./Position');
|
||||
const Report = require('./Report');
|
||||
const Project = require('./Project');
|
||||
const SupervisionTask = require('./SupervisionTask');
|
||||
const InstallationTask = require('./InstallationTask');
|
||||
const CompletedSupervision = require('./CompletedSupervision');
|
||||
const LoanApplication = require('./LoanApplication');
|
||||
const AuditRecord = require('./AuditRecord');
|
||||
const LoanContract = require('./LoanContract');
|
||||
|
||||
// 定义模型关联关系
|
||||
|
||||
@@ -141,6 +146,162 @@ User.hasMany(SupervisionTask, {
|
||||
as: 'updatedSupervisionTasks'
|
||||
});
|
||||
|
||||
// 待安装任务与用户关联(创建人)
|
||||
InstallationTask.belongsTo(User, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'creator',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(InstallationTask, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'createdInstallationTasks'
|
||||
});
|
||||
|
||||
// 待安装任务与用户关联(更新人)
|
||||
InstallationTask.belongsTo(User, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updater',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(InstallationTask, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updatedInstallationTasks'
|
||||
});
|
||||
|
||||
// 监管任务已结项与用户关联(创建人)
|
||||
CompletedSupervision.belongsTo(User, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'creator',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(CompletedSupervision, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'createdCompletedSupervisions'
|
||||
});
|
||||
|
||||
// 监管任务已结项与用户关联(更新人)
|
||||
CompletedSupervision.belongsTo(User, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updater',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(CompletedSupervision, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updatedCompletedSupervisions'
|
||||
});
|
||||
|
||||
// 贷款商品与用户关联(创建人)
|
||||
LoanProduct.belongsTo(User, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'creator',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanProduct, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'createdLoanProducts'
|
||||
});
|
||||
|
||||
// 贷款商品与用户关联(更新人)
|
||||
LoanProduct.belongsTo(User, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updater',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanProduct, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updatedLoanProducts'
|
||||
});
|
||||
|
||||
// 贷款申请与用户关联(申请人)
|
||||
LoanApplication.belongsTo(User, {
|
||||
foreignKey: 'applicantId',
|
||||
as: 'applicant',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanApplication, {
|
||||
foreignKey: 'applicantId',
|
||||
as: 'loanApplications'
|
||||
});
|
||||
|
||||
// 贷款申请与用户关联(审批人)
|
||||
LoanApplication.belongsTo(User, {
|
||||
foreignKey: 'approvedBy',
|
||||
as: 'approver',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanApplication, {
|
||||
foreignKey: 'approvedBy',
|
||||
as: 'approvedApplications'
|
||||
});
|
||||
|
||||
// 贷款申请与用户关联(拒绝人)
|
||||
LoanApplication.belongsTo(User, {
|
||||
foreignKey: 'rejectedBy',
|
||||
as: 'rejector',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanApplication, {
|
||||
foreignKey: 'rejectedBy',
|
||||
as: 'rejectedApplications'
|
||||
});
|
||||
|
||||
// 审核记录与贷款申请关联
|
||||
AuditRecord.belongsTo(LoanApplication, {
|
||||
foreignKey: 'applicationId',
|
||||
as: 'application',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
LoanApplication.hasMany(AuditRecord, {
|
||||
foreignKey: 'applicationId',
|
||||
as: 'auditRecords'
|
||||
});
|
||||
|
||||
// 审核记录与用户关联(审核人)
|
||||
AuditRecord.belongsTo(User, {
|
||||
foreignKey: 'auditorId',
|
||||
as: 'auditorUser',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(AuditRecord, {
|
||||
foreignKey: 'auditorId',
|
||||
as: 'auditRecords'
|
||||
});
|
||||
|
||||
// 贷款合同与用户关联(创建人)
|
||||
LoanContract.belongsTo(User, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'creator',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanContract, {
|
||||
foreignKey: 'createdBy',
|
||||
as: 'createdLoanContracts'
|
||||
});
|
||||
|
||||
// 贷款合同与用户关联(更新人)
|
||||
LoanContract.belongsTo(User, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updater',
|
||||
targetKey: 'id'
|
||||
});
|
||||
|
||||
User.hasMany(LoanContract, {
|
||||
foreignKey: 'updatedBy',
|
||||
as: 'updatedLoanContracts'
|
||||
});
|
||||
|
||||
// 导出所有模型和数据库实例
|
||||
module.exports = {
|
||||
sequelize,
|
||||
@@ -154,5 +315,10 @@ module.exports = {
|
||||
Position,
|
||||
Report,
|
||||
Project,
|
||||
SupervisionTask
|
||||
SupervisionTask,
|
||||
InstallationTask,
|
||||
CompletedSupervision,
|
||||
LoanApplication,
|
||||
AuditRecord,
|
||||
LoanContract
|
||||
};
|
||||
Reference in New Issue
Block a user