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 customers ORDER BY created_at DESC LIMIT 50 `); // 为每个客户获取联系人和收款信息 const customersWithDetails = await Promise.all( result.rows.map(async (customer) => { // 获取联系人信息 const contactsResult = await db.query( `SELECT * FROM contacts WHERE entity_id = $1 AND entity_type = 'customer' ORDER BY is_primary DESC`, [customer.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`, [customer.id] ); const paymentInfos = paymentInfosResult.rows.map(payment => ({ id: payment.id, account_name: payment.account_name, bank_account: payment.account_number, bank_name: payment.bank_name, qr_code: payment.qr_code, is_primary: payment.is_default === 1 })); return { ...customer, contacts: contacts.length > 0 ? contacts : [], payment_infos: paymentInfos.length > 0 ? paymentInfos : [] }; }) ); res.json({ success: true, data: customersWithDetails, count: customersWithDetails.length }); } catch (error) { console.error('获取客户失败:', error); res.status(500).json({ success: false, message: '获取客户失败', error: error.message }); } }); router.get('/:id', async (req, res) => { try { const { id } = req.params; // 获取客户基本信息 const customerResult = await db.query(` SELECT * FROM customers WHERE id = ? `, [id]); if (customerResult.rows.length > 0) { const customer = customerResult.rows[0]; // 获取客户的所有联系人 const contactsResult = await db.query(` SELECT * FROM contacts WHERE entity_id = ? AND entity_type = 'customer' 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 === 1 })); // 获取客户的所有收款信息 const paymentInfosResult = await db.query(` SELECT * FROM supplier_payment_infos WHERE supplier_id = ? ORDER BY is_default DESC `, [id]); // 转换收款信息数据结构 const payment_infos = paymentInfosResult.rows.map(info => ({ id: info.id, account_name: info.account_name || '', bank_name: info.bank_name || '', bank_account: info.account_number || '', qr_code: info.qr_code || '', is_primary: info.is_default === 1 })); const ledger = await LedgerService.getCustomerLedger(id); const formattedCustomer = { id: customer.id, code: `C${String(customer.id).padStart(4, '0')}`, name: customer.name, address: customer.address, contacts: contacts.length > 0 ? contacts : [], payment_infos: payment_infos.length > 0 ? payment_infos : [], remark: customer.remark || '', total_contract_amount: ledger.summary.total_contract_amount, total_received: ledger.summary.total_received_amount, total_receivable: ledger.summary.total_receivable_amount, ledger: ledger, created_at: customer.created_at }; res.json({ success: true, data: formattedCustomer }); } else { res.status(404).json({ success: false, message: '客户不存在' }); } } catch (error) { console.error('获取客户详情失败:', error); res.status(500).json({ success: false, message: '获取客户详情失败', error: error.message }); } }); router.post('/', async (req, res) => { try { const { name, address, remark, contacts, payment_infos } = req.body; // 从contacts中获取主联系人信息 const primaryContact = contacts?.find(c => c.is_primary) || contacts?.[0]; const contact = primaryContact?.name || ''; const position = primaryContact?.position || ''; const phone = primaryContact?.phone || ''; const email = ''; // 前端没有email字段 const result = await db.query( `INSERT INTO customers (name, address, contact, position, phone, email, remark, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [name, address, contact, position, phone, email, remark] ); const customerId = (result.rows[0]?.id || 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 (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [customerId, 'customer', contactItem.name, contactItem.position, contactItem.phone, contactItem.is_primary ? 1 : 0] ); } } // 插入收款信息数据 if (payment_infos && payment_infos.length > 0) { for (const paymentItem of payment_infos) { await db.query( `INSERT INTO supplier_payment_infos (supplier_id, account_name, bank_name, bank_account, qr_code, is_primary, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [customerId, paymentItem.account_name, paymentItem.bank_name, paymentItem.bank_account, paymentItem.qr_code, paymentItem.is_primary ? 1 : 0] ); } } res.json({ success: true, message: '客户创建成功', data: { id: customerId, code: `C${String(customerId).padStart(4, '0')}`, name, address, contacts: contacts || [], payment_infos: payment_infos || [], remark, total_contract_amount: 0, total_received: 0, total_receivable: 0, created_at: new Date().toISOString() } }); } catch (error) { console.error('创建客户失败:', error); res.status(500).json({ success: false, message: '创建客户失败', error: error.message }); } }); router.put('/:id', async (req, res) => { try { const { id } = req.params; const { name, address, remark, contacts, payment_infos } = req.body; // 从contacts中获取主联系人信息 const primaryContact = contacts?.find(c => c.is_primary) || contacts?.[0]; const contact = primaryContact?.name || ''; const position = primaryContact?.position || ''; const phone = primaryContact?.phone || ''; const email = ''; // 前端没有email字段 await db.query( `UPDATE customers SET name = ?, address = ?, contact = ?, position = ?, phone = ?, email = ?, remark = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, [name, address, contact, position, phone, email, remark, id] ); // 删除旧的联系人数据 await db.query(`DELETE FROM contacts WHERE entity_id = $1 AND entity_type = 'customer'`, [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 (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [id, 'customer', contactItem.name, contactItem.position, contactItem.phone, contactItem.is_primary ? 1 : 0] ); } } // 删除旧的收款信息数据 await db.query(`DELETE FROM supplier_payment_infos WHERE supplier_id = $1`, [id]); // 插入新的收款信息数据 if (payment_infos && payment_infos.length > 0) { for (const paymentItem of payment_infos) { await db.query( `INSERT INTO supplier_payment_infos (supplier_id, account_name, bank_name, bank_account, qr_code, is_primary, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`, [id, paymentItem.account_name, paymentItem.bank_name, paymentItem.bank_account, paymentItem.qr_code, paymentItem.is_primary ? 1 : 0] ); } } res.json({ success: true, message: '客户更新成功', data: { id, code: `C${String(id).padStart(4, '0')}`, name, address, contacts: contacts || [], payment_infos: payment_infos || [], remark, total_contract_amount: 0, total_received: 0, total_receivable: 0, created_at: new Date().toISOString() } }); } catch (error) { console.error('更新客户失败:', error); res.status(500).json({ success: false, message: '更新客户失败', error: 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 = 'customer'`, [id]); // 再删除客户数据 const result = await db.query(`DELETE FROM customers WHERE id = $1`, [id]); if (result.changes > 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: error.message }); } }); module.exports = router;