76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
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");
|
|
});
|
|
});
|