feat: add fee workspace and polish AI presentation
This commit is contained in:
75
modules/billing/types.test.ts
Normal file
75
modules/billing/types.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user