Spaces:
Sleeping
Sleeping
| """Tests for the multi-currency engine (Phase 1.1).""" | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from server.currency_engine import ( | |
| convert_currency, | |
| detect_currency_mismatch, | |
| generate_aging_report, | |
| validate_iban, | |
| validate_swift, | |
| ) | |
| class TestIBANValidation: | |
| def test_valid_german_iban(self): | |
| result = validate_iban("DE89 3704 0044 0532 0130 00") | |
| assert result["country"] == "DE" | |
| # Format check passes (checksum may vary for test data) | |
| def test_too_short(self): | |
| result = validate_iban("DE8") | |
| assert not result["valid"] | |
| assert "too short" in result["errors"][0].lower() | |
| def test_invalid_country_code(self): | |
| result = validate_iban("12345678901234567890") | |
| assert not result["valid"] | |
| class TestSWIFTValidation: | |
| def test_valid_8_char(self): | |
| result = validate_swift("DEUTDEFF") | |
| assert result["valid"] | |
| assert result["bank_code"] == "DEUT" | |
| assert result["country"] == "DE" | |
| def test_valid_11_char(self): | |
| result = validate_swift("DEUTDEFF500") | |
| assert result["valid"] | |
| def test_invalid_length(self): | |
| result = validate_swift("SHORT") | |
| assert not result["valid"] | |
| class TestCurrencyConversion: | |
| def test_same_currency(self): | |
| result = convert_currency(100.0, "USD", "USD", apply_spread=False) | |
| assert result.valid | |
| assert result.converted_amount == 100.0 | |
| def test_usd_to_eur(self): | |
| result = convert_currency(100.0, "USD", "EUR", apply_spread=False) | |
| assert result.valid | |
| assert result.converted_amount > 0 | |
| def test_unknown_currency(self): | |
| result = convert_currency(100.0, "USD", "XYZ") | |
| assert not result.valid | |
| def test_sanctioned_currency(self): | |
| result = convert_currency(100.0, "USD", "IRR") | |
| assert not result.valid | |
| assert any("sanctioned" in f for f in result.risk_flags) | |
| def test_spread_applied(self): | |
| with_spread = convert_currency(100.0, "USD", "EUR", apply_spread=True) | |
| without_spread = convert_currency(100.0, "USD", "EUR", apply_spread=False) | |
| assert with_spread.converted_amount < without_spread.converted_amount | |
| class TestCurrencyMismatch: | |
| def test_no_mismatch(self): | |
| result = detect_currency_mismatch("USD", "USD", "USD") | |
| assert not result["has_mismatch"] | |
| def test_single_mismatch(self): | |
| result = detect_currency_mismatch("USD", "", "EUR") | |
| assert result["has_mismatch"] | |
| assert result["risk_level"] == "medium" | |
| def test_triple_mismatch(self): | |
| result = detect_currency_mismatch("USD", "EUR", "GBP") | |
| assert result["has_mismatch"] | |
| assert result["risk_level"] == "high" | |
| class TestAgingReport: | |
| def test_basic_report(self): | |
| invoices = [ | |
| {"invoice_id": "INV-001", "amount": 1000, "currency": "USD", "days_outstanding": 15, "vendor_name": "Acme"}, | |
| {"invoice_id": "INV-002", "amount": 2000, "currency": "USD", "days_outstanding": 45, "vendor_name": "Beta"}, | |
| {"invoice_id": "INV-003", "amount": 500, "currency": "EUR", "days_outstanding": 95, "vendor_name": "Gamma"}, | |
| ] | |
| report = generate_aging_report(invoices) | |
| assert report["base_currency"] == "USD" | |
| assert report["total"] > 0 | |
| assert len(report["buckets"]["0_30"]) == 1 | |
| assert len(report["buckets"]["31_60"]) == 1 | |
| assert len(report["buckets"]["90_plus"]) == 1 | |