From fa1a7e559b7dc90e988c007092c3d74ecd7a5094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=91=D0=B0?= =?UTF-8?q?=D0=B3=D0=B8=D0=BD?= Date: Thu, 2 Apr 2026 19:14:31 +0000 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C=20fi?= =?UTF-8?q?nance=5Fmanager.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- finance_manager.py | 263 --------------------------------------------- 1 file changed, 263 deletions(-) delete mode 100644 finance_manager.py diff --git a/finance_manager.py b/finance_manager.py deleted file mode 100644 index 68d96a9..0000000 --- a/finance_manager.py +++ /dev/null @@ -1,263 +0,0 @@ -import csv -from datetime import datetime, timedelta - -def load_transactions(filepath: str) -> list[dict]: - """Загружает список транзакций из CSV-файла.""" - transactions = [] - try: - with open(filepath, 'r', encoding='utf-8') as file: - reader = csv.DictReader(file) - for row in reader: - try: - transaction = { - 'id': int(row['id']), - 'date': row['date'], - 'amount': float(row['amount']), - 'category': row['category'], - 'description': row['description'] - } - transactions.append(transaction) - except (ValueError, KeyError): - # Пропускаем строки с некорректным форматом - continue - print(f"Загружено транзакций: {len(transactions)}") - return transactions - except FileNotFoundError: - print(f"Ошибка: Файл {filepath} не найден") - return [] - except Exception as e: - print(f"Ошибка при чтении файла: {e}") - return [] - -def filter_by_date_range(transactions: list[dict], start_date: str, end_date: str) -> list[dict]: - """Фильтрует транзакции по диапазону дат.""" - return [t for t in transactions if start_date <= t['date'] <= end_date] - -def filter_by_category(transactions: list[dict], categories: list[str], exclude: bool = False) -> list[dict]: - """ - Фильтрует транзакции по категориям. - - Параметры: - - transactions: список транзакций. - - categories:список категорий для фильтрации - - exclude: если True - исключает указанные категории, если False - оставляет только их - - Возвращает: отфильтрованый список транзакций - """ - categories_lower = [c.lower() for c in categories] - if exclude: - return [t for t in transactions if t['category'].lower() not in categories_lower] - else: - return [t for t in transactions if t['category'].lower() in categories_lower] - -def filter_by_amount_threshold(transactions: list[dict], min_amount: float = None, max_amount: float = None) -> list[dict]: - """Фильтрует транзакции по диапазону сумм""" - result = transactions - if min_amount is not None: - result = [t for t in result if t['amount'] >= min_amount] - if max_amount is not None: - result = [t for t in result if t['amount'] <= max_amount] - return result - -def calculate_balance(transactions: list[dict]) -> float: - """Вычисляет общий баланс""" - balance = sum(t['amount'] for t in transactions) - return round(balance, 2) - -def group_by_category(transactions: list[dict]) -> dict[str, float]: - """Группирует транзакции по категориям""" - groups = {} - for t in transactions: - category = t['category'] - groups[category] = groups.get(category, 0) + t['amount'] - return {cat: round(amount, 2) for cat, amount in groups.items()} - -def get_top_expenses(transactions: list[dict], n: int) -> list[dict]: - """Возвращает n транзакций с наибольшими расходами.""" - expenses = [t for t in transactions if t['amount'] < 0] - expenses.sort(key=lambda x: x['amount']) # Сортировка от наиболее отрицательных - return expenses[:n] - -def get_average_daily_expenses(transactions: list[dict], days: int = 30) -> float: - """Вычисляет среднюю сумму расходов за последние days дней.""" - if not transactions: - return 0.0 - - # Находим самую позднюю дату - latest_date = max(t['date'] for t in transactions) - latest_date_obj = datetime.strptime(latest_date, "%Y-%m-%d") - start_date_obj = latest_date_obj - timedelta(days=days - 1) - start_date = start_date_obj.strftime("%Y-%m-%d") - - # Фильтруем расходы за указанный период - expenses_in_period = [ - t for t in transactions - if t['amount'] < 0 and start_date <= t['date'] <= latest_date - ] - - if not expenses_in_period: - return 0.0 - - total_expenses = abs(sum(t['amount'] for t in expenses_in_period)) - return round(total_expenses / days, 2) - -def find_transactions_by_text(transactions: list[dict], keyword: str) -> list[dict]: - """находит транзакции по ключевому слову в описании.""" - keyword_lower = keyword.lower() - return [t for t in transactions if keyword_lower in t['description'].lower()] - -def generate_summary_report(transactions: list[dict]) -> str: - """генерирует текстовый отчет по транзакциям.""" - if not transactions: - return "Нет данных для формирования отчета" - - total_count = len(transactions) - incomes = [t for t in transactions if t['amount'] > 0] - expenses = [t for t in transactions if t['amount'] < 0] - - total_income = sum(t['amount'] for t in incomes) - total_expense = abs(sum(t['amount'] for t in expenses)) - balance = total_income - total_expense - - # Топ-3 категории по расходам - expenses_by_category = {} - for t in expenses: - expenses_by_category[t['category']] = expenses_by_category.get(t['category'], 0) + abs(t['amount']) - top_categories = sorted(expenses_by_category.items(), key=lambda x: x[1], reverse=True)[:3] - - # Самая крупная расходная транзакция - largest_expense = min(expenses, key=lambda x: x['amount']) if expenses else None - - # Формируем отчёт - report = [] - report.append("=" * 50) - report.append("ФИНАНСОВЫЙ ОТЧЕТ") - report.append("=" * 50) - report.append(f"Всего транзакций: {total_count}") - report.append(f"Общий доход: {total_income:.2f} руб.") - report.append(f"Общий расход: {total_expense:.2f} руб.") - report.append(f"Итоговый баланс: {balance:.2f} руб.") - report.append("-" * 50) - report.append("ТОП-3 КАТЕГОРИИ ПО РАСХОДАМ:") - for i, (cat, amount) in enumerate(top_categories, 1): - report.append(f" {i}. {cat}: {amount:.2f} руб.") - - if largest_expense: - report.append("-" * 50) - report.append("САМАЯ КРУПНАЯ РАСХОДНАЯ ТРАНЗАКЦИЯ:") - report.append(f" Дата: {largest_expense['date']}") - report.append(f" Категория: {largest_expense['category']}") - report.append(f" Сумма: {largest_expense['amount']:.2f} руб.") - report.append(f" Описание: {largest_expense['description']}") - report.append("=" * 50) - - return "\n".join(report) - -def main(): - """Главная функция, демонстрирующая работу всех функций.""" - print("=" * 60) - print("СИСТЕМА УПРАВЛЕНИЯ ЛИЧНЫМИ ФИНАНСАМИ") - print("=" * 60) - - # 1.Загрузка данных - print("\n1. ЗАГРУЗКА ДАННЫХ") - print("-" * 40) - transactions = load_transactions('data/transactions.txt') - - if not transactions: - print("Нет данных для обработки. Завершение работы.") - return - - # 2. Фильтрация по дате (последние 90 дней) - print("\n2. ФИЛЬТРАЦИЯ ПО ДАТЕ (последние 90 дней)") - print("-" * 40) - - # Находим самую позднюю и самую раннюю дату - latest_date = max(t['date'] for t in transactions) - earliest_date = min(t['date'] for t in transactions) - latest_date_obj = datetime.strptime(latest_date, "%Y-%m-%d") - - # Вычисляем дату 90 дней назад - start_date_obj = latest_date_obj - timedelta(days=89) - start_date = start_date_obj.strftime("%Y-%m-%d") - end_date = latest_date - - # Если start_date раньше earliest_date, то используем earliest_date - if start_date < earliest_date: - start_date = earliest_date - print(f"Примечание: Данных за последние 90 дней недостаточно") - print(f"Используем все доступные данные с {start_date} по {end_date}") - else: - print(f"Период: с {start_date} по {end_date}") - - filtered_by_date = filter_by_date_range(transactions, start_date, end_date) - print(f"Транзакций после фильтрации по дате: {len(filtered_by_date)}") - - # 3. Фильтрация по категориям (исключаем "Перевод" и "Инвестиции") - print("\n3. ФИЛЬТРАЦИЯ ПО КАТЕГОРИЯМ (исключаем 'Перевод' и 'Инвестиции')") - print("-" * 40) - - excluded_categories = ["Перевод", "Инвестиции"] - filtered_by_category_data = filter_by_category(filtered_by_date, excluded_categories, exclude=True) - print(f"Транзакций после фильтрации по категориям: {len(filtered_by_category_data)}") - - # 4. Расчёт баланса - print("\n4. РАСЧЁТ БАЛАНСА") - print("-" * 40) - balance = calculate_balance(filtered_by_category_data) - print(f"Баланс за период: {balance:.2f} руб.") - - # 5. Топ-5 расходов - print("\n5. ТОП-5 РАСХОДОВ") - print("-" * 40) - top_expenses = get_top_expenses(filtered_by_category_data, 5) - if top_expenses: - for i, expense in enumerate(top_expenses, 1): - print(f"{i}. {expense['date']} | {expense['category']} | {expense['amount']:.2f} руб. | {expense['description']}") - else: - print("Нет расходов за указанный период") - - # 6. Поиск транзакций по ключевому слову "кафе" - print("\n6. ПОИСК ПО КЛЮЧЕВОМУ СЛОВУ 'кафе'") - print("-" * 40) - found_transactions = find_transactions_by_text(filtered_by_category_data, "кафе") - if found_transactions: - print(f"Найдено транзакций: {len(found_transactions)}") - for t in found_transactions: - print(f" {t['date']} | {t['category']} | {t['amount']:.2f} руб. | {t['description']}") - else: - print("Транзакции с ключевым словом 'кафе' не найдены") - - # 7. Среднедневные расходы за последние 30 дней - print("\n7. СРЕДНЕДНЕВНЫЕ РАСХОДЫ (последние 30 дней)") - print("-" * 40) - avg_expenses = get_average_daily_expenses(filtered_by_category_data, 30) - print(f"Среднедневные расходы: {avg_expenses:.2f} руб.") - - # 8. Группировка по категориям - print("\n8. ГРУППИРОВКА ПО КАТЕГОРИЯМ") - print("-" * 40) - grouped = group_by_category(filtered_by_category_data) - for category, amount in sorted(grouped.items(), key=lambda x: x[1], reverse=True): - print(f" {category}: {amount:.2f} руб.") - - # 9. Итоговый отчет - print("\n9. ИТОГОВЫЙ ОТЧЕТ") - print("-" * 40) - report = generate_summary_report(filtered_by_category_data) - print(report) - - # 10. Демонстрация фильтрации по сумме - print("\n10. ДЕМОНСТРАЦИЯ ФИЛЬТРАЦИИ ПО СУММЕ") - print("-" * 40) - large_expenses = filter_by_amount_threshold(filtered_by_category_data, max_amount=-500) - print(f"Расходы более 500 руб. (сумма < -500): {len(large_expenses)} транзакций") - for expense in large_expenses[:3]: # Показываем первые 3 - print(f" {expense['date']} | {expense['category']} | {expense['amount']:.2f} руб.") - - print("\n" + "=" * 60) - print("ОБРАБОТКА ЗАВЕРШЕНА") - print("=" * 60) - -if __name__ == "__main__": - main()