智能信用卡账单管家
1. 项目概述
实际应用场景
在现代金融生活中,信用卡已成为人们日常消费的重要工具。然而,许多持卡人面临着以下困扰:
- 忘记还款日期导致逾期产生高额罚息
- 不清楚最低还款额和全额还款的区别
- 多张信用卡管理混乱,容易遗漏
- 无法合理规划资金,影响信用记录
痛点分析
1. 记忆负担重: 每张卡的还款日不同,容易混淆
2. 计算复杂: 最低还款额涉及利息、手续费等复杂计算
3. 风险意识不足: 不了解逾期的严重后果
4. 资金管理困难: 无法提前规划现金流
5. 信息分散: 账单信息散落在各银行APP中
2. 核心逻辑
系统架构
输入层 → 数据处理层 → 计算引擎层 → 提醒服务层 → 输出层
↓ ↓ ↓ ↓ ↓
账单信息 数据验证 金额计算 定时提醒 报表展示
关键算法
1. 最低还款额计算: 基于央行规定的标准计算方法
2. 逾期风险评估: 基于还款能力和历史记录
3. 智能提醒算法: 考虑节假日和工作日的提醒策略
4. 现金流优化: 多卡还款的最优时间安排
3. 代码实现
项目结构
credit_card_manager/
├── main.py # 主程序入口
├── config.py # 配置文件
├── models/ # 数据模型
│ ├── card.py # 信用卡类
│ ├── bill.py # 账单类
│ └── payment.py # 还款记录类
├── services/ # 业务服务
│ ├── calculator.py # 计算服务
│ ├── reminder.py # 提醒服务
│ ├── analyzer.py # 分析服务
│ └── storage.py # 存储服务
├── utils/ # 工具函数
│ ├── date_utils.py # 日期工具
│ ├── notification.py # 通知工具
│ └── validators.py # 验证器
├── data/ # 数据目录
│ ├── cards.json # 卡片数据
│ ├── bills.json # 账单数据
│ └── payments.json # 还款记录
└── reports/ # 报表目录
├── monthly_report.html
└── debt_analysis.pdf
核心代码
main.py - 主程序
#!/usr/bin/env python3
"""
智能信用卡账单管家主程序
"""
import sys
import json
import argparse
from datetime import datetime, timedelta
from typing import List, Dict, Optional
from pathlib import Path
from models.card import CreditCard
from models.bill import Bill
from models.payment import PaymentRecord
from services.calculator import PaymentCalculator
from services.reminder import ReminderService
from services.analyzer import DebtAnalyzer
from services.storage import DataStorage
from utils.date_utils import DateUtils
from utils.notification import NotificationManager
from config import Config
class CreditCardManager:
"""信用卡管理器"""
def __init__(self):
self.config = Config()
self.storage = DataStorage()
self.calculator = PaymentCalculator()
self.reminder = ReminderService()
self.analyzer = DebtAnalyzer()
self.notifier = NotificationManager()
# 加载数据
self.cards = self.storage.load_cards()
self.bills = self.storage.load_bills()
self.payments = self.storage.load_payments()
print("🏦 智能信用卡账单管家启动成功!")
print(f"📊 当前管理 {len(self.cards)} 张信用卡")
print(f"💳 本月待还账单 {len([b for b in self.bills if not b.is_paid])} 笔")
def run(self, mode="interactive"):
"""
运行主程序
Args:
mode: 运行模式 (interactive/batch/report)
"""
try:
if mode == "interactive":
self._run_interactive_mode()
elif mode == "batch":
self._run_batch_mode()
elif mode == "report":
self._generate_reports()
elif mode == "daemon":
self._run_daemon_mode()
except KeyboardInterrupt:
print("\n\n👋 感谢使用,再见!")
self._save_all_data()
except Exception as e:
print(f"❌ 程序运行出错: {e}")
self._save_all_data()
def _run_interactive_mode(self):
"""交互式模式"""
while True:
self._clear_screen()
print("🏦 智能信用卡账单管家")
print("=" * 50)
print("1. 💳 添加信用卡")
print("2. 📄 录入账单")
print("3. 💰 计算还款金额")
print("4. ⏰ 设置还款提醒")
print("5. 📊 查看账单概览")
print("6. 📈 债务分析报告")
print("7. 🔔 检查到期提醒")
print("8. 📋 还款记录管理")
print("9. ⚙️ 系统设置")
print("0. 🚪 退出系统")
choice = input("\n请选择操作 (0-9): ").strip()
if choice == "1":
self._add_credit_card()
elif choice == "2":
self._add_bill()
elif choice == "3":
self._calculate_payments()
elif choice == "4":
self._setup_reminders()
elif choice == "5":
self._show_bills_overview()
elif choice == "6":
self._show_debt_analysis()
elif choice == "7":
self._check_reminders()
elif choice == "8":
self._manage_payments()
elif choice == "9":
self._system_settings()
elif choice == "0":
break
else:
print("⚠️ 无效选择,请重新输入")
input("\n按回车键继续...")
def _add_credit_card(self):
"""添加信用卡"""
self._clear_screen()
print("💳 添加信用卡")
print("-" * 30)
try:
card_number = input("信用卡号 (后4位即可): ").strip()
bank_name = input("发卡银行: ").strip()
card_name = input("卡片名称 (如:招行白金): ").strip()
credit_limit = float(input("信用额度: "))
billing_day = int(input("账单日 (1-31): "))
due_day = int(input("还款日 (1-31): "))
# 创建信用卡对象
card = CreditCard(
card_number=card_number,
bank_name=bank_name,
card_name=card_name,
credit_limit=credit_limit,
billing_day=billing_day,
due_day=due_day
)
# 验证信用卡信息
if not card.validate():
print("❌ 信用卡信息验证失败")
return
# 保存信用卡
self.cards.append(card)
self.storage.save_cards(self.cards)
print(f"✅ 成功添加信用卡: {card.display_name}")
input("\n按回车键继续...")
except ValueError as e:
print(f"❌ 输入格式错误: {e}")
input("\n按回车键继续...")
except Exception as e:
print(f"❌ 添加失败: {e}")
input("\n按回车键继续...")
def _add_bill(self):
"""录入账单"""
self._clear_screen()
print("📄 录入账单")
print("-" * 30)
if not self.cards:
print("📝 请先添加信用卡")
input("\n按回车键继续...")
return
# 显示可用信用卡
print("可用信用卡:")
for i, card in enumerate(self.cards, 1):
print(f"{i}. {card.display_name}")
try:
card_index = int(input("\n选择信用卡: ")) - 1
if not (0 <= card_index < len(self.cards)):
print("❌ 无效的卡片选择")
return
selected_card = self.cards[card_index]
# 获取账单信息
statement_date = input("账单日期 (YYYY-MM-DD): ").strip()
statement_date = datetime.strptime(statement_date, "%Y-%m-%d").date()
total_amount = float(input("账单总金额: "))
minimum_payment = float(input("最低还款额: "))
interest_rate = float(input("年利率 (%): ")) / 100
due_date = input("到期还款日 (YYYY-MM-DD): ").strip()
due_date = datetime.strptime(due_date, "%Y-%m-%d").date()
# 创建账单对象
bill = Bill(
card_id=selected_card.card_id,
statement_date=statement_date,
total_amount=total_amount,
minimum_payment=minimum_payment,
interest_rate=interest_rate,
due_date=due_date
)
# 验证账单
if not bill.validate():
print("❌ 账单信息验证失败")
return
# 保存账单
self.bills.append(bill)
self.storage.save_bills(self.bills)
print(f"✅ 成功录入账单: {bill.bill_id}")
print(f"💰 应还总额: ¥{bill.total_amount:,.2f}")
print(f"🔻 最低还款: ¥{bill.minimum_payment:,.2f}")
print(f"⏰ 到期日期: {bill.due_date}")
# 自动设置提醒
self.reminder.set_bill_reminder(bill)
input("\n按回车键继续...")
except ValueError as e:
print(f"❌ 输入格式错误: {e}")
input("\n按回车键继续...")
except Exception as e:
print(f"❌ 录入失败: {e}")
input("\n按回车键继续...")
def _calculate_payments(self):
"""计算还款金额"""
self._clear_screen()
print("💰 还款金额计算器")
print("-" * 30)
unpaid_bills = [bill for bill in self.bills if not bill.is_paid]
if not unpaid_bills:
print("🎉 当前没有待还账单")
input("\n按回车键继续...")
return
print(f"发现 {len(unpaid_bills)} 笔待还账单:\n")
total_minimum = 0
total_full = 0
for i, bill in enumerate(unpaid_bills, 1):
card = self._find_card_by_id(bill.card_id)
days_until_due = (bill.due_date - datetime.now().date()).days
print(f"{i}. {card.display_name}")
print(f" 账单金额: ¥{bill.total_amount:,.2f}")
print(f" 最低还款: ¥{bill.minimum_payment:,.2f}")
print(f" 到期天数: {days_until_due} 天")
if days_until_due <= 3:
print(" ⚠️ 即将到期!")
elif days_until_due < 0:
print(" 🚨 已逾期!")
print()
total_minimum += bill.minimum_payment
total_full += bill.total_amount
print("=" * 40)
print(f"📊 汇总信息:")
print(f" 最低还款总额: ¥{total_minimum:,.2f}")
print(f" 全额还款总额: ¥{total_full:,.2f}")
print(f" 差额: ¥{total_full - total_minimum:,.2f}")
# 提供建议
self._provide_payment_advice(unpaid_bills, total_minimum, total_full)
input("\n按回车键继续...")
def _provide_payment_advice(self, bills: List[Bill], total_minimum: float, total_full: float):
"""提供还款建议"""
print("\n💡 还款建议:")
# 分析现金流压力
user_income = float(input("请输入本月可用资金: ¥"))
if user_income >= total_full:
print("✅ 资金充足,建议全额还款避免利息")
elif user_income >= total_minimum:
print("⚠️ 资金紧张,建议至少还清最低还款额")
print(" 注意:未还清部分将产生循环利息")
else:
print("🚨 资金不足,建议:")
print(" 1. 优先还清利率最高的卡片")
print(" 2. 考虑分期付款减少压力")
print(" 3. 联系银行协商还款方案")
# 分析逾期风险
high_risk_bills = [bill for bill in bills if (bill.due_date - datetime.now().date()).days < 0]
if high_risk_bills:
print(f"\n🚨 发现 {len(high_risk_bills)} 笔逾期账单!")
print(" 建议立即还款并联系银行说明情况")
def _setup_reminders(self):
"""设置还款提醒"""
self._clear_screen()
print("⏰ 还款提醒设置")
print("-" * 30)
print("1. 为所有账单设置提醒")
print("2. 为特定账单设置提醒")
print("3. 修改提醒设置")
print("4. 查看提醒状态")
choice = input("\n请选择 (1-4): ").strip()
if choice == "1":
for bill in self.bills:
if not bill.is_paid:
self.reminder.set_bill_reminder(bill)
print("✅ 已为所有待还账单设置提醒")
elif choice == "2":
self._setup_specific_reminder()
elif choice == "3":
self._modify_reminder_settings()
elif choice == "4":
self._show_reminder_status()
input("\n按回车键继续...")
def _show_bills_overview(self):
"""显示账单概览"""
self._clear_screen()
print("📊 账单概览")
print("=" * 50)
# 统计信息
total_bills = len(self.bills)
paid_bills = len([b for b in self.bills if b.is_paid])
unpaid_bills = total_bills - paid_bills
overdue_bills = [b for b in self.bills if not b.is_paid and b.is_overdue()]
print(f"📈 统计信息:")
print(f" 总账单数: {total_bills}")
print(f" 已还款: {paid_bills}")
print(f" 待还款: {unpaid_bills}")
print(f" 逾期账单: {len(overdue_bills)}")
if overdue_bills:
print("\n🚨 逾期账单详情:")
for bill in overdue_bills:
card = self._find_card_by_id(bill.card_id)
days_overdue = bill.days_overdue()
print(f" • {card.display_name}: ¥{bill.total_amount:,.2f} (逾期{days_overdue}天)")
# 待还账单列表
if unpaid_bills > 0:
print("\n📋 待还账单列表:")
unpaid = [b for b in self.bills if not b.is_paid]
for i, bill in enumerate(sorted(unpaid, key=lambda x: x.due_date), 1):
card = self._find_card_by_id(bill.card_id)
days_left = (bill.due_date - datetime.now().date()).days
status = "🚨逾期" if days_left < 0 else f"⏰{days_left}天"
print(f" {i}. {card.display_name} - ¥{bill.total_amount:,.2f} ({status})")
input("\n按回车键继续...")
def _show_debt_analysis(self):
"""显示债务分析"""
self._clear_screen()
print("📈 债务分析报告")
print("=" * 50)
analysis = self.analyzer.analyze_debt(self.cards, self.bills, self.payments)
# 总体债务情况
print("💳 总体债务情况:")
print(f" 总信用额度: ¥{analysis['total_credit_limit']:,.2f}")
print(f" 当前负债: ¥{analysis['total_debt']:,.2f}")
print(f" 信用利用率: {analysis['credit_utilization']:.1%}")
print(f" 可用额度: ¥{analysis['available_credit']:,.2f}")
# 债务健康度评级
health_score = analysis['health_score']
if health_score >= 80:
grade = "优秀 🟢"
elif health_score >= 60:
grade = "良好 🟡"
elif health_score >= 40:
grade = "一般 🟠"
else:
grade = "较差 🔴"
print(f"\n🏥 债务健康度: {grade} ({health_score:.0f}/100)")
# 月度趋势
if analysis['monthly_trend']:
print("\n📊 近6个月趋势:")
for month, data in analysis['monthly_trend'].items():
print(f" {month}: 支出¥{data['spending']:,.2f}, 还款¥{data['payment']:,.2f}")
# 优化建议
print("\n💡 优化建议:")
for suggestion in analysis['suggestions']:
print(f" • {suggestion}")
input("\n按回车键继续...")
def _check_reminders(self):
"""检查到期提醒"""
self._clear_screen()
print("🔔 到期提醒检查")
print("-" * 30)
reminders = self.reminder.check_due_reminders()
if not reminders:
print("🎉 当前没有需要提醒的账单")
else:
print(f"发现 {len(reminders)} 个提醒:\n")
for reminder in reminders:
bill = reminder['bill']
card = self._find_card_by_id(bill.card_id)
print(f"🚨 {reminder['title']}")
print(f" 卡片: {card.display_name}")
print(f" 金额: ¥{bill.total_amount:,.2f}")
print(f" 到期: {bill.due_date}")
print(f" 剩余: {reminder['days_left']} 天")
print()
# 发送通知
if reminders and self.config.enable_notifications:
self.notifier.send_bulk_notification(reminders)
print("📱 已发送通知提醒")
input("\n按回车键继续...")
def _manage_payments(self):
"""还款记录管理"""
self._clear_screen()
print("📋 还款记录管理")
print("-" * 30)
print("1. 记录还款")
print("2. 查看还款历史")
print("3. 修改还款记录")
print("4. 删除还款记录")
choice = input("\n请选择 (1-4): ").strip()
if choice == "1":
self._record_payment()
elif choice == "2":
self._show_payment_history()
elif choice == "3":
self._modify_payment()
elif choice == "4":
self._delete_payment()
input("\n按回车键继续...")
def _record_payment(self):
"""记录还款"""
print("💸 记录还款")
unpaid_bills = [bill for bill in self.bills if not bill.is_paid]
if not unpaid_bills:
print("🎉 没有待还账单")
return
# 显示待还账单
for i, bill in enumerate(unpaid_bills, 1):
card = self._find_card_by_id(bill.card_id)
print(f"{i}. {card.display_name} - ¥{bill.total_amount:,.2f}")
try:
bill_index = int(input("\n选择要还款的账单: ")) - 1
if not (0 <= bill_index < len(unpaid_bills)):
print("❌ 无效选择")
return
selected_bill = unpaid_bills[bill_index]
payment_amount = float(input("还款金额: ¥"))
payment_method = input("还款方式 (银行转账/支付宝/微信等): ").strip()
payment_date_str = input("还款日期 (YYYY-MM-DD,回车使用今天): ").strip()
payment_date = (datetime.now().date() if not payment_date_str
else datetime.strptime(payment_date_str, "%Y-%m-%d").date())
# 创建还款记录
payment = PaymentRecord(
bill_id=selected_bill.bill_id,
amount=payment_amount,
payment_date=payment_date,
payment_method=payment_method
)
# 更新账单状态
if payment_amount >= selected_bill.total_amount:
selected_bill.mark_as_paid()
else:
selected_bill.paid_amount += payment_amount
# 保存数据
self.payments.append(payment)
self.storage.save_payments(self.payments)
self.storage.save_bills(self.bills)
print(f"✅ 还款记录已保存")
print(f" 还款金额: ¥{payment_amount:,.2f}")
print(f" 剩余应还: ¥{selected_bill.remaining_amount():,.2f}")
except ValueError as e:
print(f"❌ 输入错误: {e}")
def _find_card_by_id(self, card_id: str) -> Optional[CreditCard]:
"""根据ID查找信用卡"""
for card in self.cards:
if card.card_id == card_id:
return card
return None
def _clear_screen(self):
"""清屏"""
os.system('cls' if os.name == 'nt' else 'clear')
def _save_all_data(self):
"""保存所有数据"""
self.storage.save_cards(self.cards)
self.storage.save_bills(self.bills)
self.storage.save_payments(self.payments)
print("💾 数据已保存")
def _run_batch_mode(self):
"""批处理模式"""
print("🔄 批处理模式")
# 实现批量导入、批量计算等功能
pass
def _generate_reports(self):
"""生成报表"""
print("📊 生成报表")
# 生成月度报告、年度分析等
pass
def _run_daemon_mode(self):
"""守护进程模式"""
print("🔄 守护进程模式启动")
# 后台监控和提醒
pass
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='智能信用卡账单管家')
parser.add_argument('--mode', choices=['interactive', 'batch', 'report', 'daemon'],
default='interactive', help='运行模式')
parser.add_argument('--config', help='配置文件路径')
args = parser.parse_args()
manager = CreditCardManager()
manager.run(args.mode)
if __name__ == "__main__":
main()
models/card.py - 信用卡模型
"""
信用卡数据模型
"""
from dataclasses import dataclass, asdict
from datetime import date
from typing import Optional
import uuid
import re
@dataclass
class CreditCard:
"""信用卡类"""
card_id: str
card_number: str
bank_name: str
card_name: str
credit_limit: float
billing_day: int
due_day: int
is_active: bool = True
created_at: Optional[date] = None
def __post_init__(self):
if self.created_at is None:
self.created_at = date.today()
# 生成唯一ID
if not self.card_id:
self.card_id = str(uuid.uuid4())[:8]
@property
def display_name(self) -> str:
"""显示名称"""
return f"{self.bank_name} - {self.card_name}"
@pr
如果你觉得这个工具好用,欢迎关注我!