3
3
from decimal import Decimal
4
4
from uuid import uuid4
5
5
from transactions .enums import TransactionType , TransactionStatus
6
+ from transactions .exceptions import InsufficientBalanceError
6
7
from transactions .tasks import do_withdraw
7
8
8
9
@@ -21,18 +22,46 @@ def __str__(self):
21
22
22
23
def save (self , * args , ** kwargs ):
23
24
if self .status == TransactionStatus .SUCCESS and not self .is_processed :
24
- if self .type == TransactionType .DEPOSIT :
25
- self ._handle_deposit ()
26
- elif self .type == TransactionType .WITHDRAWAL :
27
- self ._handle_withdrawal ()
28
- self .is_processed = True
29
- return super ().save (* args , ** kwargs )
30
-
31
- def _handle_deposit (self ):
32
- self .user .balance += Decimal (self .amount )
33
- self .user .save ()
25
+ self ._process_transaction ()
26
+ super ().save (* args , ** kwargs )
27
+
28
+ def _process_transaction (self ):
29
+ amount = Decimal (self .amount )
30
+
31
+ if self .type == TransactionType .DEPOSIT :
32
+ self ._adjust_balance (amount )
33
+ elif self .type in {TransactionType .WITHDRAWAL , TransactionType .COST }:
34
+ self ._adjust_balance (- amount )
35
+ elif self .type == TransactionType .CHARGE :
36
+ self ._adjust_balance (amount )
37
+
38
+ self .is_processed = True
34
39
35
- def _handle_withdrawal (self ):
36
- self .user .balance -= Decimal (self .amount )
40
+ if self .type == TransactionType .WITHDRAWAL :
41
+ do_withdraw .delay (self .user .id , self .id )
42
+
43
+ def _adjust_balance (self , amount ):
44
+ if amount < 0 and self .user .balance < abs (amount ):
45
+ raise InsufficientBalanceError
46
+ self .user .balance += amount
37
47
self .user .save ()
38
- do_withdraw .delay (self .user .id , self .id )
48
+
49
+ @classmethod
50
+ def transfer (cls , sender , receiver , amount ) -> tuple :
51
+ """Transfer money from sender to receiver."""
52
+ if sender .balance < amount :
53
+ raise InsufficientBalanceError
54
+
55
+ sender_transaction = cls .objects .create (
56
+ user = sender ,
57
+ amount = amount ,
58
+ type = TransactionType .COST ,
59
+ status = TransactionStatus .SUCCESS ,
60
+ )
61
+ receiver_transaction = cls .objects .create (
62
+ user = receiver ,
63
+ amount = amount ,
64
+ type = TransactionType .CHARGE ,
65
+ status = TransactionStatus .SUCCESS ,
66
+ )
67
+ return sender_transaction , receiver_transaction
0 commit comments