/** * 贷款解押控制器 * @file loanReleaseController.js * @description 银行系统贷款解押相关接口控制器 */ const { LoanRelease, LoanReleaseHistory, User } = require('../models'); const { Op } = require('sequelize'); /** * 获取解押申请列表 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const getReleases = async (req, res) => { try { const { page = 1, pageSize = 10, searchField = 'application_number', searchValue = '', status = '', sortField = 'created_at', sortOrder = 'DESC' } = req.query; // 构建查询条件 const whereCondition = {}; // 搜索条件 if (searchValue) { switch (searchField) { case 'application_number': whereCondition.application_number = { [Op.like]: `%${searchValue}%` }; break; case 'customer_name': whereCondition[Op.or] = [ { customer_name: { [Op.like]: `%${searchValue}%` } }, { farmer_name: { [Op.like]: `%${searchValue}%` } } ]; break; case 'product_name': whereCondition.product_name = { [Op.like]: `%${searchValue}%` }; break; } } // 状态筛选 if (status) { whereCondition.status = status; } // 分页参数 const offset = (page - 1) * pageSize; const limit = parseInt(pageSize); // 查询数据 const { count, rows } = await LoanRelease.findAndCountAll({ where: whereCondition, order: [[sortField, sortOrder.toUpperCase()]], offset, limit, include: [ { model: User, as: 'processor', attributes: ['id', 'username', 'real_name'] } ] }); // 格式化返回数据 const releases = rows.map(release => ({ id: release.id, applicationNumber: release.application_number, productName: release.product_name || '养殖贷款', farmerName: release.farmer_name || release.customer_name, applicantName: release.customer_name, applicantIdNumber: release.customer_id_card, applicantPhone: release.customer_phone, assetType: release.collateral_type === 'livestock' ? '牛' : '其他', releaseQuantity: release.release_quantity || '1头', releaseAmount: parseFloat(release.release_amount), status: release.status, applicationTime: release.application_date, processTime: release.process_date, completeTime: release.complete_date, processorName: release.processor?.real_name || release.processor_name, processComment: release.process_comment, rejectionReason: release.rejection_reason, remark: release.remark, created_at: release.created_at, updated_at: release.updated_at })); res.json({ success: true, data: { releases, pagination: { current: parseInt(page), pageSize: limit, total: count, totalPages: Math.ceil(count / limit) } } }); } catch (error) { console.error('获取解押申请列表失败:', error); res.status(500).json({ success: false, message: '获取解押申请列表失败' }); } }; /** * 获取解押申请详情 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const getReleaseDetail = async (req, res) => { try { const { id } = req.params; const release = await LoanRelease.findByPk(id, { include: [ { model: User, as: 'processor', attributes: ['id', 'username', 'real_name'] } ] }); if (!release) { return res.status(404).json({ success: false, message: '解押申请不存在' }); } // 获取历史记录 const history = await LoanReleaseHistory.findAll({ where: { release_id: id }, order: [['operation_time', 'ASC']] }); const releaseDetail = { id: release.id, releaseNumber: release.application_number, customerName: release.customer_name, contractNumber: `CONTRACT-${String(release.contract_id || release.id).padStart(6, '0')}`, status: release.status, collateralType: release.collateral_type, collateralDescription: release.collateral_description, loanAmount: parseFloat(release.loan_amount || 0), collateralValue: parseFloat(release.collateral_value || 0), applicationTime: release.application_date, processTime: release.process_date, completeTime: release.complete_date, phone: release.customer_phone, idCard: release.customer_id_card, reason: release.application_reason, remark: release.remark, history: history.map(h => ({ id: h.id, action: h.action, operator: h.operator, time: h.operation_time, comment: h.comment })) }; res.json({ success: true, data: releaseDetail }); } catch (error) { console.error('获取解押申请详情失败:', error); res.status(500).json({ success: false, message: '获取解押申请详情失败' }); } }; /** * 创建解押申请 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const createRelease = async (req, res) => { try { const { contract_id, customer_name, customer_phone, customer_id_card, farmer_name, product_name, collateral_type, collateral_description, collateral_value, loan_amount, release_amount, release_quantity, application_reason, remark } = req.body; // 生成申请单号 const applicationNumber = `REL-${Date.now()}`; const release = await LoanRelease.create({ application_number: applicationNumber, contract_id, customer_name, customer_phone, customer_id_card, farmer_name, product_name, collateral_type, collateral_description, collateral_value, loan_amount, release_amount, release_quantity, application_reason, remark, status: 'pending' }); // 创建历史记录 await LoanReleaseHistory.create({ release_id: release.id, action: 'apply', operator: customer_name, comment: '提交解押申请' }); res.status(201).json({ success: true, message: '解押申请创建成功', data: { id: release.id, applicationNumber: release.application_number } }); } catch (error) { console.error('创建解押申请失败:', error); res.status(500).json({ success: false, message: '创建解押申请失败' }); } }; /** * 更新解押申请 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const updateRelease = async (req, res) => { try { const { id } = req.params; const updateData = req.body; const release = await LoanRelease.findByPk(id); if (!release) { return res.status(404).json({ success: false, message: '解押申请不存在' }); } // 更新数据 await release.update(updateData); res.json({ success: true, message: '解押申请更新成功' }); } catch (error) { console.error('更新解押申请失败:', error); res.status(500).json({ success: false, message: '更新解押申请失败' }); } }; /** * 处理解押申请 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const processRelease = async (req, res) => { try { const { id } = req.params; const { action, comment, remark } = req.body; if (!req.user || !req.user.userId) { return res.status(401).json({ success: false, message: '用户信息无效' }); } const release = await LoanRelease.findByPk(id); if (!release) { return res.status(404).json({ success: false, message: '解押申请不存在' }); } if (release.status !== 'pending') { return res.status(400).json({ success: false, message: '该申请已完成处理,无法重复操作' }); } const previousStatus = release.status; let newStatus = release.status; // 根据处理动作更新状态 if (action === 'approve') { newStatus = 'approved'; } else if (action === 'reject') { newStatus = 'rejected'; } // 更新申请状态 release.status = newStatus; release.process_date = new Date(); release.processor_id = req.user.userId; release.processor_name = req.user.username; release.process_comment = comment; release.remark = remark; if (action === 'reject') { release.rejection_reason = comment; } await release.save(); // 创建历史记录 await LoanReleaseHistory.create({ release_id: release.id, action: action, operator: req.user.username, operator_id: req.user.userId, comment: comment, previous_status: previousStatus, new_status: newStatus }); res.json({ success: true, message: `解押申请已${action === 'approve' ? '通过' : '拒绝'}`, data: { id: release.id, status: newStatus, action, comment } }); } catch (error) { console.error('处理解押申请失败:', error); res.status(500).json({ success: false, message: '处理解押申请失败' }); } }; /** * 完成解押 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const completeRelease = async (req, res) => { try { const { id } = req.params; const { comment } = req.body; if (!req.user || !req.user.userId) { return res.status(401).json({ success: false, message: '用户信息无效' }); } const release = await LoanRelease.findByPk(id); if (!release) { return res.status(404).json({ success: false, message: '解押申请不存在' }); } if (release.status !== 'approved') { return res.status(400).json({ success: false, message: '只有已通过的解押申请才能完成解押' }); } const previousStatus = release.status; // 更新状态为已完成 release.status = 'completed'; release.complete_date = new Date(); await release.save(); // 创建历史记录 await LoanReleaseHistory.create({ release_id: release.id, action: 'complete', operator: req.user.username, operator_id: req.user.userId, comment: comment || '解押手续办理完成', previous_status: previousStatus, new_status: 'completed' }); res.json({ success: true, message: '解押完成', data: { id: release.id, status: 'completed' } }); } catch (error) { console.error('完成解押失败:', error); res.status(500).json({ success: false, message: '完成解押失败' }); } }; /** * 删除解押申请 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const deleteRelease = async (req, res) => { try { const { id } = req.params; const release = await LoanRelease.findByPk(id); if (!release) { return res.status(404).json({ success: false, message: '解押申请不存在' }); } // 只有待处理状态的申请才能删除 if (release.status !== 'pending') { return res.status(400).json({ success: false, message: '只有待处理状态的申请才能删除' }); } await release.destroy(); res.json({ success: true, message: '解押申请删除成功' }); } catch (error) { console.error('删除解押申请失败:', error); res.status(500).json({ success: false, message: '删除解押申请失败' }); } }; /** * 获取解押统计信息 * @param {Object} req - 请求对象 * @param {Object} res - 响应对象 */ const getReleaseStats = async (req, res) => { try { const stats = await LoanRelease.findAll({ attributes: [ 'status', [require('sequelize').fn('COUNT', '*'), 'count'] ], group: ['status'] }); const totalCount = await LoanRelease.count(); const pendingCount = await LoanRelease.count({ where: { status: 'pending' } }); const processingCount = await LoanRelease.count({ where: { status: 'processing' } }); const completedCount = await LoanRelease.count({ where: { status: 'completed' } }); res.json({ success: true, data: { total: totalCount, pending: pendingCount, processing: processingCount, completed: completedCount, statusStats: stats } }); } catch (error) { console.error('获取解押统计信息失败:', error); res.status(500).json({ success: false, message: '获取解押统计信息失败' }); } }; module.exports = { getReleases, getReleaseDetail, createRelease, updateRelease, processRelease, completeRelease, deleteRelease, getReleaseStats };