/** * 贷款申请控制器 * @file loanApplicationController.js * @description 银行系统贷款申请相关API控制器 */ const { LoanApplication, AuditRecord, User } = require('../models'); const { Op } = require('sequelize'); const { validationResult } = require('express-validator'); /** * 获取贷款申请列表 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const getApplications = async (req, res) => { try { const { page = 1, pageSize = 10, searchField = 'applicationNumber', searchValue = '', status = '', sortField = 'createdAt', sortOrder = 'DESC' } = req.query; // 构建查询条件 const where = {}; // 搜索条件 if (searchValue) { 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}%` }; } } // 状态筛选 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 LoanApplication.findAndCountAll({ where, order, offset, limit }); // 格式化数据 const applications = rows.map(app => ({ id: app.id, customer_name: app.customer_name, customer_phone: app.customer_phone, customer_id_card: app.customer_id_card, loan_amount: parseFloat(app.loan_amount), loan_term: app.loan_term, interest_rate: parseFloat(app.interest_rate), application_date: app.application_date, status: app.status, created_at: app.created_at, updated_at: app.updated_at })); res.json({ success: true, data: { applications, 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 getApplicationById = async (req, res) => { try { const { id } = req.params; const application = await LoanApplication.findByPk(id, { include: [ { model: User, as: 'applicant', attributes: ['id', 'username', 'real_name', 'email', 'phone'] }, { model: User, as: 'approver', attributes: ['id', 'username', 'real_name'] }, { model: User, as: 'rejector', attributes: ['id', 'username', 'real_name'] }, { model: AuditRecord, as: 'auditRecords', include: [ { model: User, as: 'auditorUser', attributes: ['id', 'username', 'real_name'] } ], order: [['auditTime', 'DESC']] } ] }); if (!application) { return res.status(404).json({ success: false, message: '贷款申请不存在' }); } // 格式化数据 const formattedApplication = { id: application.id, applicationNumber: application.applicationNumber, productName: application.productName, farmerName: application.farmerName, borrowerName: application.borrowerName, borrowerIdNumber: application.borrowerIdNumber, assetType: application.assetType, applicationQuantity: application.applicationQuantity, amount: parseFloat(application.amount), status: application.status, type: application.type, term: application.term, interestRate: parseFloat(application.interestRate), phone: application.phone, purpose: application.purpose, remark: application.remark, applicationTime: application.applicationTime, approvedTime: application.approvedTime, rejectedTime: application.rejectedTime, applicant: application.applicant, approver: application.approver, rejector: application.rejector, auditRecords: application.auditRecords.map(record => ({ id: record.id, action: record.action, auditor: record.auditorUser?.real_name || record.auditor, auditorId: record.auditorId, comment: record.comment, time: record.auditTime, previousStatus: record.previousStatus, newStatus: record.newStatus })) }; res.json({ success: true, data: formattedApplication }); } catch (error) { console.error('获取贷款申请详情失败:', error); res.status(500).json({ success: false, message: '获取贷款申请详情失败' }); } }; /** * 审核贷款申请 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const auditApplication = 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 { action, comment } = req.body; const userId = req.user?.id; // 获取申请信息 const application = await LoanApplication.findByPk(id); if (!application) { return res.status(404).json({ success: false, message: '贷款申请不存在' }); } // 检查申请状态 if (application.status === 'approved' || application.status === 'rejected') { return res.status(400).json({ success: false, message: '该申请已完成审核,无法重复操作' }); } const previousStatus = application.status; let newStatus = application.status; // 根据审核动作更新状态 if (action === 'approve') { newStatus = 'approved'; application.approvedTime = new Date(); application.approvedBy = userId; } else if (action === 'reject') { newStatus = 'rejected'; application.rejectedTime = new Date(); application.rejectedBy = userId; application.rejectionReason = comment; } // 更新申请状态 application.status = newStatus; await application.save(); // 创建审核记录 await AuditRecord.create({ applicationId: id, action, auditor: req.user?.real_name || req.user?.username || '系统', auditorId: userId, comment, auditTime: new Date(), previousStatus, newStatus }); res.json({ success: true, message: action === 'approve' ? '审核通过' : '审核拒绝', data: { id: application.id, status: newStatus, action, comment } }); } catch (error) { console.error('审核贷款申请失败:', error); res.status(500).json({ success: false, message: '审核贷款申请失败' }); } }; /** * 获取申请统计信息 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const getApplicationStats = async (req, res) => { try { const stats = await LoanApplication.findAll({ attributes: [ 'status', [LoanApplication.sequelize.fn('COUNT', '*'), 'count'], [LoanApplication.sequelize.fn('SUM', LoanApplication.sequelize.col('amount')), 'totalAmount'] ], group: ['status'], raw: true }); const totalApplications = await LoanApplication.count(); const totalAmount = await LoanApplication.sum('amount') || 0; const statusStats = { pending_review: 0, verification_pending: 0, pending_binding: 0, approved: 0, rejected: 0 }; const amountStats = { pending_review: 0, verification_pending: 0, pending_binding: 0, approved: 0, rejected: 0 }; stats.forEach(stat => { statusStats[stat.status] = parseInt(stat.count); amountStats[stat.status] = parseFloat(stat.totalAmount) || 0; }); res.json({ success: true, data: { total: { applications: totalApplications, amount: parseFloat(totalAmount) }, byStatus: { counts: statusStats, amounts: amountStats } } }); } 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 [updatedCount] = await LoanApplication.update( { status, ...(status === 'approved' && { approvedTime: new Date(), approvedBy: userId }), ...(status === 'rejected' && { rejectedTime: new Date(), rejectedBy: userId }) }, { where: { id: { [Op.in]: ids } } } ); // 为每个申请创建审核记录 for (const id of ids) { await AuditRecord.create({ applicationId: id, action: status === 'approved' ? 'approve' : 'reject', auditor: req.user?.real_name || req.user?.username || '系统', auditorId: userId, comment: `批量${status === 'approved' ? '通过' : '拒绝'}`, auditTime: new Date(), newStatus: status }); } res.json({ success: true, message: `成功更新${updatedCount}个申请的状态`, data: { updatedCount, status } }); } catch (error) { console.error('批量更新申请状态失败:', error); res.status(500).json({ success: false, message: '批量更新申请状态失败' }); } }; module.exports = { getApplications, getApplicationById, auditApplication, getApplicationStats, batchUpdateStatus };