"""删除单条已平仓交易记录。""" from __future__ import annotations import asyncio import pytest from fastapi import HTTPException from app.api.trades import delete_group from app.models.db import Database def _seed_closed(db: Database, gid: str = "G-DEL-1") -> None: with db._lock: db._conn.execute( """INSERT INTO groups(group_id, status, open_at_ms, close_at_ms, realized_pnl) VALUES (?, 'closed', 1, 2, 1.5)""", (gid,), ) db._conn.execute( """INSERT INTO fills(group_id, leg, action, side, inst_id, qty_eth, fill_px, fee, slip, notional, ts_ms) VALUES (?, 'option', 'open', 'buy', 'ETH-C', 1, 10, 0.1, 0, 10, 1)""", (gid,), ) db._conn.execute( """INSERT INTO residual_options( group_id, option_inst_id, option_side, option_qty_eth, option_entry_px, status, created_at_ms ) VALUES (?, 'ETH-C', 'call', 1, 10, 'pending', 1)""", (gid,), ) db._conn.execute( """INSERT INTO ledger_entries(group_id, kind, amount, balance_after, note, ts_ms) VALUES (?, 'pnl', 1.5, 10001.5, 't', 2)""", (gid,), ) db._conn.commit() def test_delete_closed_group(tmp_path, monkeypatch) -> None: monkeypatch.setenv("MODE", "SIM") db = Database(tmp_path / "del.db") monkeypatch.setattr("app.api.trades.get_db", lambda: db) _seed_closed(db) out = asyncio.run(delete_group("G-DEL-1", _user="t")) assert out["ok"] is True assert db.fetchone("SELECT COUNT(*) AS c FROM groups")["c"] == 0 assert db.fetchone("SELECT COUNT(*) AS c FROM fills")["c"] == 0 assert db.fetchone("SELECT COUNT(*) AS c FROM residual_options")["c"] == 0 assert db.fetchone("SELECT COUNT(*) AS c FROM ledger_entries")["c"] == 0 db.close() def test_delete_open_group_refused(tmp_path, monkeypatch) -> None: monkeypatch.setenv("MODE", "SIM") db = Database(tmp_path / "del_open.db") monkeypatch.setattr("app.api.trades.get_db", lambda: db) with db._lock: db._conn.execute( """INSERT INTO groups(group_id, status, open_at_ms) VALUES ('G-OPEN', 'open', 1)""" ) db._conn.commit() with pytest.raises(HTTPException) as ei: asyncio.run(delete_group("G-OPEN", _user="t")) assert ei.value.status_code == 409 assert db.fetchone("SELECT COUNT(*) AS c FROM groups")["c"] == 1 db.close() def test_delete_active_position_refused(tmp_path, monkeypatch) -> None: monkeypatch.setenv("MODE", "SIM") db = Database(tmp_path / "del_pos.db") monkeypatch.setattr("app.api.trades.get_db", lambda: db) _seed_closed(db, "G-POS") with db._lock: # status closed but still referenced (edge) db._conn.execute( "UPDATE positions SET group_id=?, status='open' WHERE id=1", ("G-POS",), ) db._conn.commit() with pytest.raises(HTTPException) as ei: asyncio.run(delete_group("G-POS", _user="t")) assert ei.value.status_code == 409 assert db.fetchone("SELECT COUNT(*) AS c FROM groups")["c"] == 1 db.close()