python练习_module022ATM+购物车

需求

  • 额度 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


原文地址:https://www.cnblogs.com/jailly/p/6895351.html