|
|
|
@ -1,11 +1,13 @@ |
|
|
|
"""Synthetic checks for immutable, audited reconciliation checkpoints.""" |
|
|
|
"""Synthetic checks for immutable, audited reconciliation checkpoints.""" |
|
|
|
|
|
|
|
|
|
|
|
from datetime import date |
|
|
|
from datetime import date, datetime |
|
|
|
from decimal import Decimal |
|
|
|
from decimal import Decimal |
|
|
|
|
|
|
|
from uuid import UUID |
|
|
|
|
|
|
|
|
|
|
|
import pytest |
|
|
|
import pytest |
|
|
|
|
|
|
|
from django.utils import timezone |
|
|
|
|
|
|
|
|
|
|
|
from finance.models import AuditEvent, ReconciliationCheckpoint |
|
|
|
from finance.models import Account, AuditEvent, ReconciliationCheckpoint |
|
|
|
from finance.reconciliation import ( |
|
|
|
from finance.reconciliation import ( |
|
|
|
checkpoint_history, |
|
|
|
checkpoint_history, |
|
|
|
latest_checkpoint_statuses, |
|
|
|
latest_checkpoint_statuses, |
|
|
|
@ -254,3 +256,56 @@ def test_latest_checkpoint_statuses_select_by_as_of_date_then_creation_for_activ |
|
|
|
by_date.pk: newer_as_of_date.pk, |
|
|
|
by_date.pk: newer_as_of_date.pk, |
|
|
|
by_creation.pk: correction.pk, |
|
|
|
by_creation.pk: correction.pk, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_latest_checkpoint_statuses_order_selected_accounts_by_checkpoint_recency(): |
|
|
|
|
|
|
|
oldest_account = Account.objects.create( |
|
|
|
|
|
|
|
id=UUID("00000000-0000-0000-0000-000000000001"), |
|
|
|
|
|
|
|
name="Synthetic oldest account", |
|
|
|
|
|
|
|
kind="BANK", |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
older_same_date_account = Account.objects.create( |
|
|
|
|
|
|
|
id=UUID("00000000-0000-0000-0000-000000000002"), |
|
|
|
|
|
|
|
name="Synthetic older same-date account", |
|
|
|
|
|
|
|
kind="BANK", |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
newest_account = Account.objects.create( |
|
|
|
|
|
|
|
id=UUID("00000000-0000-0000-0000-000000000003"), |
|
|
|
|
|
|
|
name="Synthetic newest account", |
|
|
|
|
|
|
|
kind="BANK", |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
oldest = create_reconciliation_checkpoint( |
|
|
|
|
|
|
|
account_id=oldest_account.pk, |
|
|
|
|
|
|
|
as_of_date=AS_OF_DATE, |
|
|
|
|
|
|
|
institution_balance=Decimal("0.00"), |
|
|
|
|
|
|
|
actor=ACTOR, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
older_same_date = create_reconciliation_checkpoint( |
|
|
|
|
|
|
|
account_id=older_same_date_account.pk, |
|
|
|
|
|
|
|
as_of_date=date(2026, 9, 2), |
|
|
|
|
|
|
|
institution_balance=Decimal("0.00"), |
|
|
|
|
|
|
|
actor=ACTOR, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
newest = create_reconciliation_checkpoint( |
|
|
|
|
|
|
|
account_id=newest_account.pk, |
|
|
|
|
|
|
|
as_of_date=date(2026, 9, 2), |
|
|
|
|
|
|
|
institution_balance=Decimal("0.00"), |
|
|
|
|
|
|
|
actor=ACTOR, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
ReconciliationCheckpoint.objects.filter(pk=oldest.pk).update( |
|
|
|
|
|
|
|
created_at=timezone.make_aware(datetime(2026, 9, 1, 9, 0)) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
ReconciliationCheckpoint.objects.filter(pk=older_same_date.pk).update( |
|
|
|
|
|
|
|
created_at=timezone.make_aware(datetime(2026, 9, 1, 10, 0)) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
ReconciliationCheckpoint.objects.filter(pk=newest.pk).update( |
|
|
|
|
|
|
|
created_at=timezone.make_aware(datetime(2026, 9, 1, 11, 0)) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
statuses = latest_checkpoint_statuses("BRL") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert [status.checkpoint_id for status in statuses] == [ |
|
|
|
|
|
|
|
newest.pk, |
|
|
|
|
|
|
|
older_same_date.pk, |
|
|
|
|
|
|
|
oldest.pk, |
|
|
|
|
|
|
|
] |
|
|
|
|