fix: add missing postgres implementations for get_portfolio_by_name_and_user and insert_ledger_trade

- add get_portfolio_by_name_and_user to PortfolioRepository protocol and
  PostgresPortfolioRepository; resolves AttributeError on all CLI name+user
  resolution paths (REQ-017)
- add insert_ledger_trade to PortfolioRepository protocol and
  PostgresPortfolioRepository; resolves HTTP 500 on POST
  /v1/assets/{asset_id}/ledger/trades (REQ-008)
- add _row_to_ledger_trade static helper; uses INSERT ... ON CONFLICT DO
  NOTHING RETURNING to return (LedgerTrade, created: bool)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 04:05:48 +00:00
co-authored by Claude Sonnet 4.6
parent b9e3bddb34
commit b155eeff7d
2 changed files with 82 additions and 1 deletions
+67
View File
@@ -1169,6 +1169,73 @@ class PostgresPortfolioRepository:
rows = cur.fetchall()
return [self._row_to_ledger_entry(row) for row in rows]
def insert_ledger_trade(
self,
*,
asset_id: str,
order_id: str,
execution_id: str,
side: str,
quantity: float,
price: float,
executed_at,
fee_amount: float = 0.0,
tax_amount: float = 0.0,
) -> tuple:
self.ensure_schema()
with self._connect().cursor() as cur:
cur.execute(
"""
INSERT INTO ledger_trades
(asset_id, order_id, execution_id, side, quantity, price,
fee_amount, tax_amount, executed_at)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
ON CONFLICT ON CONSTRAINT uq_ledger_trades_idempotency DO NOTHING
RETURNING
ledger_entry_id, asset_id, order_id, execution_id, side,
quantity::float8, price::float8,
fee_amount::float8, tax_amount::float8,
executed_at, recorded_at
""",
(asset_id, order_id, execution_id, side, quantity, price,
fee_amount, tax_amount, executed_at),
)
row = cur.fetchone()
if row is not None:
return self._row_to_ledger_trade(row), True
# Conflict: fetch existing record
cur.execute(
"""
SELECT
ledger_entry_id, asset_id, order_id, execution_id, side,
quantity::float8, price::float8,
fee_amount::float8, tax_amount::float8,
executed_at, recorded_at
FROM ledger_trades
WHERE asset_id = %s AND order_id = %s AND execution_id = %s
""",
(asset_id, order_id, execution_id),
)
row = cur.fetchone()
return self._row_to_ledger_trade(row), False
@staticmethod
def _row_to_ledger_trade(row) -> "LedgerTrade":
from app.domain.models import LedgerTrade
return LedgerTrade(
ledger_entry_id=row[0],
asset_id=row[1],
order_id=row[2],
execution_id=row[3],
side=row[4],
quantity=float(row[5]),
price=float(row[6]),
fee_amount=float(row[7]),
tax_amount=float(row[8]),
executed_at=row[9],
recorded_at=row[10],
)
def reset(self, portfolio_id: str) -> Portfolio:
self.ensure_schema()
with self._connect().cursor() as cur: