const express = require('express'); const router = express.Router(); const db = require('./db'); // 获取所有付款节点 router.get('/payment-nodes', async (req, res) => { try { const result = await db.query(` SELECT pn.*, pr.project_name, pr.project_code FROM payment_nodes pn LEFT JOIN projects pr ON pn.project_id = pr.project_id ORDER BY pn.due_date ASC `); res.json({ success: true, data: result.rows, count: result.rows.length }); } catch (error) { console.error('获取付款节点失败:', error); res.status(500).json({ success: false, message: '获取付款节点失败', error: error.message }); } }); // 获取单个付款节点 router.get('/payment-nodes/:id', async (req, res) => { try { const { id } = req.params; const result = await db.query(` SELECT pn.*, pr.project_name, pr.project_code FROM payment_nodes pn LEFT JOIN projects pr ON pn.project_id = pr.project_id WHERE pn.node_id = $1 `, [id]); if (result.rows.length === 0) { return res.status(404).json({ success: false, message: '付款节点不存在' }); } res.json({ success: true, data: result.rows[0] }); } catch (error) { console.error('获取付款节点失败:', error); res.status(500).json({ success: false, message: '获取付款节点失败', error: error.message }); } }); // 创建付款节点 router.post('/payment-nodes', async (req, res) => { try { const { project_id, node_type, node_name, node_name_zh, node_name_th, node_name_en, amount, currency, due_date, status, notes } = req.body; const result = await db.query(` INSERT INTO payment_nodes ( project_id, node_type, node_name, node_name_zh, node_name_th, node_name_en, amount, currency, due_date, status, notes ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING * `, [ project_id, node_type, node_name, node_name_zh, node_name_th, node_name_en, amount, currency, due_date, status || 'pending', notes ]); res.status(201).json({ success: true, message: '付款节点创建成功', data: result.rows[0] }); } catch (error) { console.error('创建付款节点失败:', error); res.status(500).json({ success: false, message: '创建付款节点失败', error: error.message }); } }); // 更新付款节点 router.put('/payment-nodes/:id', async (req, res) => { try { const { id } = req.params; const { node_type, node_name, node_name_zh, node_name_th, node_name_en, amount, currency, due_date, status, notes } = req.body; const result = await db.query(` UPDATE payment_nodes SET node_type = COALESCE($1, node_type), node_name = COALESCE($2, node_name), node_name_zh = COALESCE($3, node_name_zh), node_name_th = COALESCE($4, node_name_th), node_name_en = COALESCE($5, node_name_en), amount = COALESCE($6, amount), currency = COALESCE($7, currency), due_date = COALESCE($8, due_date), status = COALESCE($9, status), notes = COALESCE($10, notes), updated_at = CURRENT_TIMESTAMP WHERE node_id = $11 RETURNING * `, [ node_type, node_name, node_name_zh, node_name_th, node_name_en, amount, currency, due_date, status, notes, id ]); if (result.rows.length === 0) { return res.status(404).json({ success: false, message: '付款节点不存在' }); } res.json({ success: true, message: '付款节点更新成功', data: result.rows[0] }); } catch (error) { console.error('更新付款节点失败:', error); res.status(500).json({ success: false, message: '更新付款节点失败', error: error.message }); } }); // 删除付款节点 router.delete('/payment-nodes/:id', async (req, res) => { try { const { id } = req.params; const result = await db.query( 'DELETE FROM payment_nodes WHERE node_id = $1 RETURNING *', [id] ); if (result.rows.length === 0) { return res.status(404).json({ success: false, message: '付款节点不存在' }); } res.json({ success: true, message: '付款节点删除成功' }); } catch (error) { console.error('删除付款节点失败:', error); res.status(500).json({ success: false, message: '删除付款节点失败', error: error.message }); } }); // 获取付款记录 router.get('/payment-records', async (req, res) => { try { const { node_id, record_type, start_date, end_date } = req.query; let query = ` SELECT pr.*, pn.node_name, pn.project_id, proj.project_name FROM payment_records pr LEFT JOIN payment_nodes pn ON pr.node_id = pn.node_id LEFT JOIN projects proj ON pn.project_id = proj.project_id WHERE 1=1 `; const params = []; let paramIndex = 1; if (node_id) { query += ` AND pr.node_id = $${paramIndex}`; params.push(node_id); paramIndex++; } if (record_type) { query += ` AND pr.record_type = $${paramIndex}`; params.push(record_type); paramIndex++; } if (start_date) { query += ` AND pr.payment_date >= $${paramIndex}`; params.push(start_date); paramIndex++; } if (end_date) { query += ` AND pr.payment_date <= $${paramIndex}`; params.push(end_date); paramIndex++; } query += ` ORDER BY pr.payment_date DESC, pr.created_at DESC`; const result = await db.query(query, params); res.json({ success: true, data: result.rows, count: result.rows.length }); } catch (error) { console.error('获取付款记录失败:', error); res.status(500).json({ success: false, message: '获取付款记录失败', error: error.message }); } }); // 创建付款记录 router.post('/payment-records', async (req, res) => { try { const { node_id, record_type, amount, currency, exchange_rate, payment_date, payment_method, reference_number, status, notes } = req.body; const result = await db.query(` INSERT INTO payment_records ( node_id, record_type, amount, currency, exchange_rate, payment_date, payment_method, reference_number, status, notes ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING * `, [ node_id, record_type, amount, currency, exchange_rate || 1.0, payment_date, payment_method, reference_number, status || 'completed', notes ]); // 如果是付款记录,更新付款节点状态 if (record_type === 'payment') { await db.query(` UPDATE payment_nodes SET status = 'paid', updated_at = CURRENT_TIMESTAMP WHERE node_id = $1 `, [node_id]); } res.status(201).json({ success: true, message: '付款记录创建成功', data: result.rows[0] }); } catch (error) { console.error('创建付款记录失败:', error); res.status(500).json({ success: false, message: '创建付款记录失败', error: error.message }); } }); // 获取汇率 router.get('/exchange-rates', async (req, res) => { try { const { from_currency, to_currency, effective_date } = req.query; let query = 'SELECT * FROM exchange_rates WHERE 1=1'; const params = []; let paramIndex = 1; if (from_currency) { query += ` AND from_currency = $${paramIndex}`; params.push(from_currency); paramIndex++; } if (to_currency) { query += ` AND to_currency = $${paramIndex}`; params.push(to_currency); paramIndex++; } if (effective_date) { query += ` AND effective_date = $${paramIndex}`; params.push(effective_date); paramIndex++; } query += ` ORDER BY effective_date DESC, created_at DESC`; const result = await db.query(query, params); res.json({ success: true, data: result.rows, count: result.rows.length }); } catch (error) { console.error('获取汇率失败:', error); res.status(500).json({ success: false, message: '获取汇率失败', error: error.message }); } }); // 创建/更新汇率 router.post('/exchange-rates', async (req, res) => { try { const { from_currency, to_currency, rate, effective_date } = req.body; // 检查是否已存在 const checkResult = await db.query(` SELECT * FROM exchange_rates WHERE from_currency = $1 AND to_currency = $2 AND effective_date = $3 `, [from_currency, to_currency, effective_date]); let result; if (checkResult.rows.length > 0) { // 更新 result = await db.query(` UPDATE exchange_rates SET rate = $1, updated_at = CURRENT_TIMESTAMP WHERE from_currency = $2 AND to_currency = $3 AND effective_date = $4 RETURNING * `, [rate, from_currency, to_currency, effective_date]); } else { // 创建 result = await db.query(` INSERT INTO exchange_rates (from_currency, to_currency, rate, effective_date) VALUES ($1, $2, $3, $4) RETURNING * `, [from_currency, to_currency, rate, effective_date]); } res.status(201).json({ success: true, message: '汇率保存成功', data: result.rows[0] }); } catch (error) { console.error('保存汇率失败:', error); res.status(500).json({ success: false, message: '保存汇率失败', error: error.message }); } }); // 财务统计 router.get('/finance-stats', async (req, res) => { try { // 付款节点统计 const nodesStats = await db.query(` SELECT COUNT(*) as total_nodes, COUNT(CASE WHEN status = 'pending' THEN 1 END) as pending_nodes, COUNT(CASE WHEN status = 'paid' THEN 1 END) as paid_nodes, COUNT(CASE WHEN status = 'overdue' THEN 1 END) as overdue_nodes, SUM(amount) as total_amount, SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) as pending_amount, SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) as paid_amount FROM payment_nodes `); // 付款记录统计 const recordsStats = await db.query(` SELECT COUNT(*) as total_records, COUNT(CASE WHEN record_type = 'payment' THEN 1 END) as payment_count, COUNT(CASE WHEN record_type = 'receipt' THEN 1 END) as receipt_count, SUM(CASE WHEN record_type = 'payment' THEN amount ELSE 0 END) as total_payments, SUM(CASE WHEN record_type = 'receipt' THEN amount ELSE 0 END) as total_receipts FROM payment_records `); // 货币分布 const currencyStats = await db.query(` SELECT currency, COUNT(*) as node_count, SUM(amount) as total_amount FROM payment_nodes GROUP BY currency ORDER BY total_amount DESC `); res.json({ success: true, data: { nodes: nodesStats.rows[0], records: recordsStats.rows[0], currencies: currencyStats.rows, summary: { net_cash_flow: (recordsStats.rows[0]?.total_receipts || 0) - (recordsStats.rows[0]?.total_payments || 0), outstanding_amount: nodesStats.rows[0]?.pending_amount || 0 } } }); } catch (error) { console.error('获取财务统计失败:', error); res.status(500).json({ success: false, message: '获取财务统计失败', error: error.message }); } }); module.exports = router;