const express = require('express'); const router = express.Router(); const Joi = require('joi'); // 模拟财务数据 let settlements = [ { id: 1, orderId: 1, settlementCode: 'SET001', supplierName: '山东优质牲畜合作社', buyerName: '北京肉类加工有限公司', cattleCount: 50, unitPrice: 25000, totalAmount: 1250000, paymentMethod: 'bank_transfer', paymentStatus: 'paid', settlementDate: '2024-01-20', paymentDate: '2024-01-22', invoiceNumber: 'INV001', invoiceStatus: 'issued', taxAmount: 125000, actualPayment: 1125000, bankAccount: '1234567890123456789', bankName: '中国农业银行', createdAt: new Date('2024-01-20'), updatedAt: new Date('2024-01-22') }, { id: 2, orderId: 2, settlementCode: 'SET002', supplierName: '内蒙古草原牲畜有限公司', buyerName: '天津屠宰加工厂', cattleCount: 80, unitPrice: 24000, totalAmount: 1920000, paymentMethod: 'cash', paymentStatus: 'pending', settlementDate: '2024-01-25', paymentDate: null, invoiceNumber: 'INV002', invoiceStatus: 'pending', taxAmount: 192000, actualPayment: 1728000, bankAccount: '9876543210987654321', bankName: '中国建设银行', createdAt: new Date('2024-01-25'), updatedAt: new Date('2024-01-25') } ]; let payments = [ { id: 1, settlementId: 1, paymentCode: 'PAY001', amount: 1125000, paymentMethod: 'bank_transfer', status: 'success', transactionId: 'TXN20240122001', paidAt: '2024-01-22T10:30:00Z', createdAt: new Date('2024-01-22T10:30:00Z') } ]; // 验证schemas const settlementCreateSchema = Joi.object({ orderId: Joi.number().integer().required(), cattleCount: Joi.number().integer().min(1).required(), unitPrice: Joi.number().min(0).required(), paymentMethod: Joi.string().valid('bank_transfer', 'cash', 'check', 'online').required(), settlementDate: Joi.date().iso().required(), invoiceNumber: Joi.string().min(3).max(50) }); const paymentCreateSchema = Joi.object({ settlementId: Joi.number().integer().required(), amount: Joi.number().min(0).required(), paymentMethod: Joi.string().valid('bank_transfer', 'cash', 'check', 'online').required(), transactionId: Joi.string().max(100) }); // 获取结算列表 router.get('/settlements', (req, res) => { try { const { page = 1, pageSize = 20, keyword, paymentStatus, startDate, endDate } = req.query; let filteredSettlements = [...settlements]; // 关键词搜索 if (keyword) { filteredSettlements = filteredSettlements.filter(settlement => settlement.settlementCode.includes(keyword) || settlement.supplierName.includes(keyword) || settlement.buyerName.includes(keyword) ); } // 支付状态筛选 if (paymentStatus) { filteredSettlements = filteredSettlements.filter(settlement => settlement.paymentStatus === paymentStatus); } // 时间范围筛选 if (startDate) { filteredSettlements = filteredSettlements.filter(settlement => new Date(settlement.settlementDate) >= new Date(startDate) ); } if (endDate) { filteredSettlements = filteredSettlements.filter(settlement => new Date(settlement.settlementDate) <= new Date(endDate) ); } // 分页处理 const startIndex = (page - 1) * pageSize; const endIndex = startIndex + parseInt(pageSize); const paginatedSettlements = filteredSettlements.slice(startIndex, endIndex); res.json({ success: true, data: { list: paginatedSettlements, pagination: { page: parseInt(page), pageSize: parseInt(pageSize), total: filteredSettlements.length, totalPages: Math.ceil(filteredSettlements.length / pageSize) } } }); } catch (error) { res.status(500).json({ success: false, message: '获取结算列表失败', error: error.message }); } }); // 获取结算详情 router.get('/settlements/:id', (req, res) => { try { const { id } = req.params; const settlement = settlements.find(s => s.id === parseInt(id)); if (!settlement) { return res.status(404).json({ success: false, message: '结算记录不存在' }); } // 获取相关支付记录 const relatedPayments = payments.filter(p => p.settlementId === settlement.id); res.json({ success: true, data: { ...settlement, payments: relatedPayments } }); } catch (error) { res.status(500).json({ success: false, message: '获取结算详情失败', error: error.message }); } }); // 创建结算记录 router.post('/settlements', (req, res) => { try { const { error, value } = settlementCreateSchema.validate(req.body); if (error) { return res.status(400).json({ success: false, message: '参数验证失败', errors: error.details.map(detail => detail.message) }); } const settlementCode = `SET${String(Date.now()).slice(-6)}`; const totalAmount = value.cattleCount * value.unitPrice; const taxAmount = totalAmount * 0.1; // 假设税率10% const actualPayment = totalAmount - taxAmount; const newSettlement = { id: Math.max(...settlements.map(s => s.id)) + 1, ...value, settlementCode, totalAmount, taxAmount, actualPayment, paymentStatus: 'pending', paymentDate: null, invoiceStatus: 'pending', supplierName: '供应商名称', // 实际应从订单获取 buyerName: '采购商名称', // 实际应从订单获取 bankAccount: '', bankName: '', createdAt: new Date(), updatedAt: new Date() }; settlements.push(newSettlement); res.status(201).json({ success: true, message: '结算记录创建成功', data: newSettlement }); } catch (error) { res.status(500).json({ success: false, message: '创建结算记录失败', error: error.message }); } }); // 更新结算状态 router.put('/settlements/:id/status', (req, res) => { try { const { id } = req.params; const { paymentStatus, invoiceStatus } = req.body; const settlementIndex = settlements.findIndex(s => s.id === parseInt(id)); if (settlementIndex === -1) { return res.status(404).json({ success: false, message: '结算记录不存在' }); } if (paymentStatus) { settlements[settlementIndex].paymentStatus = paymentStatus; if (paymentStatus === 'paid') { settlements[settlementIndex].paymentDate = new Date().toISOString().split('T')[0]; } } if (invoiceStatus) { settlements[settlementIndex].invoiceStatus = invoiceStatus; } settlements[settlementIndex].updatedAt = new Date(); res.json({ success: true, message: '结算状态更新成功', data: settlements[settlementIndex] }); } catch (error) { res.status(500).json({ success: false, message: '更新结算状态失败', error: error.message }); } }); // 获取支付记录列表 router.get('/payments', (req, res) => { try { const { page = 1, pageSize = 20, settlementId, status } = req.query; let filteredPayments = [...payments]; // 按结算单筛选 if (settlementId) { filteredPayments = filteredPayments.filter(payment => payment.settlementId === parseInt(settlementId)); } // 按状态筛选 if (status) { filteredPayments = filteredPayments.filter(payment => payment.status === status); } // 分页处理 const startIndex = (page - 1) * pageSize; const endIndex = startIndex + parseInt(pageSize); const paginatedPayments = filteredPayments.slice(startIndex, endIndex); res.json({ success: true, data: { list: paginatedPayments, pagination: { page: parseInt(page), pageSize: parseInt(pageSize), total: filteredPayments.length, totalPages: Math.ceil(filteredPayments.length / pageSize) } } }); } catch (error) { res.status(500).json({ success: false, message: '获取支付记录失败', error: error.message }); } }); // 创建支付记录 router.post('/payments', (req, res) => { try { const { error, value } = paymentCreateSchema.validate(req.body); if (error) { return res.status(400).json({ success: false, message: '参数验证失败', errors: error.details.map(detail => detail.message) }); } const paymentCode = `PAY${String(Date.now()).slice(-6)}`; const newPayment = { id: Math.max(...payments.map(p => p.id)) + 1, ...value, paymentCode, status: 'processing', paidAt: null, createdAt: new Date() }; payments.push(newPayment); // 模拟支付处理 setTimeout(() => { const paymentIndex = payments.findIndex(p => p.id === newPayment.id); if (paymentIndex !== -1) { payments[paymentIndex].status = 'success'; payments[paymentIndex].paidAt = new Date().toISOString(); payments[paymentIndex].transactionId = `TXN${Date.now()}`; // 更新对应结算单状态 const settlementIndex = settlements.findIndex(s => s.id === value.settlementId); if (settlementIndex !== -1) { settlements[settlementIndex].paymentStatus = 'paid'; settlements[settlementIndex].paymentDate = new Date().toISOString().split('T')[0]; settlements[settlementIndex].updatedAt = new Date(); } } }, 3000); // 3秒后处理完成 res.status(201).json({ success: true, message: '支付申请已提交', data: newPayment }); } catch (error) { res.status(500).json({ success: false, message: '创建支付记录失败', error: error.message }); } }); // 获取财务统计 router.get('/stats/overview', (req, res) => { try { const totalSettlements = settlements.length; const paidCount = settlements.filter(s => s.paymentStatus === 'paid').length; const pendingCount = settlements.filter(s => s.paymentStatus === 'pending').length; const totalAmount = settlements.reduce((sum, s) => sum + s.totalAmount, 0); const paidAmount = settlements .filter(s => s.paymentStatus === 'paid') .reduce((sum, s) => sum + s.actualPayment, 0); const pendingAmount = settlements .filter(s => s.paymentStatus === 'pending') .reduce((sum, s) => sum + s.actualPayment, 0); const totalTaxAmount = settlements.reduce((sum, s) => sum + s.taxAmount, 0); // 本月统计 const currentMonth = new Date().getMonth(); const currentYear = new Date().getFullYear(); const monthlySettlements = settlements.filter(s => { const settleDate = new Date(s.settlementDate); return settleDate.getMonth() === currentMonth && settleDate.getFullYear() === currentYear; }); const monthlyAmount = monthlySettlements.reduce((sum, s) => sum + s.totalAmount, 0); res.json({ success: true, data: { totalSettlements, paidCount, pendingCount, totalAmount, paidAmount, pendingAmount, totalTaxAmount, monthlyAmount, paymentRate: totalSettlements > 0 ? Math.round((paidCount / totalSettlements) * 100) : 0 } }); } catch (error) { res.status(500).json({ success: false, message: '获取财务统计失败', error: error.message }); } }); // 获取财务报表 router.get('/reports/monthly', (req, res) => { try { const { year = new Date().getFullYear(), month } = req.query; let targetSettlements = settlements; // 筛选指定年份 targetSettlements = targetSettlements.filter(s => { const settleDate = new Date(s.settlementDate); return settleDate.getFullYear() === parseInt(year); }); // 如果指定了月份,进一步筛选 if (month) { targetSettlements = targetSettlements.filter(s => { const settleDate = new Date(s.settlementDate); return settleDate.getMonth() === parseInt(month) - 1; }); } // 按月份分组统计 const monthlyStats = {}; for (let i = 1; i <= 12; i++) { monthlyStats[i] = { month: i, settlementCount: 0, totalAmount: 0, paidAmount: 0, pendingAmount: 0 }; } targetSettlements.forEach(settlement => { const settleMonth = new Date(settlement.settlementDate).getMonth() + 1; monthlyStats[settleMonth].settlementCount++; monthlyStats[settleMonth].totalAmount += settlement.totalAmount; if (settlement.paymentStatus === 'paid') { monthlyStats[settleMonth].paidAmount += settlement.actualPayment; } else { monthlyStats[settleMonth].pendingAmount += settlement.actualPayment; } }); res.json({ success: true, data: { year: parseInt(year), monthlyStats: Object.values(monthlyStats) } }); } catch (error) { res.status(500).json({ success: false, message: '获取财务报表失败', error: error.message }); } }); module.exports = router;