import { describe, expect, it } from "vitest"; import { createInitialBillingStatements } from "@/modules/billing/lib/presentation-data"; import { addBillingCharge, addBillingPayment, calculateBillingSummary, getBillingStatus, getStatementOutstandingCents, getStatementTotalCents, } from "@/modules/billing/types"; const referenceDate = new Date("2026-07-09T12:00:00.000Z"); describe("billing calculations", () => { it("derives paid, partial, pending, and overdue states from ledger activity", () => { const statements = createInitialBillingStatements(referenceDate); expect(statements.map((statement) => getBillingStatus(statement, referenceDate))).toEqual([ "paid", "partial", "pending", "overdue", "overdue", "paid", ]); }); it("calculates statement and workspace totals from charges and payments", () => { const statements = createInitialBillingStatements(referenceDate); const summary = calculateBillingSummary(statements, referenceDate); const firstStatement = statements[0]; expect(firstStatement).toBeDefined(); if (!firstStatement) { return; } expect(getStatementTotalCents(firstStatement)).toBe(960000); expect(summary.receivableCents).toBe(5995000); expect(summary.collectedCents).toBe(2810000); expect(summary.outstandingCents).toBe(3185000); expect(summary.overdueCount).toBe(2); }); it("updates outstanding amounts when payments and charges are appended", () => { const statement = createInitialBillingStatements(referenceDate)[2]; expect(statement).toBeDefined(); if (!statement) { return; } const paidStatement = addBillingPayment(statement, { id: "payment-new", amountCents: 200000, method: "wechat", paidAt: referenceDate.toISOString(), reference: "WX-NEW", operator: "收费员", note: "", }); expect(getStatementOutstandingCents(paidStatement)).toBe(640000); expect(getBillingStatus(paidStatement, referenceDate)).toBe("partial"); const chargedStatement = addBillingCharge(paidStatement, { id: "charge-new", category: "生活用品", description: "护理耗材", quantity: 2, serviceDate: referenceDate.toISOString(), unitPriceCents: 5000, }); expect(getStatementOutstandingCents(chargedStatement)).toBe(650000); expect(chargedStatement.invoiceStatus).toBe("not_requested"); }); });