· 5 years ago · Aug 03, 2020, 08:02 AM
1# Write your code here
2import random
3import sqlite3
4
5'''
6I've tested your code all by myself and didn't find any problems at all
7I think HyperSkill is based on the output of your programme, and if it's not right (even within a one letter), they throw an errror
8And there is a small mark in the 'transfer_success' method. You do not transfer money to the right account
9But, during reding your code I found some mistakes and by making them, You really complicate your life. So I made some remarks that I think a very important on the way of becoming a professional Python developer. Here are they:
10
111. Too much functional decomposition. you can do it in few methods/functions
122. Some unnecessary code (DRY - Don't Repeat Yourself):
13 1. You can transform this (the one below) to this! (the one below), thus You can shorten your code
14
15 if <something>: return <something>
16 return True
17 else:
18 return False
19
20 2. or some parts like two Luhn-algorithm methods (just transform it into one!) and
21 3. reusing sqlite3.connection.commit() more times than needed
22 4. You can also fetch the data from the 'select' statement by using to lines of code
23 consider this:
24 <variable> = self.cursor.execute('<SQL statement>').fetchone()
25 instead of this:
26 <variable> = self.cursor.execute('<SQL statement>')
27 <variable> = self.cursor.fetchone()
28 this will save you much more code (and nerves ???)
29
30
31I don't make You follow these recomendations, I just want to help and point You to some mistakes I've done before too.
32Again, it's only mine point of view, you can whether take advice, or skip it - it's all about YOU
33Do everything in here at your peril
34I haven't done any changes in code (maybe added a few newlines), just commented it, like this
35'''
36
37
38class BankingSystem:
39
40 def __init__(self):
41 self.pin = ''
42 self.card_num = ''
43 self.conn = None
44 self.cur = None
45 self.amt_transfer = 0
46
47
48 def database(self):
49 self.conn = sqlite3.connect('card.s3db')
50 self.cur = self.conn.cursor()
51 self.cur.execute('create table if not exists card(id integer, number text, pin text, balance integer default 0)')
52 self.conn.commit()
53
54
55 def store_data(self): #
56 self.cur.execute(f'insert into card(number, pin) values({self.card_num},{self.pin})') # Remarks 1.
57 self.conn.commit() #
58
59
60 def checksum_add_luhn(self): #
61 raw_card_num = '400000' + str(random.randint(100000000, 1000000000)) #
62 raw_card_num_list_convert = list(raw_card_num) #
63 new_number_card = '' #
64 sum_digits = 0 #
65 card_n = '' #
66 for (index, digit) in enumerate(raw_card_num_list_convert): #
67 if index % 2 == 0: #
68 digit = str(int(digit) * 2) # Remarks 2.2
69 if int(digit) > 9: #
70 digit = str(int(digit) - 9) #
71 new_number_card += digit #
72 sum_digits += int(digit) #
73 last_digit = 0 #
74 while (sum_digits + last_digit) % 10 != 0: #
75 last_digit += 1 #
76 card_n = raw_card_num + str(last_digit) #
77 return card_n #
78
79
80 def generate_card_num(self): #
81 self.card_num = self.checksum_add_luhn() # Remarks 1.
82 return self.card_num #
83
84
85 def generate_pin(self): #
86 self.pin = str(random.randint(0, 9999)).zfill(4) # Remarks 1.
87 return self.pin #
88
89
90 def create_acc(self): #
91 print(f"\nYour card has been created\nYour card number:\n{self.generate_card_num()}\nYour card PIN:\n{self.generate_pin()}") # Remarks 1.
92 self.store_data() #
93
94
95 def log_in_acc(self):
96 self.ask_card_num = input("\nEnter you card number:\n")
97 self.ask_pin = input("Enter your PIN:\n")
98 login = self.cur.execute(f'select number, pin from card where number = {self.ask_card_num} and pin = {self.ask_pin}') # Remarks 2.4
99 login_ = self.cur.fetchone() #
100 if login_ is not None:
101 print("\nYou have successfully logged in!")
102 return self.log_in_success()
103 else:
104 print("Wrong card number or PIN!")
105
106
107 def log_in_success(self):
108 while True:
109 choose_option_lis = input("""\n1. Balance\n2. Add income\n3. Do transfer\n4. Close account\n5. Log out\n0. Exit\n""")
110 if choose_option_lis == '1':
111 self.fetch_balance()
112 elif choose_option_lis == '2':
113 self.add_income()
114 elif choose_option_lis == '3':
115 self.do_transfer()
116 elif choose_option_lis == '4':
117 self.close_account()
118 elif choose_option_lis == '5':
119 print("\nYou have successfully logged out!")
120 break
121 else:
122 print('Bye!') # can change this by "quit('Bye!')" (this will print the message and quit)
123 quit() #
124
125
126 def fetch_balance(self):
127 bal = self.cur.execute(f'select balance from card where number = {self.card_num} and pin = {self.pin}') # Remarks 1.
128 bal = self.cur.fetchone() # Remarks 2.4
129 print('\nBalance:', bal[0])
130
131
132 def add_income(self): # Remarks 1.
133 amt = int(input('\nEnter income:\n')) #
134 update_amt = self.cur.execute(f'update card set balance = balance + {amt} where number = {self.ask_card_num} and pin = {self.ask_pin}')
135 update_amt_ = self.conn.commit()
136 print("Income was added!")
137
138
139 # For do transfer option
140 def check_luhn(self, ask_receiver_card_num): #
141 ask_card_num_strip = ask_receiver_card_num[0:15] #
142 ask_card_num_strip_list_convert = list(ask_card_num_strip) #
143 new_number_card = '' #
144 sum_digits = 0 #
145 card_n = '' #
146 for (index, digit) in enumerate(ask_card_num_strip_list_convert): #
147 if index % 2 == 0: #
148 digit = str(int(digit) * 2) #
149 if int(digit) > 9: #
150 digit = str(int(digit) - 9) # Remarks 2.2
151 new_number_card += digit #
152 sum_digits += int(digit) #
153 last_digit = 0 #
154 while (sum_digits + last_digit) % 10 != 0: #
155 last_digit += 1 #
156 card_n = ask_card_num_strip + str(last_digit) #
157 #
158 if ask_receiver_card_num == card_n: #
159 return True #
160 else: # Remarks 2.1
161 return False #
162
163
164 def check_card_existence(self):
165 check_card_num_exist = self.cur.execute(f'select number from card where number = {self.ask_receiver_card_num}') # Remarks 1.
166 check_card_num_exist_ = self.cur.fetchone() # Remarks 2.4
167 if check_card_num_exist_ is not None: #
168 return True #
169 else: # Remarks 2.1
170 return False #
171
172
173 def amt_avail(self):
174 sender_avail_money = self.cur.execute(f'select balance from card where number = {self.ask_card_num} and pin = {self.ask_pin}') # Remarks 2.4
175 sender_avail_money = self.cur.fetchone() #
176 sender_avail_money_ = int(sender_avail_money[0]) # Remarks 1.
177 return sender_avail_money_ #
178
179
180 def transfer_success(self):
181 upd_rec_acc = self.cur.execute(f'update card set balance = balance + {self.amt_transfer} where number = {self.ask_receiver_card_num}' ) # Remarks 1.
182 upd_rec_acc_ = self.conn.commit() #
183 # Remarks 2.3
184 upd_sen_acc = self.cur.execute(f'update card set balance = balance - {self.amt_transfer} where number = {self.card_num}') # IMPORTANT
185 # upd_sen_acc = self.cur.execute(f'update card set balance = balance - {self.amt_transfer} where number = {self.ask_card_num}')
186 upd_sen_acc_ = self.conn.commit() #
187
188
189 def do_transfer(self):
190 self.ask_receiver_card_num = input("\nTransfer\nEnter card number:\n") #
191 if self.check_luhn(self.ask_receiver_card_num) is True: # No need to compare with True, just drop the 'is True' part
192 if self.check_card_existence() is True: # Same above
193 if self.ask_receiver_card_num == self.ask_card_num: #
194 print("\nYou can't transfer money to the same account!") #
195 return self.log_in_success() #
196 else: # I would have made the complex if/else
197 self.amt_transfer = int(input("Enter how much money you want to transfer:\n")) # statements more undestandable
198 if self.amt_avail() >= self.amt_transfer: #
199 self.transfer_success() #
200 print("Success!") #
201 return self.log_in_success() # No need to return log_in_success(),
202 else: # You have called do_transfer() from it, and there's an infinite loop, so no need to add any return statements
203 print("Not enough money!") #
204 return self.log_in_success() #
205 else: #
206 print("Such a card does not exit.") # IMPORTANT - typo 'exists' (not 'exit')
207 return self.log_in_success() # It can be the cause of an error of 9-th testcase
208 else: #
209 print("Probably you made mistake in the card number. Please try again!") #
210 return self.log_in_success() #
211
212
213 def close_account(self):
214 del_acc = self.cur.execute(f'delete from card where number = {self.ask_card_num}') # Remarks 1.
215 del_acc_ = self.conn.commit() # No need to declare a variable
216 print("\nThe account has been closed!") #
217
218
219 # main
220 def main(self):
221 self.database()
222 while True:
223 choose_option = input("\n1. Create an account\n2. Log into account\n0. Exit\n") # Delete the first newline (no need)
224 if choose_option == '1':
225 self.create_acc()
226 elif choose_option == '2':
227 self.log_in_acc()
228 else:
229 print("\nBye!") # can also change to "quit('\nBye!')"
230 break # (not necessary)
231
232
233account = BankingSystem() # use "if __name__ == '__main__':" for the safe 'import' from other files
234account.main()
235