const { BillPayment, Bill } = require('../models'); const { Op } = require('sequelize'); // 获取账单的所有支付流水 const getPaymentsByBillId = async (req, res) => { try { const { billId } = req.params; const tenantId = req.user.tenantId; const payments = await BillPayment.findAll({ where: { billId, tenantId, isDeleted: 0 }, order: [['paymentTime', 'DESC']] }); res.status(200).json({ code: 200, data: payments, message: 'success' }); } catch (error) { console.error('获取支付流水失败:', error); res.status(500).json({ code: 500, error: error.message }); } }; // 创建支付流水(收款) const createPayment = async (req, res) => { try { const { billId } = req.params; const { amount, paymentMethod, paymentTime, transactionNo, remark } = req.body; const tenantId = req.user.tenantId; const createBy = req.user.id; // 查找账单 const bill = await Bill.findOne({ where: { id: billId, tenantId, isDeleted: 0 } }); if (!bill) { return res.status(404).json({ code: 404, error: '账单不存在' }); } if (bill.status === 'paid') { return res.status(400).json({ code: 400, error: '该账单已收清,无法继续收款' }); } if (bill.status === 'cancelled') { return res.status(400).json({ code: 400, error: '该账单已取消,无法收款' }); } // 计算剩余应收金额 const receivableAmount = parseFloat(bill.receivableAmount); const currentReceived = parseFloat(bill.receivedAmount || 0); const remainingAmount = receivableAmount - currentReceived; // 验证支付金额 const paymentAmount = parseFloat(amount); if (paymentAmount <= 0) { return res.status(400).json({ code: 400, error: '支付金额必须大于0' }); } if (paymentAmount > remainingAmount) { return res.status(400).json({ code: 400, error: `支付金额不能超过剩余应收金额 ¥${remainingAmount.toFixed(2)}` }); } // 创建支付流水 const payment = await BillPayment.create({ billId, amount: paymentAmount, paymentMethod, paymentTime: paymentTime || new Date(), transactionNo: transactionNo || null, remark: remark || null, tenantId, createBy, isDeleted: 0 }); // 更新账单的已收金额和状态 const newReceivedAmount = currentReceived + paymentAmount; let newStatus = bill.status; if (newReceivedAmount >= receivableAmount) { newStatus = 'paid'; } else if (newReceivedAmount > 0) { newStatus = 'partial'; } await bill.update({ receivedAmount: newReceivedAmount, status: newStatus, updateBy: createBy }); res.status(201).json({ code: 201, data: { payment, bill: { id: bill.id, receivedAmount: newReceivedAmount, status: newStatus } }, message: '收款成功' }); } catch (error) { console.error('创建支付流水失败:', error); res.status(500).json({ code: 500, error: error.message }); } }; // 删除支付流水(退款/撤销) const deletePayment = async (req, res) => { try { const { id } = req.params; const tenantId = req.user.tenantId; const updateBy = req.user.id; const payment = await BillPayment.findOne({ where: { id, tenantId, isDeleted: 0 } }); if (!payment) { return res.status(404).json({ code: 404, error: '支付流水不存在' }); } // 查找关联账单 const bill = await Bill.findOne({ where: { id: payment.billId, tenantId, isDeleted: 0 } }); if (!bill) { return res.status(404).json({ code: 404, error: '关联账单不存在' }); } // 软删除支付流水 await payment.update({ isDeleted: 1 }); // 重新计算账单的已收金额和状态 const remainingPayments = await BillPayment.findAll({ where: { billId: bill.id, tenantId, isDeleted: 0 } }); const newReceivedAmount = remainingPayments.reduce((sum, p) => { return sum + parseFloat(p.amount); }, 0); let newStatus = 'unpaid'; if (newReceivedAmount >= parseFloat(bill.receivableAmount)) { newStatus = 'paid'; } else if (newReceivedAmount > 0) { newStatus = 'partial'; } await bill.update({ receivedAmount: newReceivedAmount, status: newStatus, updateBy }); res.status(200).json({ code: 200, data: { bill: { id: bill.id, receivedAmount: newReceivedAmount, status: newStatus } }, message: '支付流水已删除,账单状态已更新' }); } catch (error) { console.error('删除支付流水失败:', error); res.status(500).json({ code: 500, error: error.message }); } }; // 获取支付流水统计 const getPaymentStatistics = async (req, res) => { try { const tenantId = req.user.tenantId; const { startDate, endDate } = req.query; const where = { tenantId, isDeleted: 0 }; if (startDate && endDate) { where.paymentTime = { [Op.between]: [new Date(startDate), new Date(endDate)] }; } const payments = await BillPayment.findAll({ where, attributes: ['paymentMethod', [sequelize.fn('SUM', sequelize.col('amount')), 'totalAmount'], [sequelize.fn('COUNT', sequelize.col('id')), 'count']], group: ['paymentMethod'] }); res.status(200).json({ code: 200, data: payments, message: 'success' }); } catch (error) { console.error('获取支付统计失败:', error); res.status(500).json({ code: 500, error: error.message }); } }; module.exports = { getPaymentsByBillId, createPayment, deletePayment, getPaymentStatistics };