dodil/erp-brick-payments

DODIL ERP brick: payments

tests/test_audit_shoulds.py

"""Payments v4 audit SHOULDs (2026-10-23): feed consent bounds, and the PAY-27 claim collision."""
from conftest import APPROVER, SYSTEM, api, bank, must, on_day, refused
from test_v4_slice_c import feed, tx


def test_a_consent_expires_on_its_expiry_day_not_the_day_after(nb):
    bank()
    must(api("POST", "/bank-accounts/BANK1/feed-consent", APPROVER, {"provider": "truelayer", "granted_on": "2026-11-20", "days": 1}))
    with on_day("2026-11-21T09:00:00+00:00"):
        refused(feed([tx("T1", "100.00")], as_of="2026-11-21"), 409, "feed_consent")


def test_the_feed_provider_must_be_the_one_the_owner_named(nb):
    bank()
    must(api("POST", "/bank-accounts/BANK1/feed-consent", APPROVER, {"provider": "truelayer"}))
    refused(api("POST", "/statements/ingest", SYSTEM, {"bank_account_id": "BANK1", "as_of": "2026-11-20", "booked_balance": "1100.00",
                                                        "provider": "plaid", "lines": [tx("T1", "100.00")]}, ), 409, "truelayer")


def test_a_consent_granted_more_than_90_days_ago_is_refused(nb):
    bank()
    refused(api("POST", "/bank-accounts/BANK1/feed-consent", APPROVER, {"provider": "truelayer", "granted_on": "2026-01-01"}), 409, "grant")


# ── a claim lost at COMMIT (live on DataK3, 2026-10-24): the loser of two concurrent allocations got a 500, not the retry-safe 409 ──

def test_a_unique_violation_raised_at_commit_is_the_409_and_another_integrity_error_is_not(engine):
    import pytest
    from sqlalchemy.exc import IntegrityError

    from brick_payments.application import use_cases
    dup = IntegrityError("INSERT", {}, Exception('duplicate key value violates unique constraint "pay_source_claim_pkey" (SQLSTATE 23505)'))
    with pytest.raises(use_cases.Refused) as lost:
        with use_cases._on_engine(engine):
            raise dup
    assert lost.value.status == 409 and "Someone else wrote" in lost.value.reason
    with pytest.raises(IntegrityError):
        with use_cases._on_engine(engine):
            raise IntegrityError("INSERT", {}, Exception("null value in column violates not-null constraint"))