const { BillPayment, Bill } = require('../models'); const { Op } = require('sequelize'); const response = require('../utils/response'); // 获取账单的所有支付流水 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']] }); response.success(res, '获取成功', payments); } catch (error) { console.error('获取支付流水失败:', error); response.serverError(res, '获取支付流水失败', error); } }; // 创建支付流水(收款) 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 response.notFound(res, '账单不存在'); } if (bill.status === 'paid') { return response.badRequest(res, '该账单已收清,无法继续收款'); } if (bill.status === 'cancelled') { return response.badRequest(res, '该账单已取消,无法收款'); } // 计算剩余应收金额 const receivableAmount = parseFloat(bill.receivableAmount); const currentReceived = parseFloat(bill.receivedAmount || 0); const remainingAmount = receivableAmount - currentReceived; // 验证支付金额 const paymentAmount = parseFloat(amount); if (paymentAmount <= 0) { return response.badRequest(res, '支付金额必须大于0'); } if (paymentAmount > remainingAmount) { return response.badRequest(res, `支付金额不能超过剩余应收金额 ¥${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 }); response.created(res, '收款成功', { payment, bill: { id: bill.id, receivedAmount: newReceivedAmount, status: newStatus } }); } catch (error) { console.error('创建支付流水失败:', error); response.serverError(res, '创建支付流水失败', error); } }; // 删除支付流水(退款/撤销) 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 response.notFound(res, '支付流水不存在'); } // 查找关联账单 const bill = await Bill.findOne({ where: { id: payment.billId, tenantId, isDeleted: 0 } }); if (!bill) { return response.notFound(res, '关联账单不存在'); } // 软删除支付流水 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 }); response.success(res, '支付流水已删除,账单状态已更新', { bill: { id: bill.id, receivedAmount: newReceivedAmount, status: newStatus } }); } catch (error) { console.error('删除支付流水失败:', error); response.serverError(res, '删除支付流水失败', error); } }; // 获取支付流水统计 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'] }); response.success(res, '获取成功', payments); } catch (error) { console.error('获取支付统计失败:', error); response.serverError(res, '获取支付统计失败', error); } }; module.exports = { getPaymentsByBillId, createPayment, deletePayment, getPaymentStatistics };