fix: restore manual confirm_duplicate compatibility and precision safeguards
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
a71c91f6ef
commit
aa40c7fdff
@@ -312,3 +312,47 @@ def test_dividend_precision_and_reversal_round_trip_on_real_postgres(
|
||||
assert cur.fetchone()[0] == "0"
|
||||
|
||||
repo.close()
|
||||
|
||||
|
||||
def test_existing_high_precision_snapshot_still_allows_legacy_manual_actions(
|
||||
isolated_settings: Settings,
|
||||
) -> None:
|
||||
"""Existing DOUBLE snapshot precision should not block unrelated manual actions."""
|
||||
upgrade_to_head(isolated_settings)
|
||||
repo = _repo(isolated_settings)
|
||||
portfolio_id = _seed_portfolio(repo, "legacy-snapshot-precision")
|
||||
with repo._connect().cursor() as cur:
|
||||
cur.execute(
|
||||
"UPDATE portfolios SET cash_balance = %s WHERE portfolio_id = %s",
|
||||
(0.123456789, portfolio_id),
|
||||
)
|
||||
|
||||
entry = repo.record_manual_ledger(
|
||||
portfolio_id,
|
||||
action="INVEST",
|
||||
amount=Decimal("1.00000000"),
|
||||
note="compat",
|
||||
)
|
||||
assert entry.action == "INVEST"
|
||||
assert entry.price == 1.0
|
||||
repo.close()
|
||||
|
||||
|
||||
def test_dividend_large_integer_with_8dp_is_rejected_to_protect_double_snapshot(
|
||||
isolated_settings: Settings,
|
||||
) -> None:
|
||||
"""Inputs valid for NUMERIC(20,8) but unsafe for DOUBLE snapshot are rejected."""
|
||||
upgrade_to_head(isolated_settings)
|
||||
repo = _repo(isolated_settings)
|
||||
portfolio_id = _seed_portfolio(repo, "double-snapshot-guard")
|
||||
|
||||
with pytest.raises(ValueError, match="double snapshot precision"):
|
||||
repo.record_manual_ledger(
|
||||
portfolio_id,
|
||||
action="DIVIDEND",
|
||||
amount=Decimal("1000000000.00000001"),
|
||||
tax=Decimal("0.00000001"),
|
||||
executed_at=datetime(2026, 9, 1, 0, 0, 0, tzinfo=timezone.utc),
|
||||
note="too-large-for-double",
|
||||
)
|
||||
repo.close()
|
||||
|
||||
@@ -558,6 +558,37 @@ def test_dividend_duplicate_requires_confirmation() -> None:
|
||||
assert confirmed.status_code == 201
|
||||
|
||||
|
||||
def test_confirm_duplicate_false_is_accepted_for_non_dividend_actions() -> None:
|
||||
repo = _FakeRepo(_portfolio())
|
||||
client = _make_client(repo)
|
||||
|
||||
invest = client.post(
|
||||
f"/v1/portfolios/{_PORTFOLIO_ID}/ledger/manual",
|
||||
json={"action": "INVEST", "amount": 100, "confirm_duplicate": False},
|
||||
headers=_auth(),
|
||||
)
|
||||
assert invest.status_code == 201
|
||||
|
||||
buy = client.post(
|
||||
f"/v1/portfolios/{_PORTFOLIO_ID}/ledger/manual",
|
||||
json={"action": "BUY", "quantity": 1, "price": 10, "confirm_duplicate": False},
|
||||
headers=_auth(),
|
||||
)
|
||||
assert buy.status_code == 201
|
||||
|
||||
|
||||
def test_confirm_duplicate_true_is_rejected_for_non_dividend_actions() -> None:
|
||||
repo = _FakeRepo(_portfolio())
|
||||
client = _make_client(repo)
|
||||
|
||||
invest = client.post(
|
||||
f"/v1/portfolios/{_PORTFOLIO_ID}/ledger/manual",
|
||||
json={"action": "INVEST", "amount": 100, "confirm_duplicate": True},
|
||||
headers=_auth(),
|
||||
)
|
||||
assert invest.status_code == 422
|
||||
|
||||
|
||||
def test_dividend_reversal_decreases_profit_buffer() -> None:
|
||||
repo = _FakeRepo(_portfolio(buffer=200))
|
||||
client = _make_client(repo)
|
||||
|
||||
Reference in New Issue
Block a user