test/shared/accounting/repoint.test.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@std/expect";
import { it as test } from "@std/testing/bdd";
import {
attendeeAccount,
revenueAccount,
WORLD,
} from "#accounting/accounts.ts";
import { accountBalance, transfersByAccount } from "#accounting/queries.ts";
import { repointAttendeeStatements } from "#accounting/repoint.ts";
import { postTransfers } from "#accounting/store.ts";
import { executeBatch } from "#db/client.ts";
import type { TransferInput } from "#shared/ledger/types.ts";
import { assessTax } from "#shared/tax/assessment.ts";
import {
initialTaxAssessmentStatement,
readTaxAssessments,
} from "#shared/tax/store.ts";
import { NO_TAX } from "#shared/tax/types.ts";
import { describeWithEnv } from "#test-utils/db.ts";
/** A paid booking on one attendee: sale (attendee→revenue) + payment. */
const booking = (attendeeId: number): TransferInput[] => [
{
amount: 5000,
destination: revenueAccount(1),
eventGroup: "evt",
kind: "sale",
occurredAt: "2026-06-21T00:00:00.000Z",
reference: "sale",
source: attendeeAccount(attendeeId),
},
{
amount: 5000,
destination: attendeeAccount(attendeeId),
eventGroup: "evt",
kind: "payment",
occurredAt: "2026-06-21T00:00:00.000Z",
reference: "pay",
source: WORLD,
},
];
describeWithEnv("accounting > repoint (integration)", { db: true }, () => {
test("moves every leg from the source attendee onto the target", async () => {
await postTransfers(booking(3));
const assessment = assessTax(
{ lines: [{ gross: 5000, listingId: 1 }], modifiers: [] },
NO_TAX,
);
await executeBatch([
await initialTaxAssessmentStatement(
"evt",
assessment,
"2026-06-21T00:00:00.000Z",
"?",
[3],
),
...repointAttendeeStatements(3, 7),
]);
expect(await readTaxAssessments([3])).toEqual([]);
expect(
(await readTaxAssessments([7])).map((record) => ({
basis: record.state.assessment.basis,
group: record.bookingGroup,
owner: record.attendeeId,
})),
).toEqual([{ basis: assessment.basis, group: "evt", owner: 7 }]);
expect((await transfersByAccount(attendeeAccount(3))).length).toBe(0);
expect((await transfersByAccount(attendeeAccount(7))).length).toBe(2);
expect(await accountBalance(attendeeAccount(7))).toBe(0); // still paid in full
expect(await accountBalance(revenueAccount(1))).toBe(5000); // revenue untouched
});
test("is a no-op for a source with no ledger rows", async () => {
await executeBatch(repointAttendeeStatements(3, 7));
expect((await transfersByAccount(attendeeAccount(7))).length).toBe(0);
});
test("leaves rows of another account type with the same numeric id untouched", async () => {
// Revenue account 3 shares the source attendee's numeric id — only the
// type+id pair may move, so a repoint of attendee 3 must not steal it.
await postTransfers([
{
amount: 5000,
destination: revenueAccount(3),
eventGroup: "evt-type",
kind: "sale",
occurredAt: "2026-06-21T00:00:00.000Z",
reference: "sale-type",
source: attendeeAccount(3),
},
]);
await executeBatch(repointAttendeeStatements(3, 7));
// The sale's source leg followed the attendee…
expect((await transfersByAccount(attendeeAccount(7))).length).toBe(1);
expect((await transfersByAccount(attendeeAccount(3))).length).toBe(0);
// …while its destination stayed on revenue 3 (same id, different type).
expect(await accountBalance(revenueAccount(3))).toBe(5000);
expect((await transfersByAccount(revenueAccount(7))).length).toBe(0);
});
});