python练习_module02-1-ATM+购物车

需求

  • 额度 15000或自定义
  • 实现购物商城,买东西加入 购物车,调用信用卡接口结账
  • 可以提现,手续费5%
  • 支持多账户登录
  • 支持账户间转账
  • 记录每月日常消费流水
  • 提供还款接口
  • ATM记录操作日志
  • 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
  • 用户认证用装饰器

目录结构


module02-2-ATM
    ├── 流程图
    ├── README
    ├── Atm #ATM主程目录
    │   ├── __init__.py
    │   ├── bin     #ATM 执行文件 目录
    │   │   ├── __init__.py
    │   │   ├── atm.py      #ATM 执行程序
    │   │   └── manage.py   #ATM 管理端
    │   ├── conf    #配置文件
    │   │   ├── __init__.py
    │   │   └── settings.py     #初始化数据:清空日志,删除用户信息,生成初始用户数据
    │   ├── core    #主要程序逻辑都 在这个目录 里
    │   │   ├── __init__.py
    │   │   ├── accounts.py     #用于从文件里加载和存储账户数据
    │   │   ├── auth.py         #用户认证模块
    │   │   ├── db_handler.py   #记录数据库信息
    │   │   ├── logger.py       #日志记录模块
    │   │   ├── main.py         #主逻辑交互程序
    │   │   └── transaction.py  #执行 记账\还钱\取钱等 所有的与账户金额相关的操作
    │   ├── db      #用户数据存储的地方
    │   │   ├── __init__.py
    │   │   ├── account_sample.py   #生成一个初始的账户数据 ,把这个数据存成一个以这个账户id为文件名的文件,放在accounts目录
    │   │   └── accounts            #存各个用户的账户数据 ,一个用户一个文件
    │   │       └── 1 #初始用户tom示例文件
    │   │       └── 2 #初始用户lily示例文件
    │   └── log     #日志目录
    │       ├── __init__.py
    │       ├── access.log          #用户访问的相关日志
    │       └── transactions.log    #所有的交易日志
    └── ShoppingMall #电子商城程序
        └── __init__.py
        └── acc.pkl             #存储商城用户数据,由make_acc.py生成
        └── make_acc.py         #生产初始商城用户数据
        └── shopping_cart.py    #电子商城主程序

代码



 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4
 5 import sys,os
 6
 7 sys.path.append(os.path.dirname(os.getcwd()))
 8
 9 from core import main
10
11 if __name__ == ‘__main__‘:
12     main.main()

