source: docs/P3-UseCaseModel/UseCase0004.md@ b715712

main
Last change on this file since b715712 was b715712, checked in by Stefan <trsunovstefan@…>, 8 weeks ago

Add the server side and configuration

  • Property mode set to 100644
File size: 3.0 KB
RevLine 
[d8ce4e2]1# Use-case 0004 — Place market BUY order
2
3**Initiating actor:** Trader
4
5**Other actors:** Market Simulator (indirect — supplies the current price via `market_trades`).
6
7A Trader buys a crypto asset at the current market price. The operation touches five tables (`orders`, `users`, `holdings`, `transactions`, `market_trades`) and must either all succeed or all roll back.
8
9## Scenario
10
111. Trader chooses "Place market BUY order".
122. System lists the available markets with their latest price:
13
14 ```sql
15 SELECT m.id, c.symbol, m.quote_currency, COALESCE(lp.price, 0)
16 FROM project.markets m
17 JOIN project.crypto c ON c.id = m.crypto_id
18 LEFT JOIN project.v_latest_prices lp ON lp.market_id = m.id
19 WHERE m.is_active = true
20 ORDER BY c.symbol;
21 ```
223. Trader enters a market symbol, e.g. `ETH`.
234. System resolves the market and looks up the latest price:
24
25 ```sql
26 SELECT m.id, c.id AS crypto_id, c.symbol, m.quote_currency
27 FROM project.markets m
28 JOIN project.crypto c ON c.id = m.crypto_id
29 WHERE upper(c.symbol) = upper($1) AND m.is_active = true;
30
31 SELECT price FROM project.v_latest_prices WHERE market_id = $2;
32 ```
335. Trader enters a quantity.
346. System computes notional = quantity × price, opens a transaction, and does:
35
36 ```sql
37 BEGIN;
38
39 INSERT INTO project.orders
40 (user_id, market_id, side, type, status, quantity, price, executed_at)
41 VALUES
42 ($user_id, $market_id, 'buy', 'market', 'executed', $qty, $price, now())
43 RETURNING id; -- captured as $order_id
44
45 SELECT available_balance FROM project.users WHERE id = $user_id FOR UPDATE;
46 -- abort if available_balance < notional
47
48 UPDATE project.users
49 SET available_balance = available_balance - $notional,
50 invested_balance = invested_balance + $notional,
51 updated_at = now()
52 WHERE id = $user_id;
53
54 -- Upsert holding with running weighted-average price:
55 SELECT quantity, avg_price
56 FROM project.holdings
57 WHERE user_id = $user_id AND crypto_id = $crypto_id
58 FOR UPDATE;
59
60 -- Either INSERT (new holding) or UPDATE (existing), computing
61 -- new_avg = (old_qty*old_avg + $qty*$price) / (old_qty + $qty)
62
63 INSERT INTO project.transactions
64 (user_id, type, amount, currency, related_order, description)
65 VALUES
66 ($user_id, 'buy', -$notional, 'USD', $order_id, 'Market buy ...');
67
68 INSERT INTO project.market_trades
69 (market_id, executed_at, price, quantity, side, source)
70 VALUES
71 ($market_id, now(), $price, $qty, 'buy', 'user');
72
73 COMMIT;
74 ```
757. System confirms: `Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)`.
76
77### Alternate flow 6a — insufficient funds
78
79If `available_balance < notional`, the entire transaction rolls back and system shows "Insufficient funds: need X, have Y."
80
81### Alternate flow 4a — market not found
82
83If the entered symbol does not match any active market, system shows "market X not found" and returns to the authenticated menu without opening a transaction.
Note: See TracBrowser for help on using the repository browser.