feat: persist skipped ledger fills
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
df0258bc36
commit
76cde2edd0
@@ -0,0 +1,132 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import UTC, datetime
|
||||
from types import SimpleNamespace
|
||||
from uuid import UUID
|
||||
|
||||
from trex_core.application.ledger_skip import LedgerSkipRecord
|
||||
from trex_core.runtime import cli
|
||||
|
||||
|
||||
def _cfg():
|
||||
return SimpleNamespace(dsn="postgresql://x/y", rabbitmq=None)
|
||||
|
||||
|
||||
def _record(*, status="unresolved", resolution_reason=None):
|
||||
return LedgerSkipRecord(
|
||||
skip_key="ledger-skip:inst-1:slot-1:sell:O-1:E-1:missing_execution_id",
|
||||
instance_key="inst-1",
|
||||
slot_id=UUID("00000000-0000-0000-0000-000000000001"),
|
||||
portfolio_id="PF-1",
|
||||
symbol="005930",
|
||||
order_id="O-1",
|
||||
execution_id="E-1",
|
||||
side="sell",
|
||||
qty=10.0,
|
||||
price=70000.0,
|
||||
executed_at=datetime(2026, 8, 24, 0, 1, 2, tzinfo=UTC),
|
||||
order_venue="SOR",
|
||||
execution_venue="unknown",
|
||||
skip_reason="missing_execution_id",
|
||||
status=status,
|
||||
resolution_reason=resolution_reason,
|
||||
resolved_at=(
|
||||
datetime(2026, 8, 24, 0, 5, 0, tzinfo=UTC)
|
||||
if status == "resolved"
|
||||
else None
|
||||
),
|
||||
created_at=datetime(2026, 8, 24, 0, 1, 2, tzinfo=UTC),
|
||||
updated_at=datetime(2026, 8, 24, 0, 5, 0, tzinfo=UTC),
|
||||
)
|
||||
|
||||
|
||||
def test_ledger_skips_parser_accepts_list_and_resolve():
|
||||
parser = cli._build_parser()
|
||||
args = parser.parse_args(["ledger", "skips", "list", "--status", "all"])
|
||||
assert args.ledger_cmd == "skips"
|
||||
assert args.ledger_skips_cmd == "list"
|
||||
args = parser.parse_args(["ledger", "skips", "resolve", "--skip-key", "abc"])
|
||||
assert args.ledger_skips_cmd == "resolve"
|
||||
|
||||
|
||||
def test_ledger_skips_list_outputs_records(monkeypatch, capsys):
|
||||
class _Store:
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
pass
|
||||
|
||||
def list_records(self, **_kwargs):
|
||||
return [_record()]
|
||||
|
||||
monkeypatch.setattr(
|
||||
"trex_core.adapters.persistence.ledger_skip_store.PostgreSQLLedgerSkipStore",
|
||||
_Store,
|
||||
)
|
||||
args = SimpleNamespace(
|
||||
cmd="ledger",
|
||||
ledger_cmd="skips",
|
||||
ledger_skips_cmd="list",
|
||||
date="2026-08-24",
|
||||
portfolio_id="PF-1",
|
||||
status="unresolved",
|
||||
limit=10,
|
||||
instance="inst-1",
|
||||
config=None,
|
||||
config_path=None,
|
||||
env_file=None,
|
||||
json=True,
|
||||
timeout=10.0,
|
||||
)
|
||||
|
||||
rc = cli._cmd_ledger_skips_list(args, _cfg())
|
||||
|
||||
assert rc == 0
|
||||
out = json.loads(capsys.readouterr().out)
|
||||
assert out["count"] == 1
|
||||
assert out["records"][0]["skip_reason"] == "missing_execution_id"
|
||||
|
||||
|
||||
def test_ledger_skips_resolve_marks_record_and_emits_alert(monkeypatch, capsys):
|
||||
class _Store:
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
pass
|
||||
|
||||
def resolve_by_key(self, skip_key, *, resolution_reason):
|
||||
assert skip_key == "abc"
|
||||
return _record(status="resolved", resolution_reason=resolution_reason)
|
||||
|
||||
published = []
|
||||
|
||||
class _Emitter:
|
||||
def publish_alarm(self, code, title, *, fields=None, severity="critical"):
|
||||
published.append((code, severity, fields))
|
||||
|
||||
class _Transport:
|
||||
def close(self):
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(
|
||||
"trex_core.adapters.persistence.ledger_skip_store.PostgreSQLLedgerSkipStore",
|
||||
_Store,
|
||||
)
|
||||
monkeypatch.setattr(cli, "_default_alarm_emitter", lambda cfg: (_Emitter(), _Transport()))
|
||||
args = SimpleNamespace(
|
||||
cmd="ledger",
|
||||
ledger_cmd="skips",
|
||||
ledger_skips_cmd="resolve",
|
||||
skip_key="abc",
|
||||
reason="operator_reconciled",
|
||||
instance="inst-1",
|
||||
config=None,
|
||||
config_path=None,
|
||||
env_file=None,
|
||||
json=True,
|
||||
timeout=10.0,
|
||||
)
|
||||
|
||||
rc = cli._cmd_ledger_skips_resolve(args, _cfg())
|
||||
|
||||
assert rc == 0
|
||||
out = json.loads(capsys.readouterr().out)
|
||||
assert out["result"] == "resolved"
|
||||
assert published[0][0] == "ledger_skip_resolved"
|
||||
Reference in New Issue
Block a user