添加银行端后端接口
This commit is contained in:
466
bank-backend/controllers/loanContractController.js
Normal file
466
bank-backend/controllers/loanContractController.js
Normal file
@@ -0,0 +1,466 @@
|
||||
/**
|
||||
* 贷款合同控制器
|
||||
* @file loanContractController.js
|
||||
* @description 银行系统贷款合同相关API控制器
|
||||
*/
|
||||
const { LoanContract, User } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const { validationResult } = require('express-validator');
|
||||
|
||||
/**
|
||||
* 获取贷款合同列表
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const getContracts = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
page = 1,
|
||||
pageSize = 10,
|
||||
searchField = 'contractNumber',
|
||||
searchValue = '',
|
||||
status = '',
|
||||
sortField = 'createdAt',
|
||||
sortOrder = 'DESC'
|
||||
} = req.query;
|
||||
|
||||
// 构建查询条件
|
||||
const where = {};
|
||||
|
||||
// 搜索条件
|
||||
if (searchValue) {
|
||||
if (searchField === 'contractNumber') {
|
||||
where.contractNumber = { [Op.like]: `%${searchValue}%` };
|
||||
} else if (searchField === 'applicationNumber') {
|
||||
where.applicationNumber = { [Op.like]: `%${searchValue}%` };
|
||||
} else if (searchField === 'borrowerName') {
|
||||
where.borrowerName = { [Op.like]: `%${searchValue}%` };
|
||||
} else if (searchField === 'farmerName') {
|
||||
where.farmerName = { [Op.like]: `%${searchValue}%` };
|
||||
} else if (searchField === 'productName') {
|
||||
where.productName = { [Op.like]: `%${searchValue}%` };
|
||||
}
|
||||
}
|
||||
|
||||
// 状态筛选
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
|
||||
// 分页参数
|
||||
const offset = (parseInt(page) - 1) * parseInt(pageSize);
|
||||
const limit = parseInt(pageSize);
|
||||
|
||||
// 排序参数
|
||||
const order = [[sortField, sortOrder.toUpperCase()]];
|
||||
|
||||
// 查询数据
|
||||
const { count, rows } = await LoanContract.findAndCountAll({
|
||||
where,
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'creator',
|
||||
attributes: ['id', 'username', 'real_name']
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: 'updater',
|
||||
attributes: ['id', 'username', 'real_name']
|
||||
}
|
||||
],
|
||||
order,
|
||||
offset,
|
||||
limit
|
||||
});
|
||||
|
||||
// 格式化数据
|
||||
const contracts = rows.map(contract => ({
|
||||
id: contract.id,
|
||||
contractNumber: contract.contractNumber,
|
||||
applicationNumber: contract.applicationNumber,
|
||||
productName: contract.productName,
|
||||
farmerName: contract.farmerName,
|
||||
borrowerName: contract.borrowerName,
|
||||
borrowerIdNumber: contract.borrowerIdNumber,
|
||||
assetType: contract.assetType,
|
||||
applicationQuantity: contract.applicationQuantity,
|
||||
amount: parseFloat(contract.amount),
|
||||
paidAmount: parseFloat(contract.paidAmount),
|
||||
status: contract.status,
|
||||
type: contract.type,
|
||||
term: contract.term,
|
||||
interestRate: parseFloat(contract.interestRate),
|
||||
phone: contract.phone,
|
||||
purpose: contract.purpose,
|
||||
remark: contract.remark,
|
||||
contractTime: contract.contractTime,
|
||||
disbursementTime: contract.disbursementTime,
|
||||
maturityTime: contract.maturityTime,
|
||||
completedTime: contract.completedTime,
|
||||
remainingAmount: parseFloat(contract.amount - contract.paidAmount),
|
||||
repaymentProgress: contract.getRepaymentProgress(),
|
||||
creator: contract.creator,
|
||||
updater: contract.updater
|
||||
}));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
contracts,
|
||||
pagination: {
|
||||
current: parseInt(page),
|
||||
pageSize: parseInt(pageSize),
|
||||
total: count,
|
||||
totalPages: Math.ceil(count / parseInt(pageSize))
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取贷款合同列表失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取贷款合同列表失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取贷款合同详情
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const getContractById = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const contract = await LoanContract.findByPk(id, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'creator',
|
||||
attributes: ['id', 'username', 'real_name', 'email', 'phone']
|
||||
},
|
||||
{
|
||||
model: User,
|
||||
as: 'updater',
|
||||
attributes: ['id', 'username', 'real_name']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (!contract) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: '贷款合同不存在'
|
||||
});
|
||||
}
|
||||
|
||||
// 格式化数据
|
||||
const formattedContract = {
|
||||
id: contract.id,
|
||||
contractNumber: contract.contractNumber,
|
||||
applicationNumber: contract.applicationNumber,
|
||||
productName: contract.productName,
|
||||
farmerName: contract.farmerName,
|
||||
borrowerName: contract.borrowerName,
|
||||
borrowerIdNumber: contract.borrowerIdNumber,
|
||||
assetType: contract.assetType,
|
||||
applicationQuantity: contract.applicationQuantity,
|
||||
amount: parseFloat(contract.amount),
|
||||
paidAmount: parseFloat(contract.paidAmount),
|
||||
status: contract.status,
|
||||
type: contract.type,
|
||||
term: contract.term,
|
||||
interestRate: parseFloat(contract.interestRate),
|
||||
phone: contract.phone,
|
||||
purpose: contract.purpose,
|
||||
remark: contract.remark,
|
||||
contractTime: contract.contractTime,
|
||||
disbursementTime: contract.disbursementTime,
|
||||
maturityTime: contract.maturityTime,
|
||||
completedTime: contract.completedTime,
|
||||
remainingAmount: parseFloat(contract.amount - contract.paidAmount),
|
||||
repaymentProgress: contract.getRepaymentProgress(),
|
||||
creator: contract.creator,
|
||||
updater: contract.updater
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: formattedContract
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取贷款合同详情失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取贷款合同详情失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建贷款合同
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const createContract = async (req, res) => {
|
||||
try {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '请求参数错误',
|
||||
errors: errors.array()
|
||||
});
|
||||
}
|
||||
|
||||
const contractData = {
|
||||
...req.body,
|
||||
createdBy: req.user?.id
|
||||
};
|
||||
|
||||
const contract = await LoanContract.create(contractData);
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: '贷款合同创建成功',
|
||||
data: contract
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建贷款合同失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '创建贷款合同失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新贷款合同
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const updateContract = async (req, res) => {
|
||||
try {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '请求参数错误',
|
||||
errors: errors.array()
|
||||
});
|
||||
}
|
||||
|
||||
const { id } = req.params;
|
||||
const updateData = {
|
||||
...req.body,
|
||||
updatedBy: req.user?.id
|
||||
};
|
||||
|
||||
const [updatedCount] = await LoanContract.update(updateData, {
|
||||
where: { id }
|
||||
});
|
||||
|
||||
if (updatedCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: '贷款合同不存在'
|
||||
});
|
||||
}
|
||||
|
||||
const updatedContract = await LoanContract.findByPk(id);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: '贷款合同更新成功',
|
||||
data: updatedContract
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('更新贷款合同失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '更新贷款合同失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除贷款合同
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const deleteContract = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const deletedCount = await LoanContract.destroy({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
if (deletedCount === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: '贷款合同不存在'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: '贷款合同删除成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除贷款合同失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '删除贷款合同失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取合同统计信息
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const getContractStats = async (req, res) => {
|
||||
try {
|
||||
const stats = await LoanContract.findAll({
|
||||
attributes: [
|
||||
'status',
|
||||
[LoanContract.sequelize.fn('COUNT', '*'), 'count'],
|
||||
[LoanContract.sequelize.fn('SUM', LoanContract.sequelize.col('amount')), 'totalAmount'],
|
||||
[LoanContract.sequelize.fn('SUM', LoanContract.sequelize.col('paidAmount')), 'totalPaidAmount']
|
||||
],
|
||||
group: ['status'],
|
||||
raw: true
|
||||
});
|
||||
|
||||
const totalContracts = await LoanContract.count();
|
||||
const totalAmount = await LoanContract.sum('amount') || 0;
|
||||
const totalPaidAmount = await LoanContract.sum('paidAmount') || 0;
|
||||
|
||||
const statusStats = {
|
||||
active: 0,
|
||||
pending: 0,
|
||||
completed: 0,
|
||||
defaulted: 0,
|
||||
cancelled: 0
|
||||
};
|
||||
|
||||
const amountStats = {
|
||||
active: 0,
|
||||
pending: 0,
|
||||
completed: 0,
|
||||
defaulted: 0,
|
||||
cancelled: 0
|
||||
};
|
||||
|
||||
const paidAmountStats = {
|
||||
active: 0,
|
||||
pending: 0,
|
||||
completed: 0,
|
||||
defaulted: 0,
|
||||
cancelled: 0
|
||||
};
|
||||
|
||||
stats.forEach(stat => {
|
||||
statusStats[stat.status] = parseInt(stat.count);
|
||||
amountStats[stat.status] = parseFloat(stat.totalAmount) || 0;
|
||||
paidAmountStats[stat.status] = parseFloat(stat.totalPaidAmount) || 0;
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
total: {
|
||||
contracts: totalContracts,
|
||||
amount: parseFloat(totalAmount),
|
||||
paidAmount: parseFloat(totalPaidAmount),
|
||||
remainingAmount: parseFloat(totalAmount - totalPaidAmount)
|
||||
},
|
||||
byStatus: {
|
||||
counts: statusStats,
|
||||
amounts: amountStats,
|
||||
paidAmounts: paidAmountStats
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取合同统计失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '获取合同统计失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量更新合同状态
|
||||
* @param {Object} req - 请求对象
|
||||
* @param {Object} res - 响应对象
|
||||
*/
|
||||
const batchUpdateStatus = async (req, res) => {
|
||||
try {
|
||||
const { ids, status } = req.body;
|
||||
const userId = req.user?.id;
|
||||
|
||||
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '请选择要操作的合同'
|
||||
});
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '请指定目标状态'
|
||||
});
|
||||
}
|
||||
|
||||
// 更新合同状态
|
||||
const updateData = {
|
||||
status,
|
||||
updatedBy: userId
|
||||
};
|
||||
|
||||
// 根据状态设置相应的时间字段
|
||||
if (status === 'active') {
|
||||
updateData.disbursementTime = new Date();
|
||||
} else if (status === 'completed') {
|
||||
updateData.completedTime = new Date();
|
||||
}
|
||||
|
||||
const [updatedCount] = await LoanContract.update(updateData, {
|
||||
where: {
|
||||
id: { [Op.in]: ids }
|
||||
}
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `成功更新${updatedCount}个合同的状态`,
|
||||
data: {
|
||||
updatedCount,
|
||||
status
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('批量更新合同状态失败:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '批量更新合同状态失败'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getContracts,
|
||||
getContractById,
|
||||
createContract,
|
||||
updateContract,
|
||||
deleteContract,
|
||||
getContractStats,
|
||||
batchUpdateStatus
|
||||
};
|
||||
Reference in New Issue
Block a user