diff options
Diffstat (limited to 'app/app_wallet.py')
-rw-r--r-- | app/app_wallet.py | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/app/app_wallet.py b/app/app_wallet.py new file mode 100644 index 0000000..9dffbd5 --- /dev/null +++ b/app/app_wallet.py | |||
@@ -0,0 +1,95 @@ | |||
1 | # UGE / L2 / Intro to relational databases / Python project prototype | ||
2 | # Author: Pacien TRAN-GIRARD | ||
3 | # Licence: EUPL-1.2 | ||
4 | |||
5 | from decimal import Decimal | ||
6 | |||
7 | from fastapi import APIRouter, Form, Depends, status | ||
8 | |||
9 | from embrace.exceptions import IntegrityError | ||
10 | from psycopg2.errors import CheckViolation | ||
11 | from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE | ||
12 | |||
13 | from app_sessions import UserSession | ||
14 | from app_database import db_transaction | ||
15 | |||
16 | |||
17 | router = APIRouter() | ||
18 | |||
19 | |||
20 | # TODO: add paging for the transaction history | ||
21 | @router.get('/wallet') | ||
22 | def wallet( | ||
23 | session: UserSession=Depends(UserSession.authenticated), | ||
24 | ): | ||
25 | with db_transaction() as tx: | ||
26 | history = tx.fetch_transactions(user_id=session.get_user_id()) | ||
27 | return list(history) | ||
28 | |||
29 | |||
30 | @router.post('/wallet/transfer') | ||
31 | def wallet_transfer( | ||
32 | session: UserSession=Depends(UserSession.authenticated), | ||
33 | recipient: str=Form(...), | ||
34 | amount: Decimal=Form(...), | ||
35 | ): | ||
36 | if amount <= 0: | ||
37 | return 'error: Invalid transaction amount.' | ||
38 | |||
39 | try: | ||
40 | with db_transaction(ISOLATION_LEVEL_SERIALIZABLE) as tx: | ||
41 | recipient_user = tx.fetch_account_username(username=recipient) | ||
42 | if recipient_user is None: | ||
43 | raise LookupError('Could not find recipient') | ||
44 | |||
45 | tx.transfer( | ||
46 | from_user_id=session.get_user_id(), | ||
47 | to_user_id=recipient_user.id, | ||
48 | amount=amount, | ||
49 | fee=amount * Decimal(0.10)) | ||
50 | |||
51 | return 'Your business is appreciated.' | ||
52 | |||
53 | except LookupError as exception: | ||
54 | return 'error: ' + str(exception) | ||
55 | |||
56 | except IntegrityError as exception: | ||
57 | if isinstance(exception.__cause__, CheckViolation): | ||
58 | return 'error: Insufficient funds.' | ||
59 | else: | ||
60 | raise exception | ||
61 | |||
62 | |||
63 | @router.post('/wallet/deposit') | ||
64 | def wallet_deposit( | ||
65 | session: UserSession=Depends(UserSession.authenticated), | ||
66 | amount: Decimal=Form(...), | ||
67 | ): | ||
68 | if amount <= 0: | ||
69 | return 'error: Invalid transaction amount.' | ||
70 | |||
71 | with db_transaction(ISOLATION_LEVEL_SERIALIZABLE) as tx: | ||
72 | tx.deposit(user_id=session.get_user_id(), amount=amount) | ||
73 | |||
74 | return 'Your business is appreciated.' | ||
75 | |||
76 | |||
77 | @router.post('/wallet/withdraw') | ||
78 | def wallet_withdraw( | ||
79 | session: UserSession=Depends(UserSession.authenticated), | ||
80 | amount: Decimal=Form(...), | ||
81 | ): | ||
82 | if amount <= 0: | ||
83 | return 'error: Invalid transaction amount.' | ||
84 | |||
85 | try: | ||
86 | with db_transaction(ISOLATION_LEVEL_SERIALIZABLE) as tx: | ||
87 | tx.withdraw(user_id=session.get_user_id(), amount=amount) | ||
88 | |||
89 | return 'Annnnnd... It\'s gone.' | ||
90 | |||
91 | except IntegrityError as exception: | ||
92 | if isinstance(exception.__cause__, CheckViolation): | ||
93 | return 'error: Insufficient funds.' | ||
94 | else: | ||
95 | raise exception | ||