|
|
|
|
@ -1,188 +1,182 @@
|
|
|
|
|
"""
|
|
|
|
|
个人财务管理系统
|
|
|
|
|
作者:[你的名字]
|
|
|
|
|
日期:2024年X月X日
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
# 全局变量
|
|
|
|
|
records = [] # 存储所有收支记录
|
|
|
|
|
categories = ['餐饮', '交通', '购物', '娱乐', '工资', '奖金', '其他'] # 收支类别
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_data():
|
|
|
|
|
"""从文件加载数据"""
|
|
|
|
|
global records
|
|
|
|
|
try:
|
|
|
|
|
with open('finance_data.json', 'r', encoding='utf-8') as f:
|
|
|
|
|
records = json.load(f)
|
|
|
|
|
print("历史数据加载成功!")
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
print("未找到历史数据,将创建新文件。")
|
|
|
|
|
records = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_data():
|
|
|
|
|
"""保存数据到文件"""
|
|
|
|
|
with open('finance_data.json', 'w', encoding='utf-8') as f:
|
|
|
|
|
json.dump(records, f, ensure_ascii=False, indent=2)
|
|
|
|
|
print("数据已保存!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_record():
|
|
|
|
|
"""添加收支记录"""
|
|
|
|
|
print("\n--- 添加收支记录 ---")
|
|
|
|
|
|
|
|
|
|
# 输入数据
|
|
|
|
|
amount = float(input("请输入金额(正数为收入,负数为支出):"))
|
|
|
|
|
|
|
|
|
|
print("可选类别:")
|
|
|
|
|
for i, cat in enumerate(categories, 1):
|
|
|
|
|
print(f"{i}. {cat}")
|
|
|
|
|
|
|
|
|
|
cat_choice = int(input("请选择类别编号:"))
|
|
|
|
|
category = categories[cat_choice - 1] if 1 <= cat_choice <= len(categories) else "其他"
|
|
|
|
|
|
|
|
|
|
note = input("请输入备注(可选):")
|
|
|
|
|
|
|
|
|
|
# 创建记录字典
|
|
|
|
|
record = {
|
|
|
|
|
'id': len(records) + 1,
|
|
|
|
|
'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
|
|
|
|
|
'amount': amount,
|
|
|
|
|
'category': category,
|
|
|
|
|
'note': note
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
records.append(record)
|
|
|
|
|
print(f"记录添加成功!ID:{record['id']}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def query_records():
|
|
|
|
|
"""查询收支记录"""
|
|
|
|
|
print("\n--- 查询记录 ---")
|
|
|
|
|
print("1. 查看所有记录")
|
|
|
|
|
print("2. 按日期查询")
|
|
|
|
|
print("3. 按类别查询")
|
|
|
|
|
|
|
|
|
|
choice = input("请选择查询方式:")
|
|
|
|
|
|
|
|
|
|
if choice == '1':
|
|
|
|
|
display_records(records)
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
date_str = input("请输入日期(YYYY-MM-DD):")
|
|
|
|
|
filtered = [r for r in records if r['date'].startswith(date_str)]
|
|
|
|
|
display_records(filtered)
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
print("可选类别:")
|
|
|
|
|
for i, cat in enumerate(categories, 1):
|
|
|
|
|
print(f"{i}. {cat}")
|
|
|
|
|
cat_choice = int(input("请选择类别编号:"))
|
|
|
|
|
if 1 <= cat_choice <= len(categories):
|
|
|
|
|
filtered = [r for r in records if r['category'] == categories[cat_choice - 1]]
|
|
|
|
|
display_records(filtered)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_records(record_list):
|
|
|
|
|
"""显示记录列表"""
|
|
|
|
|
if not record_list:
|
|
|
|
|
print("没有找到相关记录。")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n共找到 {len(record_list)} 条记录:")
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
print(f"{'ID':<5}{'日期':<20}{'类别':<10}{'金额':<15}{'备注'}")
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
|
|
|
|
|
total_income = 0
|
|
|
|
|
total_expense = 0
|
|
|
|
|
|
|
|
|
|
for record in record_list:
|
|
|
|
|
amount = record['amount']
|
|
|
|
|
if amount > 0:
|
|
|
|
|
total_income += amount
|
|
|
|
|
else:
|
|
|
|
|
total_expense += abs(amount)
|
|
|
|
|
|
|
|
|
|
print(f"{record['id']:<5}{record['date']:<20}"
|
|
|
|
|
f"{record['category']:<10}{amount:<15.2f}{record['note']}")
|
|
|
|
|
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
print(f"总收入:{total_income:.2f} | 总支出:{total_expense:.2f} | 结余:{total_income - total_expense:.2f}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def statistics():
|
|
|
|
|
"""统计报表功能"""
|
|
|
|
|
if not records:
|
|
|
|
|
print("暂无数据可统计。")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print("\n--- 财务统计报表 ---")
|
|
|
|
|
|
|
|
|
|
# 计算各类别支出
|
|
|
|
|
expense_by_category = {}
|
|
|
|
|
income_total = 0
|
|
|
|
|
expense_total = 0
|
|
|
|
|
|
|
|
|
|
for record in records:
|
|
|
|
|
amount = record['amount']
|
|
|
|
|
category = record['category']
|
|
|
|
|
|
|
|
|
|
if amount > 0:
|
|
|
|
|
income_total += amount
|
|
|
|
|
else:
|
|
|
|
|
expense_total += abs(amount)
|
|
|
|
|
if category not in expense_by_category:
|
|
|
|
|
expense_by_category[category] = 0
|
|
|
|
|
expense_by_category[category] += abs(amount)
|
|
|
|
|
|
|
|
|
|
# 显示统计结果
|
|
|
|
|
print(f"记录总数:{len(records)}")
|
|
|
|
|
print(f"总收入:{income_total:.2f}")
|
|
|
|
|
print(f"总支出:{expense_total:.2f}")
|
|
|
|
|
print(f"净结余:{income_total - expense_total:.2f}")
|
|
|
|
|
|
|
|
|
|
print("\n支出类别分布:")
|
|
|
|
|
if expense_by_category:
|
|
|
|
|
for category, amount in expense_by_category.items():
|
|
|
|
|
percentage = (amount / expense_total * 100) if expense_total > 0 else 0
|
|
|
|
|
print(f" {category}: {amount:.2f} ({percentage:.1f}%)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main_menu():
|
|
|
|
|
"""主菜单"""
|
|
|
|
|
load_data() # 启动时加载数据
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
print("\n" + "=" * 50)
|
|
|
|
|
print(" 个人财务管理系统")
|
|
|
|
|
print("=" * 50)
|
|
|
|
|
print("1. 添加收支记录")
|
|
|
|
|
print("2. 查询记录")
|
|
|
|
|
print("3. 财务统计")
|
|
|
|
|
print("4. 保存数据")
|
|
|
|
|
print("5. 退出系统")
|
|
|
|
|
|
|
|
|
|
choice = input("\n请选择操作(1-5):")
|
|
|
|
|
|
|
|
|
|
if choice == '1':
|
|
|
|
|
add_record()
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
query_records()
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
statistics()
|
|
|
|
|
elif choice == '4':
|
|
|
|
|
save_data()
|
|
|
|
|
elif choice == '5':
|
|
|
|
|
save_data()
|
|
|
|
|
print("感谢使用,再见!")
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
print("输入无效,请重新选择。")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 程序入口
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
import json
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
# 全局变量
|
|
|
|
|
records = [] # 存储所有收支记录
|
|
|
|
|
categories = ['餐饮', '交通', '购物', '娱乐', '工资', '奖金', '其他'] # 收支类别
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_data():
|
|
|
|
|
"""从文件加载数据"""
|
|
|
|
|
global records
|
|
|
|
|
try:
|
|
|
|
|
with open('finance_data.json', 'r', encoding='utf-8') as f:
|
|
|
|
|
records = json.load(f)
|
|
|
|
|
print("历史数据加载成功!")
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
print("未找到历史数据,将创建新文件。")
|
|
|
|
|
records = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_data():
|
|
|
|
|
"""保存数据到文件"""
|
|
|
|
|
with open('finance_data.json', 'w', encoding='utf-8') as f:
|
|
|
|
|
json.dump(records, f, ensure_ascii=False, indent=2)
|
|
|
|
|
print("数据已保存!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_record():
|
|
|
|
|
"""添加收支记录"""
|
|
|
|
|
print("\n--- 添加收支记录 ---")
|
|
|
|
|
|
|
|
|
|
# 输入数据
|
|
|
|
|
amount = float(input("请输入金额(正数为收入,负数为支出):"))
|
|
|
|
|
|
|
|
|
|
print("可选类别:")
|
|
|
|
|
for i, cat in enumerate(categories, 1):
|
|
|
|
|
print(f"{i}. {cat}")
|
|
|
|
|
|
|
|
|
|
cat_choice = int(input("请选择类别编号:"))
|
|
|
|
|
category = categories[cat_choice - 1] if 1 <= cat_choice <= len(categories) else "其他"
|
|
|
|
|
|
|
|
|
|
note = input("请输入备注(可选):")
|
|
|
|
|
|
|
|
|
|
# 创建记录字典
|
|
|
|
|
record = {
|
|
|
|
|
'id': len(records) + 1,
|
|
|
|
|
'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
|
|
|
|
|
'amount': amount,
|
|
|
|
|
'category': category,
|
|
|
|
|
'note': note
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
records.append(record)
|
|
|
|
|
print(f"记录添加成功!ID:{record['id']}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def query_records():
|
|
|
|
|
"""查询收支记录"""
|
|
|
|
|
print("\n--- 查询记录 ---")
|
|
|
|
|
print("1. 查看所有记录")
|
|
|
|
|
print("2. 按日期查询")
|
|
|
|
|
print("3. 按类别查询")
|
|
|
|
|
|
|
|
|
|
choice = input("请选择查询方式:")
|
|
|
|
|
|
|
|
|
|
if choice == '1':
|
|
|
|
|
display_records(records)
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
date_str = input("请输入日期(YYYY-MM-DD):")
|
|
|
|
|
filtered = [r for r in records if r['date'].startswith(date_str)]
|
|
|
|
|
display_records(filtered)
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
print("可选类别:")
|
|
|
|
|
for i, cat in enumerate(categories, 1):
|
|
|
|
|
print(f"{i}. {cat}")
|
|
|
|
|
cat_choice = int(input("请选择类别编号:"))
|
|
|
|
|
if 1 <= cat_choice <= len(categories):
|
|
|
|
|
filtered = [r for r in records if r['category'] == categories[cat_choice - 1]]
|
|
|
|
|
display_records(filtered)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_records(record_list):
|
|
|
|
|
"""显示记录列表"""
|
|
|
|
|
if not record_list:
|
|
|
|
|
print("没有找到相关记录。")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n共找到 {len(record_list)} 条记录:")
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
print(f"{'ID':<5}{'日期':<20}{'类别':<10}{'金额':<15}{'备注'}")
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
|
|
|
|
|
total_income = 0
|
|
|
|
|
total_expense = 0
|
|
|
|
|
|
|
|
|
|
for record in record_list:
|
|
|
|
|
amount = record['amount']
|
|
|
|
|
if amount > 0:
|
|
|
|
|
total_income += amount
|
|
|
|
|
else:
|
|
|
|
|
total_expense += abs(amount)
|
|
|
|
|
|
|
|
|
|
print(f"{record['id']:<5}{record['date']:<20}"
|
|
|
|
|
f"{record['category']:<10}{amount:<15.2f}{record['note']}")
|
|
|
|
|
|
|
|
|
|
print("-" * 60)
|
|
|
|
|
print(f"总收入:{total_income:.2f} | 总支出:{total_expense:.2f} | 结余:{total_income - total_expense:.2f}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def statistics():
|
|
|
|
|
"""统计报表功能"""
|
|
|
|
|
if not records:
|
|
|
|
|
print("暂无数据可统计。")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print("\n--- 财务统计报表 ---")
|
|
|
|
|
|
|
|
|
|
# 计算各类别支出
|
|
|
|
|
expense_by_category = {}
|
|
|
|
|
income_total = 0
|
|
|
|
|
expense_total = 0
|
|
|
|
|
|
|
|
|
|
for record in records:
|
|
|
|
|
amount = record['amount']
|
|
|
|
|
category = record['category']
|
|
|
|
|
|
|
|
|
|
if amount > 0:
|
|
|
|
|
income_total += amount
|
|
|
|
|
else:
|
|
|
|
|
expense_total += abs(amount)
|
|
|
|
|
if category not in expense_by_category:
|
|
|
|
|
expense_by_category[category] = 0
|
|
|
|
|
expense_by_category[category] += abs(amount)
|
|
|
|
|
|
|
|
|
|
# 显示统计结果
|
|
|
|
|
print(f"记录总数:{len(records)}")
|
|
|
|
|
print(f"总收入:{income_total:.2f}")
|
|
|
|
|
print(f"总支出:{expense_total:.2f}")
|
|
|
|
|
print(f"净结余:{income_total - expense_total:.2f}")
|
|
|
|
|
|
|
|
|
|
print("\n支出类别分布:")
|
|
|
|
|
if expense_by_category:
|
|
|
|
|
for category, amount in expense_by_category.items():
|
|
|
|
|
percentage = (amount / expense_total * 100) if expense_total > 0 else 0
|
|
|
|
|
print(f" {category}: {amount:.2f} ({percentage:.1f}%)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main_menu():
|
|
|
|
|
"""主菜单"""
|
|
|
|
|
load_data() # 启动时加载数据
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
print("\n" + "=" * 50)
|
|
|
|
|
print(" 个人财务管理系统")
|
|
|
|
|
print("=" * 50)
|
|
|
|
|
print("1. 添加收支记录")
|
|
|
|
|
print("2. 查询记录")
|
|
|
|
|
print("3. 财务统计")
|
|
|
|
|
print("4. 保存数据")
|
|
|
|
|
print("5. 退出系统")
|
|
|
|
|
|
|
|
|
|
choice = input("\n请选择操作(1-5):")
|
|
|
|
|
|
|
|
|
|
if choice == '1':
|
|
|
|
|
add_record()
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
query_records()
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
statistics()
|
|
|
|
|
elif choice == '4':
|
|
|
|
|
save_data()
|
|
|
|
|
elif choice == '5':
|
|
|
|
|
save_data()
|
|
|
|
|
print("感谢使用,再见!")
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
print("输入无效,请重新选择。")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 程序入口
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main_menu()
|