Files
nxxmdata/bank-backend/controllers/loanContractController.js

439 lines
11 KiB
JavaScript
Raw Normal View History

2025-09-24 17:49:32 +08:00
/**
* 贷款合同控制器
* @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') {
2025-09-25 15:53:44 +08:00
where.contract_number = { [Op.like]: `%${searchValue}%` };
} else if (searchField === 'customerName') {
where.customer_name = { [Op.like]: `%${searchValue}%` };
} else if (searchField === 'customerPhone') {
where.customer_phone = { [Op.like]: `%${searchValue}%` };
} else if (searchField === 'customerIdCard') {
where.customer_id_card = { [Op.like]: `%${searchValue}%` };
2025-09-24 17:49:32 +08:00
}
}
// 状态筛选
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,
order,
offset,
limit
});
// 格式化数据
const contracts = rows.map(contract => ({
id: contract.id,
2025-09-25 15:53:44 +08:00
contract_number: contract.contract_number,
customer_name: contract.customer_name,
customer_phone: contract.customer_phone,
customer_id_card: contract.customer_id_card,
loan_amount: parseFloat(contract.loan_amount),
loan_term: contract.loan_term,
interest_rate: parseFloat(contract.interest_rate),
contract_date: contract.contract_date,
2025-09-24 17:49:32 +08:00
status: contract.status,
2025-09-25 15:53:44 +08:00
created_at: contract.created_at,
updated_at: contract.updated_at
2025-09-24 17:49:32 +08:00
}));
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
};