/** * 星环OPC中心 — 应收应付管理测试 */ import { describe, it, expect, beforeEach } from "vitest"; import { SqliteAdapter } from "../db/sqlite-adapter.js"; import { createMockApi } from "../__tests__/test-utils.js"; import { registerFinanceTool } from "./finance-tool.js"; describe("OPC Finance Tool - Payment Management", () => { let db: SqliteAdapter; let api: ReturnType; beforeEach(() => { db = new SqliteAdapter(":memory:"); api = createMockApi(); registerFinanceTool(api, db); // 创建测试公司 db.execute( `INSERT INTO opc_companies (id, name, industry, owner_name, status, created_at) VALUES ('test-company-1', '测试公司', '科技', '张三', 'active', datetime('now'))`, ); }); describe("create_payment", () => { it("应该创建应收记录", async () => { const tool = api.getRegisteredTool("opc_finance"); expect(tool).toBeDefined(); const result = await tool!.execute("call-1", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户A", amount: 10000, due_date: "2026-04-01", category: "service", notes: "项目服务费", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.ok).toBe(true); expect(data.payment.direction).toBe("receivable"); expect(data.payment.counterparty).toBe("客户A"); expect(data.payment.amount).toBe(10000); expect(data.payment.status).toBe("pending"); }); it("应该创建应付记录", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-2", { action: "create_payment", company_id: "test-company-1", direction: "payable", counterparty: "供应商B", amount: 5000, due_date: "2026-03-20", category: "product", payment_method: "bank_transfer", notes: "采购货款", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.ok).toBe(true); expect(data.payment.direction).toBe("payable"); expect(data.payment.amount).toBe(5000); }); }); describe("list_payments", () => { beforeEach(async () => { const tool = api.getRegisteredTool("opc_finance"); // 创建多条测试数据 await tool!.execute("call-1", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户A", amount: 10000, due_date: "2026-04-01", category: "service", }); await tool!.execute("call-2", { action: "create_payment", company_id: "test-company-1", direction: "payable", counterparty: "供应商B", amount: 5000, due_date: "2026-03-20", category: "product", }); await tool!.execute("call-3", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户C", amount: 8000, due_date: "2026-03-25", category: "service", }); }); it("应该查询所有应收应付记录", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-4", { action: "list_payments", company_id: "test-company-1", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.ok).toBe(true); expect(data.payments).toHaveLength(3); }); it("应该按方向筛选", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-5", { action: "list_payments", company_id: "test-company-1", direction: "receivable", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.payments).toHaveLength(2); expect(data.payments[0].direction).toBe("receivable"); }); it("应该按状态筛选", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-6", { action: "list_payments", company_id: "test-company-1", status: "pending", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.payments).toHaveLength(3); }); }); describe("update_payment", () => { let paymentId: string; beforeEach(async () => { const tool = api.getRegisteredTool("opc_finance"); const createResult = await tool!.execute("call-1", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户A", amount: 10000, due_date: "2026-04-01", category: "service", }); const data = JSON.parse(createResult.content[0].text); paymentId = data.payment.id; }); it("应该支持部分到账", async () => { const tool = api.getRegisteredTool("opc_finance"); // 第一次到账 3000 const result1 = await tool!.execute("call-2", { action: "update_payment", payment_id: paymentId, paid_amount: 3000, paid_date: "2026-03-15", }); expect(result1.type).toBe("success"); const data1 = JSON.parse(result1.content[0].text); expect(data1.payment.paid_amount).toBe(3000); expect(data1.payment.status).toBe("partial"); // 第二次到账 7000 const result2 = await tool!.execute("call-3", { action: "update_payment", payment_id: paymentId, paid_amount: 7000, paid_date: "2026-03-20", }); const data2 = JSON.parse(result2.content[0].text); expect(data2.payment.paid_amount).toBe(10000); expect(data2.payment.status).toBe("paid"); }); it("应该支持手动修改状态", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-4", { action: "update_payment", payment_id: paymentId, status: "cancelled", notes: "客户取消合同", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.payment.status).toBe("cancelled"); }); }); describe("payment_summary", () => { beforeEach(async () => { const tool = api.getRegisteredTool("opc_finance"); // 应收记录 await tool!.execute("call-1", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户A", amount: 10000, due_date: "2026-04-01", }); await tool!.execute("call-2", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户B", amount: 8000, due_date: "2026-02-01", // 已逾期 }); // 应付记录 await tool!.execute("call-3", { action: "create_payment", company_id: "test-company-1", direction: "payable", counterparty: "供应商C", amount: 5000, due_date: "2026-03-20", }); // 标记逾期 await tool!.execute("call-4", { action: "overdue_check", company_id: "test-company-1", }); }); it("应该汇总应收应付数据", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-5", { action: "payment_summary", company_id: "test-company-1", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.ok).toBe(true); expect(data.summary.receivable.overdue_count).toBeGreaterThan(0); expect(data.summary.receivable.overdue_total).toBe(8000); }); }); describe("overdue_check", () => { beforeEach(async () => { const tool = api.getRegisteredTool("opc_finance"); // 创建逾期应收记录 await tool!.execute("call-1", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户A", amount: 10000, due_date: "2026-02-01", // 已逾期 }); // 创建正常应收记录 await tool!.execute("call-2", { action: "create_payment", company_id: "test-company-1", direction: "receivable", counterparty: "客户B", amount: 5000, due_date: "2026-05-01", // 未逾期 }); }); it("应该自动标记逾期记录", async () => { const tool = api.getRegisteredTool("opc_finance"); const result = await tool!.execute("call-3", { action: "overdue_check", company_id: "test-company-1", }); expect(result.type).toBe("success"); const data = JSON.parse(result.content[0].text); expect(data.ok).toBe(true); expect(data.overdue_check.receivable.count).toBe(1); expect(data.overdue_check.receivable.total).toBe(10000); expect(data.overdue_check.overdue_list).toHaveLength(1); }); it("逾期记录应该自动更新状态", async () => { const tool = api.getRegisteredTool("opc_finance"); await tool!.execute("call-3", { action: "overdue_check", company_id: "test-company-1", }); const listResult = await tool!.execute("call-4", { action: "list_payments", company_id: "test-company-1", status: "overdue", }); const data = JSON.parse(listResult.content[0].text); expect(data.payments).toHaveLength(1); expect(data.payments[0].status).toBe("overdue"); }); }); });