from datetime import date from decimal import Decimal from app.service.offsite_fund_rules import ( OffsiteFundRuleEngine, normalize_amount_yuan, parse_application_date, ) def test_subscription_minimum_amount_boundary() -> None: engine = OffsiteFundRuleEngine() below = engine.check_subscription( amount_yuan=Decimal("0.99"), nav=None, total_fund_shares=None, before_holding_shares=None) equal = engine.check_subscription( amount_yuan=Decimal("1.00"), nav=None, total_fund_shares=None, before_holding_shares=None) above = engine.check_subscription( amount_yuan=Decimal("1.01"), nav=None, total_fund_shares=None, before_holding_shares=None) assert below[0].result == "异常" assert equal[0].result == "异常" assert above[0].result == "正常" def test_subscription_ratio_and_share_limit_boundary() -> None: engine = OffsiteFundRuleEngine() normal = engine.check_subscription( amount_yuan=Decimal("100"), nav=Decimal("1"), total_fund_shares=Decimal("1000"), before_holding_shares=Decimal("100")) abnormal = engine.check_subscription( amount_yuan=Decimal("101"), nav=Decimal("1"), total_fund_shares=Decimal("1000"), before_holding_shares=Decimal("100")) assert {item.rule_code: item.result for item in normal}["subscription_holding_ratio"] == "正常" assert {item.rule_code: item.result for item in abnormal}[ "subscription_holding_ratio"] == "异常" assert {item.rule_code: item.result for item in abnormal}[ "subscription_single_share_limit"] == "异常" def test_redemption_ratio_and_available_quantity_boundary() -> None: engine = OffsiteFundRuleEngine() normal = engine.check_redemption( redemption_shares=Decimal("200"), total_fund_shares=Decimal("1000"), available_quantity=Decimal("200")) abnormal = engine.check_redemption( redemption_shares=Decimal("201"), total_fund_shares=Decimal("1000"), available_quantity=Decimal("200")) assert {item.rule_code: item.result for item in normal}["redemption_large_ratio"] == "正常" assert {item.rule_code: item.result for item in normal}[ "redemption_available_quantity"] == "正常" assert {item.rule_code: item.result for item in abnormal}["redemption_large_ratio"] == "异常" assert {item.rule_code: item.result for item in abnormal}[ "redemption_available_quantity"] == "异常" def test_normalize_amount_keeps_original_unit_semantics() -> None: assert normalize_amount_yuan("2.50", "万元") == Decimal("25000.00") assert normalize_amount_yuan("2.50", "元") == Decimal("2.50") assert normalize_amount_yuan("20,000.00万元", "万元") == Decimal("200000000.00") assert normalize_amount_yuan("人民币5,000.00元", "元") == Decimal("5000.00") assert normalize_amount_yuan("CNY 5,000.00", "元") == Decimal("5000.00") assert normalize_amount_yuan("2.50", "美元") is None def test_parse_application_date_accepts_compact_calendar_date() -> None: assert parse_application_date("20260908") == date(2026, 9, 8)