atm.py

  1 #!  /usr/bin/env python3
  2 #   -*- coding:utf-8 -*-
  3 #   Author:Jailly
  4 #   添加/删除/冻结账户,设定账户额度
  5
  6 import os,sys,pickle,time
  7 from imp import reload
  8
  9 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 10
 11 from core import db_handler
 12
 13 # 中英文对齐
 14 def alignment(str1, space, align = ‘left‘):
 15     length = len(str1.encode(‘gb2312‘))
 16     space = space - length if space >=length else 0
 17     if align == ‘left‘:
 18         str1 = str1 + ‘ ‘ * space
 19     elif align == ‘right‘:
 20         str1 = ‘ ‘* space +str1
 21     elif align == ‘center‘:
 22         str1 = ‘ ‘ * (space //2) +str1 + ‘ ‘* (space - space // 2)
 23     return str1
 24
 25
 26 # 查看账户[只显示用户名,信用额度,冻结状态]
 27 def show():
 28     import core.accounts
 29     reload(core.accounts)  # 每次获取账号信息都需重载
 30     acc_dict = core.accounts.acc_dict
 31
 32     print(‘-‘*40)
 33     print(‘|‘,alignment(‘用户名‘,10),‘|‘,alignment(‘信用额度‘,10),‘|‘,alignment(‘冻结状态‘,10),‘|‘)
 34     for i in sorted(acc_dict.keys()):
 35         last_frozen_time = acc_dict[i][‘last_frozen_time‘] if acc_dict[i][‘last_frozen_time‘] else 0
 36         status = ‘ב if time.time() - last_frozen_time > 86400 else ‘√‘
 37
 38         print(‘|‘,alignment(acc_dict[i][‘user‘],10),‘|‘,alignment(str(acc_dict[i][‘limit‘]),10),‘|‘,
 39               alignment(status, 10),‘|‘)
 40
 41     print(‘-‘*40)
 42
 43     input(‘\033[1;36m请输入任意键按回车继续...\n\033[0m‘)
 44
 45 # 添加账户
 46 def create():
 47     import core.accounts
 48     reload(core.accounts)  # 每次获取账号信息都需重载
 49     acc_dict = core.accounts.acc_dict
 50
 51     while 1:
 52         # 输入用户名并判断其是否已存在
 53         while 1:
 54             user = input(‘请输入要添加的用户名:‘).strip()
 55             if user:
 56                 for i in list(acc_dict.values()):
 57                     if user == i[‘user‘]:
 58                         print(‘\033[1;31m该用户名已存在!\033[0m‘)
 59                         break
 60                 else:
 61                     break
 62             else:
 63                 print(‘\033[1;31m用户名不能为空!\033[0m‘)
 64
 65         # 两次输入密码并判断输入是否相同
 66         while 1:
 67             pwd = input(‘请输入密码:‘)
 68             re_pwd= input(‘请再次输入密码:‘)
 69
 70             if pwd:
 71                 if pwd == re_pwd:
 72                     break
 73                 else:
 74                     print(‘\033[1;31m两次密码输入不一致!请重新输入\033[0m‘)
 75             else:
 76                 print(‘\033[1;31m密码不能为空!\033[0m‘)
 77
 78         # 设定额度
 79         while 1:
 80             limit = input(‘请设定信用额度(默认15000元):‘).strip()
 81             if limit :
 82                if limit.isdigit():
 83                    limit = int(limit)
 84                    break
 85                else:
 86                    print(‘\033[1;31m请输入整数!\033[0m‘)
 87
 88             else:
 89                 limit = 15000
 90                 break
 91
 92         print(‘\n要添加的账户信息为:‘)
 93         print(‘-‘*25)
 94         print(‘用户名:%s‘%user)
 95         print(‘密码:%s‘%pwd)
 96         print(‘信用额度:%d‘%limit)
 97         print(‘-‘ * 25)
 98
 99         confirm = input(‘确定吗?(y/n)‘)
100
101         if confirm.lower() == ‘n‘:
102             continue
103         else:
104             break
105
106     new_id = max(list(acc_dict.keys())) + 1 if acc_dict else 1
107     new_accfile_path = os.path.join(core.accounts.acc_path,str(new_id))
108     new_acc = {‘user‘:user,
109                ‘pwd‘:pwd,
110                ‘limit‘:limit,
111                ‘available_limit‘:limit,
112                ‘last_login_time‘:None,
113                ‘last_frozen_time‘:None}
114
115     with open(new_accfile_path,‘wb‘) as f:
116         pickle.dump(new_acc,f)
117
118     print(‘用户 \033[1;36m%s\033[0m 已添加,用户文件路径为 \033[1;36m%s\033[0m\n‘%(user,new_accfile_path))
119
120
121 # 删除用户
122 def delete():
123     import core.accounts
124     reload(core.accounts)  # 每次获取账号信息都需重载
125     acc_dict = core.accounts.acc_dict
126
127     user = input(‘请输入您要删除的用户名:‘).strip()
128
129     for i in acc_dict.keys():
130         if user == acc_dict[i][‘user‘]:
131             os.remove(os.path.join(core.accounts.acc_path,str(i)))
132             print(‘用户 \033[1;31m%s\033[0m 已删除‘%user)
133             break
134     else:
135         print(‘\033[1;31m用户名不存在!\033[0m‘)
136
137
138 # 冻结用户
139 def frozen():
140     import core.accounts
141     reload(core.accounts)  # 每次获取账号信息都需重载
142     acc_dict = core.accounts.acc_dict
143
144     user = input(‘请输入您要冻结的用户名:‘).strip()
145     for i in acc_dict:
146         if acc_dict[i][‘user‘] == user:
147             acc_dict[i][‘last_frozen_time‘] = time.time()
148
149             # 写入数据库
150             db_handler.write(i,acc_dict[i])
151
152             print(‘\033[1;31m%s\033[0m 已冻结,将于 \033[1;31m%s\033[0m 解冻\n‘ % (user,
153                                                                     time.asctime(time.localtime(time.time() + 86400))))
154
155             break
156     else:
157         print(‘\033[1;31m用户名不存在!\033[0m‘)
158
159
160 # 设置额度
161 def set_limit():
162     import core.accounts
163     reload(core.accounts)  # 每次获取账号信息都需重载
164     acc_dict = core.accounts.acc_dict
165
166     user = input(‘请输入用户名:‘).strip()
167     limit = input(‘请设置信用额度:‘).strip()
168
169     for i in acc_dict:
170         if user == acc_dict[i][‘user‘]:
171             if limit.isdigit():
172                 limit = int(limit)
173                 acc_dict[i][‘limit‘] = limit
174
175                 #写入数据库
176                 db_handler.write(i,acc_dict[i])
177
178                 print(‘\033[1;31m%s\033[0m 的信用额度已被设置为 \033[1;31m%d\033[0m 元‘%(user,limit))
179
180             else:
181                 print(‘\033[1;31m额度必须是整数!\033[0m‘)
182             break
183     else:
184         print(‘\033[1;31m用户名不存在!\033[0m‘)
185
186
187 # 主程序
188 def main():
189
190     while 1:
191         print(‘ 操作列表 ‘.center(30, ‘-‘))
192         print(‘|‘, ‘1.查看用户‘.center(25), ‘|‘)
193         print(‘|‘, ‘2.添加用户‘.center(25), ‘|‘)
194         print(‘|‘, ‘3.删除用户‘.center(25), ‘|‘)
195         print(‘|‘, ‘4.冻结用户‘.center(25), ‘|‘)
196         print(‘|‘, ‘5.设置额度‘.center(25), ‘|‘)
197         print(‘|‘, ‘6.退出系统‘.center(25), ‘|‘)
198         print(‘‘.center(34, ‘-‘))
199
200         choice = input(‘请输入您要进行的操作编号<1|2|3|4|5|6>:‘).strip()
201
202         if choice in [‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘]:
203             if choice == ‘1‘:
204                 show()
205
206             elif choice == ‘2‘:
207                 create()
208
209             elif choice == ‘3‘:
210                 delete()
211
212             elif choice == ‘4‘:
213                 frozen()
214
215             elif choice == ‘5‘:
216                 set_limit()
217
218             elif choice == ‘6‘:
219                 exit()
220
221         else:
222             print(‘\033[1;31m请输入正确的操作编号!\033[0m‘)
223
224
225 if __name__ == ‘__main__‘:
226     main()

manage.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4 #   用于从文件里加载和存储账户数据
 5
 6 import os,pickle
 7
 8 acc_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ‘db‘, ‘accounts‘)
 9 acc_filenames_list = os.listdir(acc_path)
10 acc_dict = {}
11
12 for i in acc_filenames_list:
13     acc_file_path = os.path.join( acc_path,i )
14
15     with open(acc_file_path,‘rb‘) as f:
16         acc_dict[int(i)] = pickle.load(f)
17
18 # for i in acc_dict.values():
19 #     print(i)

accounts.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4 #   用户认证
 5
 6 import os,sys,time
 7
 8 sys.path.append(os.path.dirname(os.path.dirname(os.getcwd())))
 9
10 from Atm.core import accounts,logger,db_handler
11
12 acc_dict = accounts.acc_dict
13 current_user_id = None
14
15 def auth(func):
16     def wrapper(*args,**kwargs):
17         n = 0
18         flag = 0
19         while n<3:
20             user_input = input(‘请输入用户名:‘).strip()
21             pwd_input = input(‘请输入密码:‘).strip()
22
23             for i in acc_dict:
24
25                 if user_input == acc_dict[i][‘user‘] and pwd_input == acc_dict[i][‘pwd‘]:
26
27                     last_frozen_time = acc_dict[i][‘last_frozen_time‘] if acc_dict[i][‘last_frozen_time‘] else 0
28                     # 未冻结
29                     if time.time() - last_frozen_time > 86400:
30                         # 将登陆时间写入数据库
31                         acc_dict[i][‘last_login_time‘] = time.time()  # 时间戳,用于数据库记录
32                         db_handler.write(i,acc_dict[i])
33
34                         # 日志记录
35                         access_time = time.asctime()  # 时间格式化字符串,用于日志记录
36                         logger.access_record(user_input,access_time)
37
38                         # 传递给core.main,表明当前用户
39                         global current_user_id
40                         current_user_id = i
41
42                         flag = 1
43                         return func(*args,**kwargs)
44
45                     # 已冻结
46                     else:
47                         print(‘\033[1;31m该账户已冻结!\033[0m‘)
48                         break
49             else:
50                 print(‘\033[1;31m您输入的用户名或密码不正确,请重新输入\033[0m‘)
51
52             if flag:
53                 break
54
55             n += 1
56
57         else:
58             print(‘\033[1;31m输入错误次数过多,程序关闭!\033[0m‘)
59             exit()
60
61
62
63     return wrapper

auth.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4 #   数据库连接引擎
 5
 6 import os,pickle
 7
 8 db_path = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))),‘db‘,‘accounts‘ )
 9
10 def write(id,user_info):
11     acc_file_path = os.path.join(db_path, str(id))
12     with open(acc_file_path, ‘wb‘) as f:
13         pickle.dump(user_info, f)

db_hander.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4 #   日志记录
 5
 6 import os
 7
 8 log_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),‘log‘)
 9 access_log_path = os.path.join(log_path,‘access.log‘)
10 transctions_log_path = os.path.join(log_path,‘transactions.log‘)
11
12 def access_record(user,access_time):
13
14     with open(access_log_path,‘a‘,encoding=‘utf-8‘) as f:
15         record = ‘{user} accesses at {time}\n‘.format(user=user,time=access_time)
16         f.write(record)
17
18
19 def transactions_record(user,type,amount,time,handing_fee=0,to_who=None):
20     if type == ‘withdraw‘:
21         with open(transctions_log_path,‘a‘,encoding=‘utf-8‘) as f:
22             record = ‘{user} {type}s ¥{amount}(handing fee:{handing_fee}) at {time}\n‘ 23                 .format(user=user,type=type,amount=amount,handing_fee=handing_fee,time=time)
24             f.write(record)
25
26     elif type == ‘repay‘:
27         with open(transctions_log_path,‘a‘,encoding=‘utf-8‘) as f:
28             record = ‘{user} {type}s ¥{amount} at {time}\n‘.format(user=user,type=type,amount=amount,time=time)
29             f.write(record)
30
31     elif type == ‘transfer‘:
32         with open(transctions_log_path,‘a‘,encoding=‘utf-8‘) as f:
33             record = ‘{user} {type}s ¥{amount} to {to_who} at {time}\n‘ 34                 .format(user=user,type=type,amount=amount,to_who=to_who,time=time)
35             f.write(record)
36
37     elif type == ‘receive‘:
38         with open(transctions_log_path,‘a‘,encoding=‘utf-8‘) as f:
39             record = ‘{user} {type}s ¥{amount} from {to_who} at {time}\n‘ 40                 .format(user=user,type=type,amount=amount,to_who=to_who,time=time)
41             f.write(record)

logger.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4
 5 import os,sys
 6
 7 sys.path.append(os.path.dirname(os.getcwd()))
 8
 9 from core import auth,transaction,accounts
10
11 @auth.auth
12 def main():
13     id = auth.current_user_id
14     print(‘\033[1;36m%s\033[0m,欢迎进入atm操作系统‘%accounts.acc_dict[id][‘user‘])
15
16     if id:
17         while 1:
18             print(‘操作菜单‘.center(30,‘-‘))
19             print(‘| 1. 账户信息‘.ljust(28,‘ ‘),‘|‘)
20             print(‘| 2. 提现‘.ljust(30,‘ ‘),‘|‘)
21             print(‘| 3. 还款‘.ljust(30,‘ ‘),‘|‘)
22             print(‘| 4. 转账‘.ljust(30,‘ ‘),‘|‘)
23             print(‘| 5. 账单‘.ljust(30,‘ ‘),‘|‘)
24             print(‘| 6. 退出‘.ljust(30,‘ ‘),‘|‘)
25             print(‘-‘*34)
26
27             operation = input(‘请输入您想要执行的操作编号(1|2|3|4|5|6):‘).strip()
28             if operation == ‘1‘ :
29                 transaction.acc_info(id)
30
31             elif operation == ‘2‘ :
32                 transaction.withdraw(id)
33
34             elif operation == ‘3‘ :
35                 transaction.repay(id)
36
37             elif operation == ‘4‘ :
38                 transaction.transfer(id)
39
40             elif operation == ‘5‘:
41                 transaction.bill(id)
42
43             elif operation == ‘6‘:
44                 break
45
46             else:
47                 print(‘\n\033[1;31m输入错误,请重新输入\033[0m‘)
48
49         print(‘谢谢您的使用,再见!‘)
50
51 if __name__ == ‘__main__‘:
52     main()

main.py

  1 #!  /usr/bin/env python3
  2 #   -*- coding:utf-8 -*-
  3 #   Author:Jailly
  4
  5 import os,sys,time
  6 from imp import reload
  7
  8 sys.path.append(os.path.dirname(os.path.dirname(os.getcwd())))
  9
 10 from Atm.core import auth,db_handler,logger
 11 import Atm.core.accounts
 12
 13
 14 # 显示账户信息
 15 def acc_info(id):
 16     reload(Atm.core.accounts)
 17     acc_dict = Atm.core.accounts.acc_dict[id]
 18     user = acc_dict[‘user‘]
 19     limit = acc_dict[‘limit‘]
 20     available_limit = acc_dict[‘available_limit‘]
 21     need_repay = limit - available_limit
 22     last_login_time = time.asctime() if not acc_dict[‘last_login_time‘] else  23         time.asctime(time.localtime(acc_dict[‘last_login_time‘]))
 24
 25     print(‘账户信息‘.center(55,‘-‘))
 26
 27     print(‘‘‘
 28 用户名:\t\t%s
 29 信用额度:\t\t%s
 30 可用额度:\t\t%s
 31 待还款:\t\t%s
 32 最近登陆时间:\t%s
 33     ‘‘‘%(user,limit,available_limit,need_repay,last_login_time))
 34
 35     print(‘‘.ljust(58,‘-‘))
 36
 37     input(‘\033[1;36m输入任意键按回车继续...\033[0m\n‘)
 38
 39 # 提现
 40 def withdraw(id):
 41     reload(Atm.core.accounts)
 42     acc_dict = Atm.core.accounts.acc_dict[id]
 43     user = acc_dict[‘user‘]
 44
 45     while 1:
 46         available_limit = acc_dict[‘available_limit‘]  # 出错则初始化可用额度
 47
 48         withdraw_amount = input(‘请输入取现金额([\033[1;36mb\033[0m]:返回上一级;[\033[1;36mq\033[0m]:退出系统):‘).strip()
 49         if withdraw_amount.isdigit():
 50             withdraw_amount = int(withdraw_amount)
 51             handing_fee = int(withdraw_amount*0.05)
 52             available_limit -= int(withdraw_amount*1.05)
 53
 54             if not withdraw_amount%100:
 55                 if available_limit >= 0:
 56                     acc_dict[‘available_limit‘] = available_limit
 57                     withdraw_time = time.asctime()
 58                     acc_dict[‘transaction_record‘].append((withdraw_time,‘提现‘,withdraw_amount,handing_fee,‘‘))
 59
 60                     # 模拟出钞
 61                     print(‘出钞中‘,end=‘‘)
 62                     for i in range(3):
 63                         sys.stdout.write(‘.‘)
 64                         sys.stdout.flush()
 65                         time.sleep(0.5)
 66                     print(‘\n请从取钞口取出钞票,取钞时请注意安全‘,end=‘‘)
 67                     for i in range(3):
 68                         sys.stdout.write(‘.‘)
 69                         sys.stdout.flush()
 70                         time.sleep(0.5)
 71
 72                     print(‘\n本次取现 \033[1;31m%d\033[0m 元,手续费 \033[1;31m%d\033[0m 元,您的当前可用额度为 \033[1;31m%d\033[0m 元‘%  73                           (withdraw_amount,int(withdraw_amount*0.05),available_limit))
 74
 75                     # 写入账户数据库
 76                     db_handler.write(id,acc_dict)
 77
 78                     # 记录日志
 79                     logger.transactions_record(user,‘withdraw‘,withdraw_amount,withdraw_time,handing_fee)
 80
 81                     input(‘\n\033[1;36m取款结束后请按任意键继续...\033[0m\n‘)
 82                     break
 83
 84                 else:
 85                     print(‘\033[1;31m取款金额超出可用额度,请重试!\033[0m‘)
 86             else:
 87                 print(‘\033[1;31m提现金额只能是100的整数倍!\033[0m‘)
 88
 89         elif withdraw_amount == ‘b‘:
 90             break
 91
 92         elif withdraw_amount == ‘q‘:
 93             exit()
 94
 95         else:
 96             print(‘\033[1;31m金额必须输入整数!\033[0m‘)
 97
 98
 99 # 还款
100 def repay(id):
101     reload(Atm.core.accounts)
102     acc_dict = Atm.core.accounts.acc_dict[id]
103     user= acc_dict[‘user‘]
104     available_limit = acc_dict[‘available_limit‘]
105     limit = acc_dict[‘limit‘]
106
107     while 1:
108         repay_amount = input(‘请输入还款金额:‘).strip()
109
110         if repay_amount.isdigit():
111             repay_amount = int(repay_amount)
112
113             if available_limit + repay_amount <= limit:
114                 acc_dict[‘available_limit‘] = available_limit + repay_amount
115                 repay_time = time.asctime()
116                 acc_dict[‘transaction_record‘].append((repay_time,‘还款‘,repay_amount,0,‘‘))
117
118                 # 模拟还款
119                 print(‘连接您绑定的银行卡‘,end=‘‘)
120                 for i in range(3):
121                     sys.stdout.write(‘.‘)
122                     sys.stdout.flush()
123                     time.sleep(0.5)
124
125                 print(‘\n处理还款请求‘,end=‘‘)
126                 for i in range(3):
127                     sys.stdout.write(‘.‘)
128                     sys.stdout.flush()
129                     time.sleep(0.5)
130
131                 print(‘\n交易完成!\n您已还款 \033[1;31m%d\033[0m 元,您的当前可用额度为 \033[1;31m%d\033[0m 元‘% 132                       (repay_amount,acc_dict[‘available_limit‘]))
133
134                 # 写入账户数据库
135                 db_handler.write(id, acc_dict)
136
137                 # 记录日志
138                 logger.transactions_record(user,‘repay‘,repay_amount,repay_time)
139
140                 input(‘\033[1;36m输入任意键按回车继续...\033[0m\n‘)
141                 break
142             else:
143                 print(‘\033[1;31m还款金额已超出信用额度,请重试!\033[0m‘)
144
145         else:
146             print(‘\033[1;31m金额必须输入整数!\033[0m‘)
147
148 # 转账
149 def transfer(id):
150     while 1:
151         reload(Atm.core.accounts)
152         accs_dict = Atm.core.accounts.acc_dict
153         acc_dict = accs_dict[id]
154
155         to_user = input(‘对方账户:‘).strip()
156
157         for i in accs_dict:
158             if to_user == accs_dict[i][‘user‘]:
159                 to_id = i
160                 break
161         else:
162             print(‘账户\033[1;31m %s \033[0m不存在!‘%to_user)
163             continue
164
165         transfer_amount = input(‘转账金额:‘).strip()
166
167         if transfer_amount.isdigit():
168             transfer_amount = int(transfer_amount)
169
170
171             if transfer_amount <= acc_dict[‘available_limit‘]:
172                 if accs_dict[to_id][‘available_limit‘] + transfer_amount <= accs_dict[to_id][‘limit‘]:
173
174                     # 本账号记录信息
175                     acc_dict[‘available_limit‘] -= transfer_amount
176                     transfer_time = time.asctime()
177                     acc_dict[‘transaction_record‘].append((transfer_time,‘转账‘,transfer_amount,0,to_user))
178
179                     # 对方账号记录信息
180                     accs_dict[to_id][‘available_limit‘] += transfer_amount
181                     accs_dict[to_id][‘transaction_record‘].append((transfer_time,‘收款‘,transfer_amount,0,to_user))
182
183                     # 模拟转账
184                     print(‘连接对方账户‘,end=‘‘)
185                     for i in range(3):
186                         sys.stdout.write(‘.‘)
187                         sys.stdout.flush()
188                         time.sleep(0.5)
189
190                     print(‘\n处理转账请求‘,end=‘‘)
191                     for i in range(3):
192                         sys.stdout.write(‘.‘)
193                         sys.stdout.flush()
194                         time.sleep(0.5)
195
196                     print(‘\n交易完成!\n您向 %s 转账 \033[1;31m%d\033[0m 元,您的当前可用额度为 \033[1;31m%d\033[0m 元‘% 197                         (to_user,transfer_amount,acc_dict[‘available_limit‘]))
198
199                     # 写入账户数据库
200                     db_handler.write(id,acc_dict)
201                     db_handler.write(to_id,accs_dict[to_id])
202
203                     # 日志记录
204                     logger.transactions_record(acc_dict[‘user‘],‘transfer‘,transfer_amount,transfer_time,to_who=to_user)
205                     logger.transactions_record(to_user,‘receive‘,transfer_amount,transfer_time,to_who=acc_dict[‘user‘])
206
207                     input(‘\033[1;36m输入任意键按回车继续...\033[0m\n‘)
208                     break
209
210                 else:
211                     print(‘\033[1;31m转账金额超出对方信用额度\033[0m‘)
212             else:
213                 print(‘\033[1;31m转账金额超出本账号当前可用额度\033[0m‘)
214
215         else:
216             print(‘\033[1;31m金额必须输入整数!\033[0m‘)
217
218
219
220 # 支付
221 @auth.auth
222 def pay(payment_amount,to_who):
223     reload(Atm.core.accounts)
224     id = auth.current_user_id
225     acc_dict = Atm.core.accounts.acc_dict[id]
226     available_limit = acc_dict[‘available_limit‘]
227
228     # print(payment_amount,available_limit)
229
230     if payment_amount <= available_limit:
231         acc_dict[‘available_limit‘] -= payment_amount
232         pay_time = time.asctime()
233         acc_dict[‘transaction_record‘].append((pay_time,‘支付‘,payment_amount,0,to_who))
234
235         # 写入账户数据库
236         db_handler.write(id, acc_dict)
237
238         # 日志记录
239         logger.transactions_record(acc_dict[‘user‘], ‘pay‘, payment_amount, pay_time, to_who=to_who)
240
241         return 1
242
243     else:
244         return 0
245
246 # 消费记录
247 def bill(id):
248     reload(Atm.core.accounts)
249     acc_dict = Atm.core.accounts.acc_dict[id]
250
251     print(‘ 账单 ‘.center(80,‘-‘))
252     print(‘时间‘.ljust(28),‘交易类型\t‘.ljust(10),‘金额\t‘.ljust(10),‘手续费\t‘.ljust(10),‘对方账户‘)
253     for i in sorted(acc_dict[‘transaction_record‘]):
254         print(i[0].ljust(30),i[1].ljust(12), str(i[2]).ljust(13), str(i[3]).ljust(14),i[4])
255
256     print(‘-‘*84)
257     print(‘|‘,(‘信用额度: %d‘%acc_dict[‘limit‘]).center(20),‘|‘,
258           (‘可用额度: %d‘%acc_dict[‘available_limit‘]).center(20),‘|‘,
259           (‘待还款: %d‘%(acc_dict[‘limit‘] - acc_dict[‘available_limit‘])).center(20),‘|‘)
260     print(‘-‘ * 84)
261
262     input(‘\033[1;36m输入任意键按回车继续...\033[0m\n‘)
263
264 # if __name__ == ‘__main__‘:
265 #     x = pay(10,‘tianmao‘)
266 #     print(x)

transaction.py

 1 #!  /usr/bin/env python3
 2 #   -*- coding:utf-8 -*-
 3 #   Author:Jailly
 4 #   生成初始账户数据
 5
 6 import pickle,os
 7
 8 accounts_path = os.path.join((os.path.dirname(__file__)),‘accounts‘)
 9
10 acc1 = {‘user‘:‘tom‘,               # 用户名
11         ‘pwd‘:‘123‘,                # 密码
12         ‘limit‘:15000,              # 信用额度
13         ‘available_limit‘:15000,    # 可用额度
14         ‘transaction_record‘:[],    # 交易记录(时间,类型,金额,手续费,对方账户)
15         ‘last_login_time‘:None,     # 最近登录时间
16         ‘last_frozen_time‘:None}    # 最近冻结时间
17
18 acc2 = {‘user‘:‘lily‘,              # 用户名
19         ‘pwd‘:‘123‘,                # 密码
20         ‘limit‘:15000,              # 信用额度
21         ‘available_limit‘:15000,    # 可用额度
22         ‘transaction_record‘:[],    # 交易记录(时间,类型,金额,手续费,对方账户)
23         ‘last_login_time‘:None,     # 最近登录时间
24         ‘last_frozen_time‘:None}    # 最近冻结时间
25
26 def init_account():
27     with open(os.path.join(accounts_path,‘1‘),‘wb‘) as f:
28         pickle.dump(acc1,f)
29
30     with open(os.path.join(accounts_path,‘2‘),‘wb‘) as f:
31         pickle.dump(acc2,f)
32
33 if __name__ == ‘__main__‘:
34     init_account()

account_sample.py

 1 #! /usr/bin/env python3
 2 # -*- encoding:utf-8 -*-
 3 # Author:Jailly
 4
 5 import  pickle
 6
 7 acc = {
 8     ‘tom‘:
 9         {‘pwd‘:‘123‘,
10          ‘shopping cart‘:[],
11          ‘payment amount‘:0},
12     ‘lily‘:
13         {‘pwd‘:‘123‘,
14         ‘shopping cart‘:[],
15          ‘payment amount‘: 0}
16 }
17
18 with open(‘acc.pkl‘,‘wb‘) as f:
19     pickle.dump(acc,f)
20
21 print(‘已生成初始账号(\033[1;36m tom、lily \033[0m)‘)

make_acc

  1 #! /usr/bin/env python3
  2 # -*- encoding:utf-8 -*-
  3 # Author:Jailly
  4
  5 import pickle,os,sys,time
  6 from imp import reload
  7
  8 sys.path.append(os.path.dirname(os.getcwd()))
  9
 10 import Atm.core.transaction
 11
 12 # 用户登陆
 13 def login():
 14     count = 0
 15     while count < 3:
 16         name_input = input(‘用户名:‘).strip()
 17         pwd_input = input(‘密码:‘)
 18
 19         if name_input in acc:
 20             if acc[name_input][‘pwd‘] == pwd_input:
 21                 return name_input
 22             else:
 23                 print(‘\033[1;31m密码错误\033[0m‘)
 24                 count += 1
 25         else:
 26             print(‘\033[1;31m您输入的用户名不存在,请重新输入\033[0m‘)
 27     else:
 28         print(‘错误次数太多,程序关闭...‘)
 29         exit()
 30
 31
 32 # 查看购物车
 33 def show_cart(name):
 34
 35     with open(‘acc.pkl‘, ‘rb‘) as f:
 36         acc = pickle.load(f)
 37
 38     if acc[name][‘shopping cart‘]:
 39         print(‘-‘ * 51)
 40         print(‘|‘, ‘shopping cart‘.center(47, ‘ ‘), ‘|‘)
 41         print(‘-‘ * 51)
 42         for i in acc[name][‘shopping cart‘]:
 43             print(‘|‘, i[1][0].center(22, ‘ ‘), ‘|‘, str(i[1][1]).center(22, ‘ ‘), ‘|‘)
 44             print(‘-‘ * 51)
 45         print(‘|‘, (‘待付款: %d 元‘%acc[name][‘payment amount‘]).center(42, ‘ ‘), ‘|‘)
 46         print(‘-‘ * 51)
 47     else:
 48         print(‘您的购物车为空‘)
 49     input(‘\033[1;36m输入任意键按回车继续...\033[0m‘)
 50
 51
 52 # 移出购物车
 53 def remove(name):
 54     # 实时读取用户数据库
 55     with open(‘acc.pkl‘, ‘rb‘) as f:
 56         acc = pickle.load(f)
 57
 58     if acc[name][‘shopping cart‘]:
 59         while 1:
 60             choice = input(‘请输入您想要移出的商品编号([\033[1;36mb\033[0m]:返回):‘).strip()
 61
 62             if choice.isdigit():
 63                 choice = int(choice)
 64                 for i in acc[name][‘shopping cart‘]:
 65                     if choice == i[0]:
 66                         acc[name][‘shopping cart‘].remove(i)
 67                         acc[name][‘payment amount‘] -= i[1][1]
 68
 69                         # 实时写入用户数据库
 70                         with open(‘acc.pkl‘,‘wb‘) as f:
 71                             pickle.dump(acc,f)
 72
 73                         print(‘\033[1;36m%s\033[0m 已移出购物车‘%i[1][0])
 74                         break
 75
 76             elif choice == ‘b‘:
 77                 break
 78
 79             else:
 80                 print(‘\033[1;31m请输入正确的商品编号!\033[0m‘)
 81     else:
 82         print(‘\033[1;31m您的购物车为空!\033[0m‘)
 83
 84
 85 # 调用支付接口
 86 def pay(name,to_who):
 87
 88     reload(Atm.core.transaction)
 89
 90     with open(‘acc.pkl‘, ‘rb‘) as f:
 91         acc = pickle.load(f)
 92
 93     print(‘连接ATM系统‘, end=‘‘)
 94     for i in range(3):
 95         sys.stdout.write(‘.‘)
 96         sys.stdout.flush()
 97         time.sleep(0.5)
 98     print()
 99     # print(‘\n 待支付 %s‘%acc[name][‘payment amount‘] )
100
101     payment_amount = acc[name][‘payment amount‘]
102
103     flag = Atm.core.transaction.pay(payment_amount, to_who)
104     # print(flag)
105
106
107
108     if flag:
109         acc[name][‘shopping cart‘] = []
110         acc[name][‘payment amount‘] = 0
111
112         # 实时写入用户数据库
113         with open(‘acc.pkl‘, ‘wb‘) as f:
114             pickle.dump(acc,f)
115
116         print(‘\n\033[5m支付成功!已付款 %d 元\033[0m‘ % payment_amount)
117
118     else:
119         print(‘\033[1;31m信用卡的可用额度不足,交易取消\033[0m‘)
120
121
122 # 选购商品
123 def shopping(name_input):
124
125     while 1:
126         # 显示商品列表
127         print(‘ Product List ‘.center(50,‘-‘))
128         for k,v in enumerate(product_list):
129             print((‘| %s\t -> \t%s‘%(k,v[0])).ljust(30),str(v[1]).ljust(14),‘|‘)
130         print(‘-‘*50)
131
132         choice = input(‘请输入您想要购买的商品编号([\033[1;36ms\033[0m]:查看购物车;[\033[1;36mr\033[0m]:移出购物车;‘
133                        ‘[\033[1;36mp\033[0m]:付款;[\033[1;36mq\033[0m]:退出):‘).strip()
134
135         # 选购商品 -> 加入购物车
136         if choice.isdigit():
137
138             with open(‘acc.pkl‘, ‘rb‘) as f:  # 待支付 与 购物车 是中间变量
139                 acc = pickle.load(f)
140
141             choice = int(choice)
142             if 0 <= choice < len(product_list):
143                 acc[name_input][‘shopping cart‘].append((choice,product_list[choice]))
144                 acc[name_input][‘payment amount‘] += product_list[choice][1]
145
146                 print(‘\033[1;31m%s\033[0m 已加入购物车,待付款 \033[1;31m%d\033[0m 元‘% 147                       (product_list[choice][0] , acc[name_input][‘payment amount‘]))
148
149                 # 实时写入用户数据库
150                 with open(‘acc.pkl‘, ‘wb‘) as f:
151                     pickle.dump(acc, f)
152
153             else:
154                 print(‘抱歉,没有找到您选择的商品‘)
155
156         # 查看购物车
157         elif choice == ‘s‘:
158             show_cart(name_input)
159
160         # 移出购物车
161         elif choice == ‘r‘:
162             remove(name_input)
163
164         # 支付
165         elif choice == ‘p‘:
166             pay(name_input,‘ShoppingMall‘)
167
168         # 退出
169         elif choice == ‘q‘:
170
171             with open(‘acc.pkl‘, ‘rb‘) as f:  # 待支付 与 购物车 是中间变量
172                 acc = pickle.load(f)
173
174             if acc[name_input][‘shopping cart‘]:
175                 empty_confirm = input(‘购物车中的商品还未支付购买,要现在支付吗?(y/n)‘)
176                 if (empty_confirm.strip()).lower() != ‘n‘:
177                     pay(name_input,‘ShoppingMall‘)
178                 else:
179                     print(‘感谢您的支持,再见!‘)
180                     exit()
181             else:
182                 print(‘感谢您的支持,再见!‘)
183                 exit()
184
185         else:
186             print(‘\033[1;31m请输入正确的商品编号\033[0m‘)
187
188
189 # 主程序
190 def main():
191     name_input = login()
192     shopping(name_input)
193
194
195 if __name__ == ‘__main__‘:
196
197     product_list = [
198         (‘IPhone‘, 5000),
199         (‘Mac Pro‘, 12000),
200         (‘xbox360‘, 2500),
201         (‘PlayStation3‘, 2000),
202         (‘bike‘, 1000),
203         (‘kindle‘, 150)
204     ]
205
206     with open(‘acc.pkl‘, ‘rb‘) as f:
207         acc = pickle.load(f)
208
209     main()

shopping_cart

时间: 2024-10-05 08:00:46

python练习_module02-1-ATM+购物车的相关文章

Python实战之ATM+购物车

ATM + 购物车 需求分析 ''' - 额度 15000或自定义 - 实现购物商城,买东西加入 购物车,调用信用卡接口结账 - 可以提现,手续费5% - 支持多账户登录 - 支持账户间转账 - 记录每月日常消费流水 - 提供还款接口 - ATM记录操作日志 - 提供管理接口,包括添加账户.用户额度,冻结账户等... - 用户认证功能 ''' 一个项目是如何从无到有的 # 1.需求分析: ''' 开发项目前,都必须找到相应的客户,让客户给企业提出项目的需求,以及需要实现的功能有哪些,拿到需求后再

Python学习day5作业-ATM和购物商城

Python学习day5作业 Python学习day5作业 ATM和购物商城 作业需求 ATM: 指定最大透支额度 可取款 定期还款(每月指定日期还款,如15号) 可存款 定期出账单 支持多用户登陆,用户间转帐 支持多用户 管理员可添加账户.指定用户额度.冻结用户等 购物车: 商品信息- 数量.单价.名称 用户信息- 帐号.密码.余额 用户可充值 购物历史信息 允许用户多次购买,每次可购买多件 余额不足时进行提醒 用户退出时 ,输出当次购物信息 用户下次登陆时可查看购物历史 商品列表分级显示 1

ATM+购物车完整版

代码视频之一:https://www.bilibili.com/video/BV1Cc411h78m/ 更多ATM代码视频请浏览:https://space.bilibili.com/516735973 一 项目三层结构设计 在项目开发中,清晰明了的结构设计非常重要.它的重要性至少提现在三个方面:结构清晰:可维护性强:可扩展性高. 常用的项目结构设计中,三层架构设计非常实用.这种架构设计模式将整个程序分为三层: 用户视图层:用于与用户交互的,可以接受用户的输入,打印接口返回的数据. 逻辑接口层:

python实现简单的循环购物车小功能

python实现简单的循环购物车小功能 # -*- coding: utf-8 -*- __author__ = 'hujianli' shopping = [ ("iphone6s", 5000), ("book python", 81), ("iwach", 3200), ("电视机", 2200) ] def zero(name): if len(name) == 0: print("\033[31;1m您的输

python ATM + 购物车

一.项目介绍 ATM + 购物商城程序其实是通过模拟银行ATM机功能以及电商平台<购物商城程序>功能的实现,将前面大部分所学的知识点串联起来, 更好的去巩固python基础.这也是在学习python这门语言的第一个程序. 项目需求如下: - 额度 15000或自定义 - 实现购物商城,买东西加入 购物车,调用信用卡接口结账 - 可以提现,手续费5% - 支持多账户登录 - 支持账户间转账 - 记录每月日常消费流水 - 提供还款接口 - ATM记录操作日志 - 提供管理接口,包括添加账户.用户额

Python程序练习3--模拟购物车

1.功能简介 此程序模拟用户登陆商城后购买商品操作.可实现用户登陆.商品购买.历史消费记查询.余额和消费信息更新等功能.首次登陆输入初始账户资金,后续登陆则从文件获取上次消费后的余额,每次购买商品后会扣除相应金额并更新余额信息,退出时也会将余额和消费记录更新到文件以备后续查询. 2.实现方法 架构: 本程序采用python语言编写,将各项任务进行分解并定义对应的函数来处理,从而使程序结构清晰明了.主要编写了六个函数: (1)login(name,password) 用户登陆函数,实现用户名和密码

Python开发程序:ATM+购物商城

一.需求 1.模拟实现一个ATM + 购物商城程序 1).实现功能 1.额度 15000或自定义 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息 5.支持多账户登录 6.支持账户间转账 7.记录每月日常消费流水 8.提供还款接口 9.ATM记录操作日志 10.提供管理接口,包括添加账户.用户额度,冻结账户等... 11.用户认证用装饰器 二.程序code 程序说明: ## AT

ATM+购物车

本次代码的实现用到了模块间的互相调用,这对于初学者而言有些难度,不过这也是我们必须要掌握的,在以后的大程序中,多个模块会让我们的代码看起来简洁明了,易排错 (本次代码只是简单的实现的基本的功能,其代码还不是很完美,望各位大神多多指导) 对于一个程序而言,读者想要大概了解你的代码都实现了什么功能,READEME是最直接的.这也是我们呈现给读者的窗口.就本次程序而言 ├── README ├── ATM #ATM主程目录 │   ├── __init__.py │   ├── bin #ATM 执行

【我们一起自学Python】-程序练习:购物车程序

描述: 1.启动程序后,让用户输入金额,然后打印出所有的商品及其价格    如果输入的不是数字则退出程序    2.允许用户输入商品的编号来购买商品    如果输入的是数字则判断数字是否合理,如果合理则扣钱,加入用户的购物车    如果输入的是q则退出程序    如果输入的是其他字符或符号则提示输入有误,询问是否重新输入        如果重新输入的是y则继续让用户输入产品序号        否则退出程序,并打印出已经购买的商品 3.退出程序时打印所购买的商品 流程图 #!usr/bin/evn

ATM购物车部分功能

额度 15000或自定义 实现购物商城,买东西加入 购物车,调用信用卡接口结账 可以提现,手续费5% 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息 支持多账户登录 支持账户间转账 记录每月日常消费流水 提供还款接口 ATM记录操作日志 提供管理接口,包括添加账户.用户额度,冻结账户等... 用户认证用装饰器 思维导图 目录结构 atm作业 ├── README ├── atm #ATM主程目录 │ ├── bin #ATM 执行文件 目录 │ │ ├── __i