Files
yunhaifinance/backend/services/ledgerService.js
T

188 lines
7.6 KiB
JavaScript
Raw Normal View History

/**
* 业务台账服务
* 为合作伙伴提供统一的业务台账数据
*/
const db = require('../db');
class LedgerService {
static async getSubcontractorLedger(subcontractorId) {
try {
const projectsResult = await db.query(`
SELECT p.id, p.code as project_code, p.name, p.contract_amount, p.status
FROM projects p
WHERE p.subcontractor_id = ?
ORDER BY p.created_at DESC
`, [subcontractorId]);
const projects = projectsResult.rows;
const totalContract = projects.reduce((sum, p) => sum + (parseFloat(p.contract_amount) || 0), 0);
let totalPaid = 0;
try {
const paymentsResult = await db.query(`
SELECT COALESCE(SUM(amount), 0) as paid_amount
FROM payment_requests
WHERE payee_type = 'subcontractor' AND payee_id = ? AND status = 'paid'
`, [subcontractorId]);
totalPaid = parseFloat(paymentsResult.rows[0]?.paid_amount) || 0;
} catch (e) { /* payment_requests may not have payee_type column */ }
return {
summary: {
item_count: projects.length,
total_contract_amount: totalContract,
total_paid_amount: totalPaid,
total_unpaid_amount: totalContract - totalPaid
},
items: projects.map(p => ({
id: p.id, type: 'project', code: p.project_code, name: p.name,
contract_amount: parseFloat(p.contract_amount) || 0,
paid_amount: 0, unpaid_amount: parseFloat(p.contract_amount) || 0,
status: p.status
}))
};
} catch (error) {
console.error('获取分包商台账失败:', error);
return { summary: { item_count: 0, total_contract_amount: 0, total_paid_amount: 0, total_unpaid_amount: 0 }, items: [] };
}
}
static async getCustomerLedger(customerId) {
try {
const projectsResult = await db.query(`
SELECT p.id, p.code as project_code, p.name, p.contract_amount, p.status
FROM projects p
WHERE p.customer_id = ?
ORDER BY p.created_at DESC
`, [customerId]);
const projects = projectsResult.rows;
const totalContract = projects.reduce((sum, p) => sum + (parseFloat(p.contract_amount) || 0), 0);
let totalReceived = 0;
try {
const receiptsResult = await db.query(`
SELECT COALESCE(SUM(amount), 0) as received_amount
FROM payment_records
WHERE customer_id = ? AND type = 'income'
`, [customerId]);
totalReceived = parseFloat(receiptsResult.rows[0]?.received_amount) || 0;
} catch (e) { /* ignore */ }
return {
summary: {
item_count: projects.length,
total_contract_amount: totalContract,
total_received_amount: totalReceived,
total_receivable_amount: totalContract - totalReceived
},
items: projects.map(p => ({
id: p.id, type: 'project', code: p.project_code, name: p.name,
contract_amount: parseFloat(p.contract_amount) || 0,
received_amount: 0, receivable_amount: parseFloat(p.contract_amount) || 0,
status: p.status
}))
};
} catch (error) {
console.error('获取客户台账失败:', error);
return { summary: { item_count: 0, total_contract_amount: 0, total_received_amount: 0, total_receivable_amount: 0 }, items: [] };
}
}
static async getSupplierLedger(supplierId) {
try {
const ordersResult = await db.query(`
SELECT po.id, po.code, po.total_amount, po.status, po.created_at,
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.created_at DESC
`, [supplierId]);
const orders = ordersResult.rows;
const totalAmount = orders.reduce((sum, o) => sum + (parseFloat(o.total_amount) || 0), 0);
let totalPaid = 0;
try {
const paymentsResult = await db.query(`
SELECT COALESCE(SUM(pp.actual_amount), 0) as paid_amount
FROM payment_plans pp
JOIN purchase_orders po ON pp.purchase_order_id = po.id
WHERE po.supplier_id = ? AND pp.status = 'paid'
`, [supplierId]);
totalPaid = parseFloat(paymentsResult.rows[0]?.paid_amount) || 0;
} catch (e) { /* ignore */ }
return {
summary: {
item_count: orders.length,
total_order_amount: totalAmount,
total_paid_amount: totalPaid,
total_unpaid_amount: totalAmount - totalPaid
},
items: orders.map(o => ({
id: o.id, type: 'purchase_order', code: o.code, name: o.project_name || o.code,
order_amount: parseFloat(o.total_amount) || 0,
paid_amount: 0, unpaid_amount: parseFloat(o.total_amount) || 0,
status: o.status, date: o.created_at
}))
};
} catch (error) {
console.error('获取供应商台账失败:', error);
return { summary: { item_count: 0, total_order_amount: 0, total_paid_amount: 0, total_unpaid_amount: 0 }, items: [] };
}
}
static async getLogisticsCompanyLedger(companyId) {
try {
const ordersResult = await db.query(`
SELECT lr.id, lr.code, lr.ship_date, lr.status,
lr.primary_freight, lr.primary_freight_currency, lr.primary_freight_status,
lr.secondary_freight, lr.secondary_freight_currency, lr.secondary_freight_status,
po.code as order_code, p.name as project_name
FROM logistics_records lr
LEFT JOIN purchase_orders po ON lr.purchase_order_id = po.id
LEFT JOIN projects p ON po.project_id = p.id
WHERE lr.logistics_company_id = ?
ORDER BY lr.created_at DESC
`, [companyId]);
const orders = ordersResult.rows;
const totalPrimary = orders.reduce((sum, o) => sum + (parseFloat(o.primary_freight) || 0), 0);
const totalSecondary = orders.reduce((sum, o) => sum + (parseFloat(o.secondary_freight) || 0), 0);
const paidPrimary = orders.filter(o => o.primary_freight_status === 'paid').reduce((sum, o) => sum + (parseFloat(o.primary_freight) || 0), 0);
const paidSecondary = orders.filter(o => o.secondary_freight_status === 'paid').reduce((sum, o) => sum + (parseFloat(o.secondary_freight) || 0), 0);
return {
summary: {
item_count: orders.length,
total_primary_freight: totalPrimary,
total_secondary_freight: totalSecondary,
total_freight: totalPrimary + totalSecondary,
paid_primary_freight: paidPrimary,
paid_secondary_freight: paidSecondary,
paid_amount: paidPrimary + paidSecondary,
unpaid_amount: (totalPrimary + totalSecondary) - (paidPrimary + paidSecondary)
},
items: orders.map(o => ({
id: o.id, type: 'logistics_record', code: o.code, name: o.order_code || o.code,
project_name: o.project_name,
primary_freight: parseFloat(o.primary_freight) || 0,
primary_freight_currency: o.primary_freight_currency || 'CNY',
primary_freight_status: o.primary_freight_status,
secondary_freight: parseFloat(o.secondary_freight) || 0,
secondary_freight_currency: o.secondary_freight_currency || 'LAK',
secondary_freight_status: o.secondary_freight_status,
status: o.status, date: o.ship_date
}))
};
} catch (error) {
console.error('获取物流公司台账失败:', error);
return { summary: { item_count: 0, total_primary_freight: 0, total_secondary_freight: 0, total_freight: 0, paid_primary_freight: 0, paid_secondary_freight: 0, paid_amount: 0, unpaid_amount: 0 }, items: [] };
}
}
}
module.exports = LedgerService;