resource-control/tests/test_settlement.py
tegwick f8d1c542d5 feat: operational resource procurement facility
Implement RESOURCE-WP-0005: entity register, V0.1 terms parameters,
entity association on inventory and planning records, transfer-price
and credit-state arithmetic, monthly settlement, and entity views on
the portfolio report. Live close emits nothing until delivered cost
is known. Handoffs are FIN-WP-0006 and RAILIANCE-WP-0017.
2026-08-14 13:15:02 +02:00

116 lines
4.8 KiB
Python

import json
import sys
import unittest
from datetime import date
from decimal import Decimal
from pathlib import Path
ROOT = Path(__file__).parents[1]
sys.path.insert(0, str(ROOT / "tools"))
from entities import load_register, load_terms
from financial_exchange import money
from settlement import (
apply_payment,
close_fixture,
close_live,
due_date,
evaluate_credit,
monthly_interest,
transfer_price,
)
class ArithmeticTest(unittest.TestCase):
def setUp(self):
self.terms = load_terms(ROOT)
_, self.register = load_register(ROOT)
def test_coulomb_ordinary_month_section_15_1(self):
price = transfer_price(money("200.00"), "entity:coulomb", self.terms)
self.assertEqual(money("240.00"), price)
self.assertEqual(date(2026, 9, 11), due_date(date(2026, 9, 1), self.terms))
credit = evaluate_credit(
money("240.00"), self.terms, entity_id="entity:coulomb",
register=self.register, overdue=False,
)
self.assertEqual("open", credit["consumption_mode"])
self.assertEqual("760.00", credit["credit_headroom_eur"])
self.assertIsNone(credit["new_transfer_charges_allowed_eur"])
def test_unpaid_statement_interest_section_15_2(self):
self.assertEqual(money("1.00"), monthly_interest(money("240.00"), self.terms))
def test_helixforge_at_default_limit_section_15_3(self):
credit = evaluate_credit(
money("1000.00"), self.terms, entity_id="entity:helixforge",
register=self.register, overdue=True,
)
self.assertEqual("restricted", credit["consumption_mode"])
self.assertEqual("4.17", credit["interest_this_month_eur"])
self.assertEqual("45.83", credit["new_transfer_charges_allowed_eur"])
self.assertEqual("38.19", credit["max_new_delivered_cost_eur"])
def test_railiance_self_use_has_no_markup(self):
self.assertEqual(
money("200.00"),
transfer_price(money("200.00"), "entity:railiance", self.terms),
)
def test_unknown_delivered_cost_stays_null(self):
self.assertIsNone(transfer_price(None, "entity:coulomb", self.terms))
def test_payment_clears_interest_before_principal(self):
applied = apply_payment(money("1.00"), money("240.00"), money("200.00"))
self.assertEqual(money("1.00"), applied["interest_paid"])
self.assertEqual(money("199.00"), applied["principal_paid"])
self.assertEqual(money("41.00"), applied["principal_remaining"])
self.assertEqual(money("0.00"), applied["interest_remaining"])
class StatementFixtureTest(unittest.TestCase):
def setUp(self):
self.terms = load_terms(ROOT)
_, self.register = load_register(ROOT)
def _close(self, name):
payload = json.loads((ROOT / "examples/settlement" / name).read_text())
return close_fixture(payload, self.terms, self.register)
def test_ordinary_statement(self):
statements = self._close("15.1-ordinary.json")
self.assertEqual(1, len(statements))
statement = statements[0]
self.assertEqual("entity:coulomb", statement["financial_entity_id"])
self.assertEqual("240.00", statement["known_transfer_price_eur"])
self.assertEqual("2026-09-11", statement["due_date"])
self.assertEqual("760.00", statement["credit_headroom_eur"])
self.assertEqual("open", statement["consumption_mode"])
self.assertEqual("unknown", statement["payment_recognition"])
def test_extended_payment_statement(self):
statements = self._close("15.2-extended.json")
statement = statements[0]
self.assertEqual("1.00", statement["interest_eur"])
self.assertEqual("120.00", statement["new_transfer_charges_eur"])
self.assertEqual("361.00", statement["outstanding_eur"])
self.assertEqual("open", statement["consumption_mode"])
def test_restricted_statement(self):
statements = self._close("15.3-restricted.json")
statement = statements[0]
self.assertEqual("entity:helixforge", statement["financial_entity_id"])
self.assertEqual("4.17", statement["interest_eur"])
self.assertEqual("restricted", statement["consumption_mode"])
self.assertEqual("45.83", statement["next_month_allowance_eur"])
def test_empty_period_emits_nothing(self):
self.assertEqual([], close_live(ROOT, "2026-08"))
class PlanningForecastTest(unittest.TestCase):
def test_forecast_fixture_carries_transfer_price_and_headroom(self):
record = json.loads((ROOT / "examples/planning/entity-forecast-transfer.json").read_text())
self.assertEqual("entity:coulomb", record["financial_entity_id"])
self.assertEqual("240.00", record["transfer_price"])
self.assertEqual("760.00", record["credit_headroom"])
self.assertIn("not booked spend", record["uncertainty"])