Ctrl K
ComunidadGuías…

test/shared/accounting/tax-modifier-projections.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import {
  attendeeAccount,
  modifierAccount,
  TAX_VAT,
} from "#accounting/accounts.ts";
import { KIND } from "#accounting/kinds.ts";
import { mapBooking, mapRefund } from "#accounting/mappers.ts";
import {
  externalCashBalanceSubquery,
  orderTotalSubquery,
  reservationSubtotalSubquery,
} from "#accounting/projection-sql.ts";
import { accountBalance, allTransfers } from "#accounting/queries.ts";
import { postTransfers } from "#accounting/store.ts";
import { queryOne } from "#db/client.ts";
import { tx, useTransactionalDb } from "#test-utils/ledger.ts";

const customerTotals = () =>
  queryOne<{ cash: number; total: number; deposit_base: number }>(`SELECT
  ${externalCashBalanceSubquery("attendee", "1")} AS cash,
  ${orderTotalSubquery("attendee", "1")} AS total,
  ${reservationSubtotalSubquery("attendee", "1")} AS deposit_base`);

describe("db > accounting > tax modifier corrections", () => {
  useTransactionalDb();

  test("reclassifies option income in either direction without changing cash or the included-tax deposit", async () => {
    await postTransfers(
      await mapBooking({
        amountPaid: 1100,
        attendeeId: 1,
        bookingFee: 0,
        eventId: "modifier-tax",
        lines: [{ gross: 1000, listingId: 1 }],
        modifiers: [{ delta: 100, modifierId: 1 }],
        occurredAt: "2026-06-21T00:00:00.000Z",
      }),
    );
    await postTransfers([
      tx({
        amount: 20,
        destination: attendeeAccount(1),
        eventGroup: "tax-option-1",
        kind: KIND.taxModifier,
        reference: "option-less",
        source: modifierAccount(1),
      }),
      tx({
        amount: 20,
        destination: TAX_VAT,
        eventGroup: "tax-option-1",
        kind: KIND.vat,
        reference: "vat-more",
        source: attendeeAccount(1),
      }),
    ]);
    expect(await accountBalance(modifierAccount(1))).toBe(80);
    expect(await customerTotals()).toEqual({
      cash: 1100,
      deposit_base: 1100,
      total: 1100,
    });
    await postTransfers([
      tx({
        amount: 10,
        destination: modifierAccount(1),
        eventGroup: "tax-option-2",
        kind: KIND.taxModifier,
        reference: "option-more",
        source: attendeeAccount(1),
      }),
      tx({
        amount: 10,
        destination: attendeeAccount(1),
        eventGroup: "tax-option-2",
        kind: KIND.vat,
        reference: "vat-less",
        source: TAX_VAT,
      }),
    ]);
    expect(await accountBalance(modifierAccount(1))).toBe(90);
    expect(await customerTotals()).toEqual({
      cash: 1100,
      deposit_base: 1100,
      total: 1100,
    });
    for (const legs of Map.groupBy(
      await allTransfers(),
      (leg) => leg.eventGroup,
    ).values()) {
      await postTransfers(
        await mapRefund({
          occurredAt: "2026-06-22T00:00:00.000Z",
          orderLegs: legs,
        }),
      );
    }
    expect(await accountBalance(modifierAccount(1))).toBe(0);
    expect(await accountBalance(TAX_VAT)).toBe(0);
    expect(await accountBalance(attendeeAccount(1))).toBe(0);
    expect(
      (await allTransfers()).filter(
        (leg) => leg.kind === KIND.refundTaxModifier,
      ),
    ).toHaveLength(2);
    expect(await customerTotals()).toEqual({
      cash: 0,
      deposit_base: 1100,
      total: 1100,
    });
  });
});