| | 1 | = Use-case 0006 — View portfolio and transaction history = |
| | 2 | |
| | 3 | '''Initiating actor:''' Trader |
| | 4 | |
| | 5 | '''Other actors:''' — |
| | 6 | |
| | 7 | A Trader inspects their current holdings, unrealised P/L, cash balance and recent ledger. |
| | 8 | |
| | 9 | == Scenario == |
| | 10 | |
| | 11 | === Portfolio === |
| | 12 | |
| | 13 | 1. Trader chooses "View portfolio". |
| | 14 | 2. System queries the `v_portfolio` view: |
| | 15 | |
| | 16 | {{{ |
| | 17 | SELECT symbol, |
| | 18 | quantity, |
| | 19 | COALESCE(reserved_quantity, 0), |
| | 20 | COALESCE(available_quantity, quantity), |
| | 21 | COALESCE(avg_price, 0), |
| | 22 | COALESCE(current_price, 0), |
| | 23 | COALESCE(market_value, 0), |
| | 24 | COALESCE(unrealized_pnl, 0) |
| | 25 | FROM project.v_portfolio |
| | 26 | WHERE user_id = $1 |
| | 27 | AND quantity > 0 |
| | 28 | ORDER BY symbol; |
| | 29 | }}} |
| | 30 | |
| | 31 | `reserved_quantity` is the amount committed to the Trader's own open sell |
| | 32 | orders (see UseCase0005); `available_quantity` is what is |
| | 33 | actually free to sell right now. |
| | 34 | |
| | 35 | 3. System displays the rows and a computed summary: |
| | 36 | |
| | 37 | {{{ |
| | 38 | SELECT available_balance, invested_balance |
| | 39 | FROM project.users |
| | 40 | WHERE id = $1; |
| | 41 | }}} |
| | 42 | |
| | 43 | === Transaction history === |
| | 44 | |
| | 45 | 1. Trader chooses "View transaction history". |
| | 46 | 2. System queries the last 20 ledger entries: |
| | 47 | |
| | 48 | {{{ |
| | 49 | SELECT created_at, type, amount, currency, COALESCE(description, '') |
| | 50 | FROM project.transactions |
| | 51 | WHERE user_id = $1 |
| | 52 | ORDER BY created_at DESC |
| | 53 | LIMIT 20; |
| | 54 | }}} |
| | 55 | |
| | 56 | === Reference — how `v_portfolio` is defined === |
| | 57 | |
| | 58 | {{{ |
| | 59 | CREATE OR REPLACE VIEW project.v_portfolio AS |
| | 60 | SELECT h.user_id, |
| | 61 | c.symbol, |
| | 62 | h.quantity, |
| | 63 | h.reserved_quantity, |
| | 64 | (h.quantity - h.reserved_quantity) AS available_quantity, |
| | 65 | h.avg_price, |
| | 66 | lp.price AS current_price, |
| | 67 | (h.quantity * lp.price) AS market_value, |
| | 68 | (h.quantity * (lp.price - h.avg_price)) AS unrealized_pnl |
| | 69 | FROM project.holdings h |
| | 70 | JOIN project.crypto c ON c.id = h.crypto_id |
| | 71 | LEFT JOIN project.markets m |
| | 72 | ON m.crypto_id = c.id AND m.quote_currency = 'USD' |
| | 73 | LEFT JOIN project.v_latest_prices lp |
| | 74 | ON lp.market_id = m.id; |
| | 75 | }}} |