| 1 | package main
|
|---|
| 2 |
|
|---|
| 3 | import (
|
|---|
| 4 | "fmt"
|
|---|
| 5 | "strconv"
|
|---|
| 6 | "strings"
|
|---|
| 7 |
|
|---|
| 8 | "bp_project/server/db"
|
|---|
| 9 | )
|
|---|
| 10 |
|
|---|
| 11 | // ShowBalance prints the logged-in user's balances.
|
|---|
| 12 | func ShowBalance(s *Session) {
|
|---|
| 13 | // P7 view v_trader_balances: cash is split into what is free and what
|
|---|
| 14 | // is reserved by the user's open buy orders.
|
|---|
| 15 | var avail, reserved, invested float64
|
|---|
| 16 | err := db.DB.QueryRow(
|
|---|
| 17 | `SELECT available_balance, reserved_balance, invested_balance
|
|---|
| 18 | FROM v_trader_balances WHERE user_id = $1`,
|
|---|
| 19 | s.UserID,
|
|---|
| 20 | ).Scan(&avail, &reserved, &invested)
|
|---|
| 21 | if err != nil {
|
|---|
| 22 | fmt.Println("Error:", err)
|
|---|
| 23 | return
|
|---|
| 24 | }
|
|---|
| 25 | fmt.Printf("\n Available: %.4f USD\n", avail)
|
|---|
| 26 | fmt.Printf(" Reserved : %.4f USD (open buy orders)\n", reserved)
|
|---|
| 27 | fmt.Printf(" Invested : %.4f USD\n", invested)
|
|---|
| 28 | fmt.Printf(" Total : %.4f USD\n", avail+reserved+invested)
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | // Deposit - UC0003
|
|---|
| 32 | // Transactional: updates users.available_balance and inserts a ledger row.
|
|---|
| 33 | func Deposit(s *Session) {
|
|---|
| 34 | fmt.Println("\n-- Deposit virtual funds --")
|
|---|
| 35 | amtStr := prompt("Amount (USD): ")
|
|---|
| 36 | amt, err := strconv.ParseFloat(amtStr, 64)
|
|---|
| 37 | if err != nil || amt <= 0 {
|
|---|
| 38 | fmt.Println("Invalid amount.")
|
|---|
| 39 | return
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | tx, err := db.DB.Begin()
|
|---|
| 43 | if err != nil {
|
|---|
| 44 | fmt.Println("Error:", err)
|
|---|
| 45 | return
|
|---|
| 46 | }
|
|---|
| 47 | defer tx.Rollback()
|
|---|
| 48 |
|
|---|
| 49 | if _, err := tx.Exec(
|
|---|
| 50 | `UPDATE users
|
|---|
| 51 | SET available_balance = available_balance + $1,
|
|---|
| 52 | updated_at = now()
|
|---|
| 53 | WHERE id = $2`,
|
|---|
| 54 | amt, s.UserID,
|
|---|
| 55 | ); err != nil {
|
|---|
| 56 | fmt.Println("Error:", err)
|
|---|
| 57 | return
|
|---|
| 58 | }
|
|---|
| 59 | if _, err := tx.Exec(
|
|---|
| 60 | `INSERT INTO transactions (user_id, type, amount, currency, description)
|
|---|
| 61 | VALUES ($1, 'deposit', $2, 'USD', 'Virtual deposit')`,
|
|---|
| 62 | s.UserID, amt,
|
|---|
| 63 | ); err != nil {
|
|---|
| 64 | fmt.Println("Error:", err)
|
|---|
| 65 | return
|
|---|
| 66 | }
|
|---|
| 67 | if err := tx.Commit(); err != nil {
|
|---|
| 68 | fmt.Println("Error:", err)
|
|---|
| 69 | return
|
|---|
| 70 | }
|
|---|
| 71 | fmt.Printf("Deposited %.4f USD.\n", amt)
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | // ShowTransactions lists the last 20 ledger entries for the user.
|
|---|
| 75 | func ShowTransactions(s *Session) {
|
|---|
| 76 | rows, err := db.DB.Query(
|
|---|
| 77 | `SELECT created_at, type, amount, currency, COALESCE(description, '')
|
|---|
| 78 | FROM transactions
|
|---|
| 79 | WHERE user_id = $1
|
|---|
| 80 | ORDER BY created_at DESC
|
|---|
| 81 | LIMIT 20`,
|
|---|
| 82 | s.UserID,
|
|---|
| 83 | )
|
|---|
| 84 | if err != nil {
|
|---|
| 85 | fmt.Println("Error:", err)
|
|---|
| 86 | return
|
|---|
| 87 | }
|
|---|
| 88 | defer rows.Close()
|
|---|
| 89 |
|
|---|
| 90 | fmt.Println()
|
|---|
| 91 | fmt.Printf(" %-20s %-8s %12s %-3s %s\n", "When", "Type", "Amount", "Cur", "Description")
|
|---|
| 92 | fmt.Println(" " + strings.Repeat("-", 70))
|
|---|
| 93 | for rows.Next() {
|
|---|
| 94 | var when, typ, cur, desc string
|
|---|
| 95 | var amt float64
|
|---|
| 96 | if err := rows.Scan(&when, &typ, &amt, &cur, &desc); err != nil {
|
|---|
| 97 | fmt.Println("scan error:", err)
|
|---|
| 98 | return
|
|---|
| 99 | }
|
|---|
| 100 | fmt.Printf(" %-20s %-8s %12.4f %-3s %s\n", when[:19], typ, amt, cur, desc)
|
|---|
| 101 | }
|
|---|
| 102 | }
|
|---|