const express = require('express'); const db = require('../db'); const { authenticate, requireAdmin } = require('../middleware/auth'); const LedgerService = require('../services/ledgerService'); const router = express.Router(); router.get('/', async (req, res) => { try { const result = await db.query(` SELECT * FROM suppliers ORDER BY created_at DESC LIMIT 50 `); // 为每个供应商获取联系人和收款信息 const suppliersWithDetails = await Promise.all( result.rows.map(async (supplier) => { // 获取联系人信息 const contactsResult = await db.query( `SELECT * FROM contacts WHERE entity_id = $1 AND entity_type = 'supplier' ORDER BY is_primary DESC`, [supplier.id] ); const contacts = contactsResult.rows.map(contact => ({ name: contact.name || '未命名', position: contact.position || '', phone: contact.phone || '', is_primary: contact.is_primary === 1 })); // 获取收款信息 const paymentInfosResult = await db.query( `SELECT * FROM supplier_payment_infos WHERE supplier_id = $1 ORDER BY is_default DESC`, [supplier.id] ); const paymentInfos = paymentInfosResult.rows.map(payment => ({ id: payment.id, account_name: payment.account_name, bank_account: payment.bank_account, bank_name: payment.bank_name, qr_code: payment.qr_code, is_primary: payment.is_default === true })); return { ...supplier, supply_category: supplier.product_category, country: supplier.supplier_source, remark: supplier.remark || '', contacts: contacts.length > 0 ? contacts : [], payment_infos: paymentInfos.length > 0 ? paymentInfos : [] }; }) ); res.json({ success: true, data: suppliersWithDetails, count: suppliersWithDetails.length }); } catch (error) { console.error('获取供应商失败:', error); res.status(500).json({ success: false, message: '获取供应商失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.get('/:id', async (req, res) => { try { const { id } = req.params; // 获取供应商基本信息 const supplierResult = await db.query(` SELECT * FROM suppliers WHERE id = $1 `, [id]); if (supplierResult.rows.length > 0) { const supplier = supplierResult.rows[0]; // 获取供应商的所有联系人 const contactsResult = await db.query(` SELECT * FROM contacts WHERE entity_id = $1 AND entity_type = 'supplier' ORDER BY is_primary DESC `, [id]); // 转换联系人数据结构 const contacts = contactsResult.rows.map(contact => ({ name: contact.name || '未命名', position: contact.position || '', phone: contact.phone || '', is_primary: contact.is_primary === true })); // 获取供应商的所有收款信息 const paymentInfosResult = await db.query(` SELECT * FROM supplier_payment_infos WHERE supplier_id = $1 ORDER BY is_default DESC `, [id]); // 转换收款信息数据结构 const paymentInfos = paymentInfosResult.rows.map(payment => ({ id: payment.id, account_name: payment.account_name, bank_account: payment.bank_account, bank_name: payment.bank_name, qr_code: payment.qr_code, is_primary: payment.is_default === true })); const ledger = await LedgerService.getSupplierLedger(id); const formattedSupplier = { id: supplier.id, code: `S${String(supplier.id).padStart(4, '0')}`, name: supplier.name || '未命名', supply_category: supplier.product_category || '电力设备', country: supplier.supplier_source || 'Laos', contacts: contacts.length > 0 ? contacts : [], payment_infos: paymentInfos.length > 0 ? paymentInfos : [], remark: supplier.remark || '', total_purchase_amount: ledger.summary.total_order_amount, total_paid: ledger.summary.total_paid_amount, total_payable: ledger.summary.total_unpaid_amount, ledger: ledger, created_at: supplier.created_at }; // 设置响应头确保UTF-8编码 res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.json({ success: true, data: formattedSupplier }); } else { res.status(404).json({ success: false, message: '供应商不存在' }); } } catch (error) { console.error('获取供应商详情失败:', error); res.status(500).json({ success: false, message: '获取供应商详情失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.post('/', async (req, res) => { try { const { name, supply_category, country, remark, contacts, payment_infos } = req.body; // 从contacts中获取主联系人信息 const primaryContact = contacts?.find(c => c.is_primary) || contacts?.[0]; const contact_person = primaryContact?.name || ''; const phone = primaryContact?.phone || ''; const email = ''; // 前端没有email字段 const address = ''; // 前端没有address字段 const result = await db.query( `INSERT INTO suppliers (name, address, contact_person, phone, email, product_category, supplier_source, remark, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) RETURNING id`, [name, address, contact_person, phone, email, supply_category, country, remark || ''] ); const supplierId = result.rows[0]?.id; // 插入联系人数据 if (contacts && contacts.length > 0) { for (const contactItem of contacts) { await db.query( `INSERT INTO contacts (entity_id, entity_type, name, position, phone, is_primary, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [supplierId, 'supplier', contactItem.name, contactItem.position, contactItem.phone, contactItem.is_primary ? true : false] ); } } // 插入收款信息数据 if (payment_infos && payment_infos.length > 0) { for (const paymentInfo of payment_infos) { await db.query( `INSERT INTO supplier_payment_infos (supplier_id, account_name, bank_account, bank_name, qr_code, is_primary, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [supplierId, paymentInfo.account_name, paymentInfo.bank_account, paymentInfo.bank_name, paymentInfo.qr_code, paymentInfo.is_primary ? true : false] ); } } res.json({ success: true, message: '供应商创建成功', data: { id: supplierId, code: `S${String(supplierId).padStart(4, '0')}`, name, supply_category, country, contacts: contacts || [], payment_infos: payment_infos || [], remark, total_purchase_amount: 0, total_paid: 0, total_payable: 0, created_at: new Date().toISOString() } }); } catch (error) { console.error('创建供应商失败:', error); res.status(500).json({ success: false, message: '创建供应商失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.put('/:id', async (req, res) => { try { const { id } = req.params; const { name, supply_category, country, remark, contacts, payment_infos } = req.body; // 从contacts中获取主联系人信息 const primaryContact = contacts?.find(c => c.is_primary) || contacts?.[0]; const contact_person = primaryContact?.name || ''; const phone = primaryContact?.phone || ''; const email = ''; // 前端没有email字段 const address = ''; // 前端没有address字段 await db.query( `UPDATE suppliers SET name = $1, address = $2, contact_person = $3, phone = $4, email = $5, product_category = $6, supplier_source = $7, remark = $8, updated_at = CURRENT_TIMESTAMP WHERE id = $9`, [name, address, contact_person, phone, email, supply_category, country, remark || '', id] ); // 删除旧的联系人数据 await db.query(`DELETE FROM contacts WHERE entity_id = $1 AND entity_type = 'supplier'`, [id]); // 插入新的联系人数据 if (contacts && contacts.length > 0) { for (const contactItem of contacts) { await db.query( `INSERT INTO contacts (entity_id, entity_type, name, position, phone, is_primary, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [id, 'supplier', contactItem.name, contactItem.position, contactItem.phone, contactItem.is_primary ? true : false] ); } } // 删除旧的收款信息数据 await db.query(`DELETE FROM supplier_payment_infos WHERE supplier_id = $1`, [id]); // 插入新的收款信息数据 if (payment_infos && payment_infos.length > 0) { for (const paymentInfo of payment_infos) { await db.query( `INSERT INTO supplier_payment_infos (supplier_id, account_name, bank_account, bank_name, qr_code, is_primary, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [id, paymentInfo.account_name, paymentInfo.bank_account, paymentInfo.bank_name, paymentInfo.qr_code, paymentInfo.is_primary ? true : false] ); } } res.json({ success: true, message: '供应商更新成功', data: { id, code: `S${String(id).padStart(4, '0')}`, name, supply_category, country, contacts: contacts || [], payment_infos: payment_infos || [], remark, total_purchase_amount: 0, total_paid: 0, total_payable: 0, created_at: new Date().toISOString() } }); } catch (error) { console.error('更新供应商失败:', error); res.status(500).json({ success: false, message: '更新供应商失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.delete('/:id', async (req, res) => { try { const { id } = req.params; // 先删除关联的联系人数据 await db.query(`DELETE FROM contacts WHERE entity_id = $1 AND entity_type = 'supplier'`, [id]); // 再删除供应商数据 const result = await db.query(`DELETE FROM suppliers WHERE id = $1`, [id]); if (result.rowCount > 0) { res.json({ success: true, message: '供应商删除成功' }); } else { res.status(404).json({ success: false, message: '供应商不存在' }); } } catch (error) { console.error('删除供应商失败:', error); res.status(500).json({ success: false, message: '删除供应商失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.get('/:id/orders', async (req, res) => { try { const { id } = req.params; const ordersResult = await db.query(` SELECT po.id, po.code, po.project_id, po.total_amount, po.paid_amount, (po.total_amount - po.paid_amount) as unpaid_amount, po.order_date, po.status, po.currency, p.name as project_name FROM purchase_orders po LEFT JOIN projects p ON po.project_id = p.id WHERE po.supplier_id = ? ORDER BY po.order_date DESC `, [id]); res.json({ success: true, data: ordersResult.rows }); } catch (error) { console.error('获取供应商订单列表失败:', error); res.status(500).json({ success: false, message: '获取供应商订单列表失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); router.get('/:id/ledger', async (req, res) => { try { const { id } = req.params; const summaryResult = await db.query(` SELECT COUNT(*) as order_count, COALESCE(SUM(total_amount), 0) as total_amount, COALESCE(SUM(paid_amount), 0) as paid_amount, COALESCE(SUM(total_amount - paid_amount), 0) as unpaid_amount FROM purchase_orders WHERE supplier_id = ? `, [id]); const ordersResult = await db.query(` SELECT po.id, po.code, po.project_id, po.total_amount, po.paid_amount, (po.total_amount - po.paid_amount) as unpaid_amount, po.order_date, po.status, po.currency, p.name as project_name FROM purchase_orders po LEFT JOIN projects p ON po.project_id = p.id WHERE po.supplier_id = ? ORDER BY po.order_date DESC `, [id]); const summary = summaryResult.rows[0] || { order_count: 0, total_amount: 0, paid_amount: 0, unpaid_amount: 0 }; res.json({ success: true, data: { summary: { order_count: summary.order_count || 0, total_amount: summary.total_amount || 0, paid_amount: summary.paid_amount || 0, unpaid_amount: summary.unpaid_amount || 0 }, orders: ordersResult.rows } }); } catch (error) { console.error('获取供应商台账失败:', error); res.status(500).json({ success: false, message: '获取供应商台账失败', error: process.env.NODE_ENV === 'development' ? error.message : '操作失败' }); } }); module.exports = router;