rentease-backend-new/controllers/billPaymentController.js

212 lines
5.5 KiB
JavaScript

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
};