188 lines
7.6 KiB
JavaScript
188 lines
7.6 KiB
JavaScript
/**
|
|||
|
|
* 业务台账服务
|
||
|
|
* 为合作伙伴提供统一的业务台账数据
|
||
|
|
*/
|
||
|
|
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;
|