Implement FIN-WP-0006-T01 settlement statement join; mark FIN-WP-0004/0005 blocked
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 6s

Add SettlementStatement schema and a dedicated settlement_statements store
(ingest_settlement_statement, current_settlement_statements) so
resource-control internal transfer settlements join as a referenced
projection without ever entering the booked-cost ledger. exchange_health
now surfaces a current statement with payment_recognition=unknown as a
settlement_awaiting_payment_join residual instead of booked cost. Adds
CLI commands finhub ledger ingest-settlement / settlements.

FIN-WP-0006-T01 is done; the workplan is finished.

Reviewed all other open workplans for closeable work: FIN-WP-0004's only
remaining task (T05) waits on an external provider fact from
resource-control, and every FIN-WP-0005 task waits on operator/Steuerbüro
confirmation or a non-production DATEV tenant. Neither has actionable
in-repo work right now, so both move to status: blocked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 242919@bnt-lap001
Assistant-Session: 286d235a-1654-40ff-b8fd-eee4e2ff9ea6
This commit is contained in:
tegwick 2026-09-27 21:50:54 +02:00
parent 4ef6fec8ff
commit 91d62f6430
8 changed files with 377 additions and 8 deletions

View file

@ -0,0 +1,28 @@
{
"schema_version": "0.1",
"record_type": "settlement_statement",
"terms_version": "V0.1",
"financial_entity_id": "entity:frontier",
"procuring_entity_id": "entity:railiance",
"period": "2026-08",
"statement_date": "2026-09-01",
"due_date": "2026-09-15",
"currency": "EUR",
"line_items": [
{"resource_id": "resource:platform:audit-storage", "delivered_cost_eur": "42.10", "markup_eur": "6.32"}
],
"known_delivered_cost_eur": "42.10",
"known_transfer_price_eur": "48.42",
"unknown_cost_remainder": false,
"prior_outstanding_eur": "0.00",
"recognized_payments_eur": null,
"payment_recognition": "unknown",
"interest_eur": "0.00",
"new_transfer_charges_eur": "48.42",
"outstanding_eur": "48.42",
"credit_limit_eur": "500.00",
"credit_headroom_eur": "451.58",
"consumption_mode": "open",
"next_month_allowance_eur": null,
"payment_instruction": null
}

View file

@ -12,13 +12,16 @@ from fin_hub.schemas.exchange import (
BookedCostEvidence,
ForecastEvidence,
)
from fin_hub.schemas.exchange import SettlementStatement
from fin_hub.services.exchange import (
booked_cost_projection,
current_settlement_statements,
exchange_health,
financial_constraint_projection,
ingest_planning_evidence,
ingest_resource_forecast,
ingest_resource_usage,
ingest_settlement_statement,
reconcile_resource_period,
)
from fin_hub.services.ledger import import_csv
@ -413,3 +416,86 @@ def test_audit_storage_usage_omits_nulls_and_does_not_invent_zero_spend(tmp_path
assert august.invented_zero is False
health = exchange_health(ledger_path=ledger)
assert "usage_without_booked_fact" in {issue.code for issue in health.issues}
def _settlement_payload() -> dict:
return json.loads((FIXTURES / "settlement-statement-2026-08.json").read_text())
def test_settlement_statement_joins_as_referenced_projection_not_booked_cost(
tmp_path: Path,
):
ledger = tmp_path / "ledger.db"
payload = _settlement_payload()
statement = ingest_settlement_statement(
payload,
source_evidence_ref="resource-control:data/settlements/2026-08.json",
ledger_path=ledger,
)
assert isinstance(statement, SettlementStatement)
assert statement.financial_entity_id == "entity:frontier"
assert statement.outstanding_eur == Decimal("48.42")
assert statement.payment_recognition == "unknown"
current = current_settlement_statements(ledger_path=ledger)
assert len(current) == 1
assert current[0].statement_id() == statement.statement_id()
# No booked cost is created by joining a settlement statement.
assert booked_cost_projection(ledger_path=ledger) == []
def test_settlement_statement_is_idempotent_and_supersedes_prior_period_statement(
tmp_path: Path,
):
ledger = tmp_path / "ledger.db"
payload = _settlement_payload()
ingest_settlement_statement(
payload, source_evidence_ref="resource-control:data/settlements/2026-08.json",
ledger_path=ledger,
)
ingest_settlement_statement(
payload, source_evidence_ref="resource-control:data/settlements/2026-08.json",
ledger_path=ledger,
)
assert len(current_settlement_statements(ledger_path=ledger)) == 1
corrected = {**payload, "statement_date": "2026-09-05", "outstanding_eur": "10.00",
"new_transfer_charges_eur": "10.00", "known_transfer_price_eur": "10.00"}
ingest_settlement_statement(
corrected, source_evidence_ref="resource-control:data/settlements/2026-08-corrected.json",
ledger_path=ledger,
)
current = current_settlement_statements(ledger_path=ledger)
assert len(current) == 1
assert current[0].outstanding_eur == Decimal("10.00")
def test_settlement_statement_rejects_provider_invoice_shaped_payload(tmp_path: Path):
ledger = tmp_path / "ledger.db"
with pytest.raises(ValueError, match="record_type=settlement_statement"):
ingest_settlement_statement(
{"record_type": "booked_cost"},
source_evidence_ref="resource-control:x",
ledger_path=ledger,
)
def test_exchange_health_surfaces_settlement_without_payment_join_as_residual(
tmp_path: Path,
):
ledger = tmp_path / "ledger.db"
ingest_settlement_statement(
_settlement_payload(),
source_evidence_ref="resource-control:data/settlements/2026-08.json",
ledger_path=ledger,
)
health = exchange_health(ledger_path=ledger)
assert "settlement_awaiting_payment_join" in {issue.code for issue in health.issues}
assert health.booked_fact_count == 0