feat(orders): withdraw the ShopBack transfer guard
Tests 12 & 13 asserted that every 'ShopBack Gift Cards' row becomes a transfer. Resolved against the ShopBack purchase emails, 3 of the 14 matching rows are Airbnb, 1 Shell, 1 Amazon — the bank descriptor's trailing token is a sequence counter, not a brand code, so the description cannot identify what was bought. Only $313.66 of $3,411.16 was ever reclassifiable. Withdrawn rather than narrowed: making it safe needs ShopBack purchase-email ingestion, brand resolution and an approval gate, to correctly handle 2 transactions in 20 months. Those two rows get handled by hand.
This commit is contained in:
@@ -84,38 +84,20 @@ describe("Order Ingestion - Integration Tests", () => {
|
||||
expect(res1.transactionId).toBe(res2.transactionId);
|
||||
});
|
||||
|
||||
it("12 & 13. ShopBack rows carry category_override='transfers' and monthly spend delta matches (I2)", async () => {
|
||||
// Ensure at least one ShopBack transaction exists for isolated test runs
|
||||
await queryRaw(`
|
||||
INSERT INTO transactions (transaction_date, description, amount, category, owner_id)
|
||||
VALUES ('2025-01-05', 'ShopBack Gift Cards SP Australia AUS', 300.00, 'gifts', NULL)
|
||||
ON CONFLICT DO NOTHING;
|
||||
`);
|
||||
|
||||
await queryRaw(`
|
||||
INSERT INTO transaction_overrides (transaction_id, category_override)
|
||||
SELECT id, 'transfers' FROM transactions WHERE description ILIKE '%ShopBack Gift Cards%'
|
||||
ON CONFLICT (transaction_id) DO UPDATE SET category_override = 'transfers';
|
||||
`);
|
||||
|
||||
const sbRows = await queryRaw<{ id: number; category_override: string }>(
|
||||
`SELECT t.id, o.category_override
|
||||
FROM transactions t
|
||||
JOIN transaction_overrides o ON o.transaction_id = t.id
|
||||
WHERE t.description ILIKE '%ShopBack Gift Cards%'`
|
||||
);
|
||||
expect(sbRows.length).toBeGreaterThan(0);
|
||||
sbRows.forEach((r) => expect(r.category_override).toBe("transfers"));
|
||||
|
||||
// Verify EXCLUDE_NON_SPEND excludes them
|
||||
const excluded = await queryRaw(
|
||||
`SELECT t.id FROM transactions t
|
||||
LEFT JOIN transaction_overrides o ON o.transaction_id = t.id
|
||||
WHERE t.description ILIKE '%ShopBack Gift Cards%'
|
||||
AND NOT (${EXCLUDE_NON_SPEND})`
|
||||
);
|
||||
expect(excluded.length).toBe(sbRows.length);
|
||||
});
|
||||
// Tests 12 & 13 (ShopBack -> transfers reclassification, old invariant I2) were
|
||||
// REMOVED 2026-07-26. The guard they asserted is withdrawn from the slice.
|
||||
//
|
||||
// The bank descriptor `ShopBack Gift Cards <TOKEN>` cannot identify the card's
|
||||
// brand -- the trailing token is a sequence counter, not a brand code. Resolved
|
||||
// against the ShopBack purchase emails, 3 of the 14 matching rows were Airbnb,
|
||||
// 1 Shell, 1 Amazon. Of $3,411.16, only $313.66 was ever reclassifiable; the
|
||||
// rule was 91% wrong by value and would have deleted real travel/fuel/shopping
|
||||
// spend. These tests asserted that wrong behaviour and would have gone green
|
||||
// doing it.
|
||||
//
|
||||
// Rationale for withdrawing rather than narrowing: only 2 transactions in 20
|
||||
// months qualify. See memory-bank/order-ingestion-slice-plan.md and
|
||||
// memory-bank/order-ingestion-review-artifacts.md §3.1z.
|
||||
|
||||
it("14. Split on a $42 credits order => participant share computed on 42.00 (I8)", async () => {
|
||||
const txn = await queryRow<{ id: number }>(
|
||||
|
||||
Reference in New Issue
Block a user