from __future__ import annotations import json from exec_mcp import repo, storage from exec_mcp.services_orders import cancel_all_orders, get_open_orders from fastapi import HTTPException class _FakeTrading: def cancel_order(self, order_id, version=2): return True class _FakeClient: def __init__(self): self.trading = _FakeTrading() def test_bulk_tools_match_open_status_case_and_client_id(tmp_path, monkeypatch): db_path = tmp_path / "exec.sqlite3" monkeypatch.setattr(storage, "DB_PATH", db_path) storage.init_db() monkeypatch.setattr("exec_mcp.services_orders._get_client", lambda account_id: _FakeClient()) repo.create_account(display_name="strategy", venue="bitstamp", venue_account_ref="ref-1", api_key="k", api_secret="s") account_id = repo.list_accounts(enabled_only=False)[0]["id"] with storage.get_connection() as conn: conn.execute( """ INSERT INTO order_records (id, account_id, market, side, order_type, amount, price, expire_time, status, bitstamp_order_id, client_id, client_order_id, raw_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( "rec-1", account_id, "xrpusd", "sell", "limit", "10", "2.00", None, "Open", "1994292738961409", "test", None, json.dumps({"id": "1994292738961409", "status": "Open"}), "2026-04-09T08:20:50+00:00", "2026-04-09T08:20:50+00:00", ), ) conn.commit() open_orders = get_open_orders(account_id=account_id, client_id="test") assert open_orders["ok"] is True assert len(open_orders["orders"]) == 1 assert open_orders["orders"][0]["bitstamp_order_id"] == "1994292738961409" cancelled = cancel_all_orders(account_id=account_id, client_id="test") assert cancelled["ok"] is True assert cancelled["count"] == 1 assert cancelled["cancelled"][0]["ok"] is True assert cancelled["cancelled"][0]["order_id"] == "1994292738961409" def test_cancel_all_orders_skips_missing_orders_and_continues(tmp_path, monkeypatch): db_path = tmp_path / "exec.sqlite3" monkeypatch.setattr(storage, "DB_PATH", db_path) storage.init_db() repo.create_account(display_name="strategy", venue="bitstamp", venue_account_ref="ref-1", api_key="k", api_secret="s") account_id = repo.list_accounts(enabled_only=False)[0]["id"] with storage.get_connection() as conn: for idx, order_id in enumerate(["missing-order", "ok-order"]): conn.execute( """ INSERT INTO order_records (id, account_id, market, side, order_type, amount, price, expire_time, status, bitstamp_order_id, client_id, client_order_id, raw_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( f"rec-{idx}", account_id, "xrpusd", "sell", "limit", "10", "2.00", None, "open", order_id, None, None, json.dumps({"id": order_id, "status": "Open"}), "2026-04-09T08:20:50+00:00", "2026-04-09T08:20:50+00:00", ), ) conn.commit() def fake_cancel_order(*, account_id: str, order_id): if order_id == "missing-order": raise HTTPException(status_code=400, detail="Order not found") with storage.get_connection() as conn: conn.execute( "UPDATE order_records SET status = ?, updated_at = ? WHERE bitstamp_order_id = ?", ("cancelled", "2026-04-09T09:00:00+00:00", order_id), ) conn.commit() return {"ok": True, "order_id": order_id, "raw": {"id": order_id}} monkeypatch.setattr("exec_mcp.services_orders.cancel_order", fake_cancel_order) result = cancel_all_orders(account_id=account_id) assert result["ok"] is True assert result["count"] == 2 assert result["cancelled"][0]["status"] == "missing" assert result["cancelled"][1]["ok"] is True open_orders = get_open_orders(account_id=account_id) assert open_orders["orders"] == []