From e5393ca2689fe544b38fe9f948905c4d7f2a4817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D0=BB=20=D0=A0=D1=83=D1=81=D1=81?= =?UTF-8?q?=D0=BA=D0=B8=D1=85?= Date: Sat, 4 Apr 2026 12:16:50 +0300 Subject: [PATCH] feat: initial commit - bank transaction analyzer --- .gitignore | 6 + requirements.txt | 1 + транзакции интернет банка/data.txt | 3 + транзакции интернет банка/data/report.txt | 7 + .../data/transactions.json | 218 +++++++++ .../financial_report.txt | 33 ++ транзакции интернет банка/report.txt | 19 + .../reports/financial_report.txt | 52 +++ .../транзакции интернет банка.pyproj | 35 ++ .../транзакции интернет банка.sln | 23 + .../транзакции_интернет_банка.py | 417 ++++++++++++++++++ 11 files changed, 814 insertions(+) create mode 100644 .gitignore create mode 100644 requirements.txt create mode 100644 транзакции интернет банка/data.txt create mode 100644 транзакции интернет банка/data/report.txt create mode 100644 транзакции интернет банка/data/transactions.json create mode 100644 транзакции интернет банка/financial_report.txt create mode 100644 транзакции интернет банка/report.txt create mode 100644 транзакции интернет банка/reports/financial_report.txt create mode 100644 транзакции интернет банка/транзакции интернет банка.pyproj create mode 100644 транзакции интернет банка/транзакции интернет банка.sln create mode 100644 транзакции интернет банка/транзакции_интернет_банка.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f86f62 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.venv/ +__pycache__/ +*.pyc +.vs/ +reports/*.txt +*.backup.json diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7df3edc --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +# Нет внешних зависимостей, только стандартная библиотека diff --git a/транзакции интернет банка/data.txt b/транзакции интернет банка/data.txt new file mode 100644 index 0000000..f425310 --- /dev/null +++ b/транзакции интернет банка/data.txt @@ -0,0 +1,3 @@ +tx001|1|1500.50|Продукты|2024-01-15 10:30:00|False|1234 +tx002|1|250.00|Кафе|2024-01-15 12:45:00|False|1234 +tx003|2|5000.00|Электроника|2024-01-15 15:20:00|True|5678 \ No newline at end of file diff --git a/транзакции интернет банка/data/report.txt b/транзакции интернет банка/data/report.txt new file mode 100644 index 0000000..e9e2a2e --- /dev/null +++ b/транзакции интернет банка/data/report.txt @@ -0,0 +1,7 @@ +=== Отчёт по отзывам === +Общее количество отзывов: 0 +Средний рейтинг: 0.0 + +Топ слов: + +Пользователи: \ No newline at end of file diff --git a/транзакции интернет банка/data/transactions.json b/транзакции интернет банка/data/transactions.json new file mode 100644 index 0000000..afb4e62 --- /dev/null +++ b/транзакции интернет банка/data/transactions.json @@ -0,0 +1,218 @@ +[ + { + "transaction_id": "TXN001", + "user_id": 1, + "amount": 1250.5, + "category": "Products", + "timestamp": "2024-01-15 10:30:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN002", + "user_id": 1, + "amount": 3500.0, + "category": "Cafe", + "timestamp": "2024-01-15 19:45:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN003", + "user_id": 1, + "amount": 450.0, + "category": "Transport", + "timestamp": "2024-01-16 08:15:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN004", + "user_id": 1, + "amount": 5600.0, + "category": "Entertainment", + "timestamp": "2024-01-16 20:30:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN005", + "user_id": 1, + "amount": 2800.0, + "category": "Products", + "timestamp": "2024-01-17 14:20:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN006", + "user_id": 1, + "amount": 12500.0, + "category": "Entertainment", + "timestamp": "2024-01-18 22:00:00", + "is_fraud": false, + "card_last_digits": "1234" + }, + { + "transaction_id": "TXN007", + "user_id": 2, + "amount": 3500.0, + "category": "Products", + "timestamp": "2024-01-15 12:00:00", + "is_fraud": false, + "card_last_digits": "5678" + }, + { + "transaction_id": "TXN008", + "user_id": 2, + "amount": 15000.0, + "category": "Transfers", + "timestamp": "2024-01-15 22:15:00", + "is_fraud": true, + "card_last_digits": "5678" + }, + { + "transaction_id": "TXN009", + "user_id": 2, + "amount": 45000.0, + "category": "Transfers", + "timestamp": "2024-01-16 23:30:00", + "is_fraud": true, + "card_last_digits": "5678" + }, + { + "transaction_id": "TXN010", + "user_id": 2, + "amount": 2800.0, + "category": "Cafe", + "timestamp": "2024-01-17 13:00:00", + "is_fraud": false, + "card_last_digits": "5678" + }, + { + "transaction_id": "TXN011", + "user_id": 2, + "amount": 32000.0, + "category": "Cash Withdrawal", + "timestamp": "2024-01-18 09:45:00", + "is_fraud": true, + "card_last_digits": "5678" + }, + { + "transaction_id": "TXN012", + "user_id": 3, + "amount": 800.0, + "category": "Transport", + "timestamp": "2024-01-15 09:00:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN013", + "user_id": 3, + "amount": 1200.0, + "category": "Products", + "timestamp": "2024-01-15 17:30:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN014", + "user_id": 3, + "amount": 4500.0, + "category": "Cafe", + "timestamp": "2024-01-16 20:00:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN015", + "user_id": 3, + "amount": 2300.0, + "category": "Products", + "timestamp": "2024-01-16 11:15:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN016", + "user_id": 3, + "amount": 6800.0, + "category": "Entertainment", + "timestamp": "2024-01-17 21:30:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN017", + "user_id": 3, + "amount": 950.0, + "category": "Transport", + "timestamp": "2024-01-18 08:45:00", + "is_fraud": false, + "card_last_digits": "9012" + }, + { + "transaction_id": "TXN018", + "user_id": 4, + "amount": 5800.0, + "category": "Utilities", + "timestamp": "2024-01-15 14:20:00", + "is_fraud": false, + "card_last_digits": "3456" + }, + { + "transaction_id": "TXN019", + "user_id": 4, + "amount": 4200.0, + "category": "Products", + "timestamp": "2024-01-16 16:45:00", + "is_fraud": false, + "card_last_digits": "3456" + }, + { + "transaction_id": "TXN020", + "user_id": 4, + "amount": 18500.0, + "category": "Transfers", + "timestamp": "2024-01-17 11:30:00", + "is_fraud": false, + "card_last_digits": "3456" + }, + { + "transaction_id": "TXN021", + "user_id": 5, + "amount": 3200.0, + "category": "Cafe", + "timestamp": "2024-01-15 12:30:00", + "is_fraud": false, + "card_last_digits": "7890" + }, + { + "transaction_id": "TXN022", + "user_id": 5, + "amount": 1500.0, + "category": "Transport", + "timestamp": "2024-01-16 18:20:00", + "is_fraud": false, + "card_last_digits": "7890" + }, + { + "transaction_id": "TXN023", + "user_id": 5, + "amount": 4700.0, + "category": "Products", + "timestamp": "2024-01-17 09:15:00", + "is_fraud": false, + "card_last_digits": "7890" + }, + { + "transaction_id": "TXN024", + "user_id": 1, + "amount": 28500.0, + "category": "Transfers", + "timestamp": "2024-01-19 03:00:00", + "is_fraud": true, + "card_last_digits": "1234" + } +] \ No newline at end of file diff --git a/транзакции интернет банка/financial_report.txt b/транзакции интернет банка/financial_report.txt new file mode 100644 index 0000000..0cea2f4 --- /dev/null +++ b/транзакции интернет банка/financial_report.txt @@ -0,0 +1,33 @@ +============================================================ +ФИНАНСОВЫЙ ОТЧЕТ +============================================================ + +Всего транзакций: 3 +Общая сумма: 6,750.50 руб. + +Обычные транзакции: + Количество: 2 + Сумма: 1,750.50 руб. + +Мошеннические транзакции: + Количество: 1 + Сумма: 5,000.00 руб. + +ТОП-5 КАТЕГОРИЙ ПО ТРАТАМ: + 1. Электроника: 5,000.00 руб. + 2. Продукты: 1,500.50 руб. + 3. Кафе: 250.00 руб. + +ТОП-3 ПОЛЬЗОВАТЕЛЯ ПО КОЛИЧЕСТВУ ТРАНЗАКЦИЙ: + 1. Пользователь 1: 2 транзакций + 2. Пользователь 2: 1 транзакций + +Уникальных пользователей: 2 + +СТАТИСТИКА ПО ДНЯМ (первые 7 дней): + 2024-01-15: + Сумма: 6,750.50 руб. + Кол-во: 3 + Средний чек: 2,250.17 руб. + +============================================================ \ No newline at end of file diff --git a/транзакции интернет банка/report.txt b/транзакции интернет банка/report.txt new file mode 100644 index 0000000..4a92266 --- /dev/null +++ b/транзакции интернет банка/report.txt @@ -0,0 +1,19 @@ +=== Отчёт по отзывам === +Общее количество отзывов: 7 +Средний рейтинг: 3.43 + +Топ слов: +- покупкой: 2 +- рекомендую: 2 +- есть: 2 +- за: 2 +- отличный: 1 + +Пользователи: +- Анна +- Дмитрий +- Елена +- Ирина +- Михаил +- Ольга +- Сергей \ No newline at end of file diff --git a/транзакции интернет банка/reports/financial_report.txt b/транзакции интернет банка/reports/financial_report.txt new file mode 100644 index 0000000..8bc60b0 --- /dev/null +++ b/транзакции интернет банка/reports/financial_report.txt @@ -0,0 +1,52 @@ +============================================================ +ФИНАНСОВЫЙ ОТЧЕТ +============================================================ + +Всего транзакций: 24 +Общая сумма: 207,350.50 руб. + +Обычные транзакции: + Количество: 20 + Сумма: 86,850.50 руб. + +Мошеннические транзакции: + Количество: 4 + Сумма: 120,500.00 руб. + +ТОП-5 КАТЕГОРИЙ ПО ТРАТАМ: + 1. Transfers: 107,000.00 руб. + 2. Cash Withdrawal: 32,000.00 руб. + 3. Entertainment: 24,900.00 руб. + 4. Products: 19,950.50 руб. + 5. Cafe: 14,000.00 руб. + +ТОП-3 ПОЛЬЗОВАТЕЛЯ ПО КОЛИЧЕСТВУ ТРАНЗАКЦИЙ: + 1. Пользователь 1: 7 транзакций + 2. Пользователь 3: 6 транзакций + 3. Пользователь 2: 5 транзакций + +Уникальных пользователей: 5 + +СТАТИСТИКА ПО ДНЯМ (первые 7 дней): + 2024-01-15: + Сумма: 34,250.50 руб. + Кол-во: 8 + Средний чек: 4,281.31 руб. + 2024-01-16: + Сумма: 63,550.00 руб. + Кол-во: 7 + Средний чек: 9,078.57 руб. + 2024-01-17: + Сумма: 35,600.00 руб. + Кол-во: 5 + Средний чек: 7,120.00 руб. + 2024-01-18: + Сумма: 45,450.00 руб. + Кол-во: 3 + Средний чек: 15,150.00 руб. + 2024-01-19: + Сумма: 28,500.00 руб. + Кол-во: 1 + Средний чек: 28,500.00 руб. + +============================================================ \ No newline at end of file diff --git a/транзакции интернет банка/транзакции интернет банка.pyproj b/транзакции интернет банка/транзакции интернет банка.pyproj new file mode 100644 index 0000000..8a97736 --- /dev/null +++ b/транзакции интернет банка/транзакции интернет банка.pyproj @@ -0,0 +1,35 @@ + + + Debug + 2.0 + 6efbf71d-f045-46ef-8006-9621f4cfde65 + . + транзакции_интернет_банка.py + + + . + . + транзакции интернет банка + транзакции интернет банка + + + true + false + + + true + false + + + + + + + + + + + + \ No newline at end of file diff --git a/транзакции интернет банка/транзакции интернет банка.sln b/транзакции интернет банка/транзакции интернет банка.sln new file mode 100644 index 0000000..bf48ece --- /dev/null +++ b/транзакции интернет банка/транзакции интернет банка.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36518.9 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "транзакции интернет банка", "транзакции интернет банка.pyproj", "{6EFBF71D-F045-46EF-8006-9621F4CFDE65}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6EFBF71D-F045-46EF-8006-9621F4CFDE65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EFBF71D-F045-46EF-8006-9621F4CFDE65}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {280AB7AA-1880-4723-92BD-77A223A9F832} + EndGlobalSection +EndGlobal diff --git a/транзакции интернет банка/транзакции_интернет_банка.py b/транзакции интернет банка/транзакции_интернет_банка.py new file mode 100644 index 0000000..f704bd1 --- /dev/null +++ b/транзакции интернет банка/транзакции_интернет_банка.py @@ -0,0 +1,417 @@ +import json +import sys +from datetime import datetime +from collections import defaultdict + + +def zagruzit_tranzaktsii(filepath): + transaktsii = [] + + try: + with open(filepath, 'r', encoding='utf-8') as f: + for num, line in enumerate(f, 1): + line = line.strip() + if not line: + continue + + parts = line.split('|') + + if len(parts) != 7: + print(f'Ошибка в строке {num}: ожидается 7 полей, найдено {len(parts)}. Строка: {line[:50]}...', file=sys.stderr) + continue + + try: + transaktsiya = { + 'transaction_id': parts[0].strip(), + 'user_id': int(parts[1].strip()), + 'amount': float(parts[2].strip()), + 'category': parts[3].strip(), + 'timestamp': parts[4].strip(), + 'is_fraud': parts[5].strip().lower() == 'true', + 'card_last_digits': parts[6].strip() + } + transaktsii.append(transaktsiya) + except ValueError as e: + print(f'Ошибка в строке {num}: неверный тип данных - {e}', file=sys.stderr) + continue + + except FileNotFoundError: + print(f'Файл {filepath} не найден', file=sys.stderr) + return [] + except Exception as e: + print(f'Ошибка при чтении файла: {e}', file=sys.stderr) + return [] + + return transaktsii + + +def filtr_po_kategorii(transaktsii, kategorii): + resultat = [] + kategorii_nizhnij = [kat.lower() for kat in kategorii] + + for t in transaktsii: + if t.get('category', '').lower() in kategorii_nizhnij: + resultat.append(t) + return resultat + + +def filtr_po_summe(transaktsii, min_summa, max_summa): + otfiltrovannye = [] + for t in transaktsii: + summa = t.get('amount', 0) + if min_summa <= summa <= max_summa: + otfiltrovannye.append(t) + return otfiltrovannye + + +def filtr_moshennicheskih(transaktsii): + moshenniki = [] + for t in transaktsii: + if t.get('is_fraud') == True: + moshenniki.append(t) + + #сорт по убыванию суммы + moshenniki.sort(key=lambda x: x.get('amount', 0), reverse=True) + return moshenniki + + +def rassch_traty_po_kategoriyam(transaktsii, id_polzovatelya): + traty = {} + + for t in transaktsii: + if t.get('user_id') == id_polzovatelya and t.get('is_fraud') == False: + kat = t.get('category', 'Другое') + summa = t.get('amount', 0) + + if kat in traty: + traty[kat] += summa + else: + traty[kat] = summa + + return traty + + +def top_kategorii(transaktsii, n): + summy_kategorij = {} + + for t in transaktsii: + kat = t.get('category', 'Другое') + summa = t.get('amount', 0) + + if kat in summy_kategorij: + summy_kategorij[kat] += summa + else: + summy_kategorij[kat] = summa + + #список пар сортировк + elementy = list(summy_kategorij.items()) + elementy.sort(key=lambda x: x[1], reverse=True) + + return elementy[:n] + + +def obnaruzhit_podozritelnye(transaktsii, id_polzovatelya, porog): + traty_polzovatelya = [] + for t in transaktsii: + if t.get('user_id') == id_polzovatelya and t.get('is_fraud') == False: + traty_polzovatelya.append(t) + + if len(traty_polzovatelya) < 3: + return [] + + vsego = 0 + for t in traty_polzovatelya: + vsego += t.get('amount', 0) + srednyaya = vsego / len(traty_polzovatelya) + + porogovoe_znachenie = srednyaya * porog + podozritelnye = [] + for t in traty_polzovatelya: + if t.get('amount', 0) > porogovoe_znachenie: + podozritelnye.append(t) + + # убыван суммы + podozritelnye.sort(key=lambda x: x.get('amount', 0), reverse=True) + return podozritelnye + + +def gruppirovat_po_dnyam(transaktsii): + dni = {} + + for t in transaktsii: + + ts = t.get('timestamp', '') + if ts: + data = ts.split()[0] + else: + data = '1970-01-01' + + summa = t.get('amount', 0) + + if data not in dni: + dni[data] = { + 'total_amount': 0.0, + 'transaction_count': 0, + 'avg_amount': 0.0 + } + + dni[data]['total_amount'] += summa + dni[data]['transaction_count'] += 1 + + # среднее дня + for data in dni: + kolvo = dni[data]['transaction_count'] + if kolvo > 0: + dni[data]['avg_amount'] = dni[data]['total_amount'] / kolvo + + return dni + + +def gruppirovat_po_polzovatelyam(transaktsii): + polzovateli = {} + + for t in transaktsii: + uid = t.get('user_id') + if uid is None: + continue + + if uid not in polzovateli: + polzovateli[uid] = [] + + polzovateli[uid].append(t) + + # сорт по времени + for uid in polzovateli: + polzovateli[uid].sort(key=lambda x: x.get('timestamp', '1970-01-01 00:00:00')) + + return polzovateli + + +def sozdat_otchet(transaktsii, output_file): + try: + vsego_tranzaktsij = len(transaktsii) + vsego_summa = 0 + moshen_tranzaktsij = 0 + moshen_summa = 0 + + for t in transaktsii: + summa = t.get('amount', 0) + vsego_summa += summa + + if t.get('is_fraud'): + moshen_tranzaktsij += 1 + moshen_summa += summa + + obych_tranzaktsij = vsego_tranzaktsij - moshen_tranzaktsij + obych_summa = vsego_summa - moshen_summa + + top_kategorij = top_kategorii(transaktsii, 5) + + kolvo_po_polzovatelyam = {} + for t in transaktsii: + uid = t.get('user_id') + if uid: + kolvo_po_polzovatelyam[uid] = kolvo_po_polzovatelyam.get(uid, 0) + 1 + + top_polzovateli = sorted(kolvo_po_polzovatelyam.items(), key=lambda x: x[1], reverse=True)[:3] + + unikalnye_polzovateli = len(set([t.get('user_id') for t in transaktsii if t.get('user_id')])) + + po_dnyam = gruppirovat_po_dnyam(transaktsii) + pervye_7_dnej = dict(list(po_dnyam.items())[:7]) + + otchet = [] + otchet.append('=' * 60) + otchet.append('ФИНАНСОВЫЙ ОТЧЕТ') + otchet.append('=' * 60) + otchet.append('') + otchet.append(f'Всего транзакций: {vsego_tranzaktsij}') + otchet.append(f'Общая сумма: {vsego_summa:,.2f} руб.') + otchet.append('') + otchet.append('Обычные транзакции:') + otchet.append(f' Количество: {obych_tranzaktsij}') + otchet.append(f' Сумма: {obych_summa:,.2f} руб.') + otchet.append('') + otchet.append('Мошеннические транзакции:') + otchet.append(f' Количество: {moshen_tranzaktsij}') + otchet.append(f' Сумма: {moshen_summa:,.2f} руб.') + otchet.append('') + otchet.append('ТОП-5 КАТЕГОРИЙ ПО ТРАТАМ:') + + for i, (kat, summa) in enumerate(top_kategorij, 1): + otchet.append(f' {i}. {kat}: {summa:,.2f} руб.') + + otchet.append('') + otchet.append('ТОП-3 ПОЛЬЗОВАТЕЛЯ ПО КОЛИЧЕСТВУ ТРАНЗАКЦИЙ:') + + for i, (uid, kol) in enumerate(top_polzovateli, 1): + otchet.append(f' {i}. Пользователь {uid}: {kol} транзакций') + + otchet.append('') + otchet.append(f'Уникальных пользователей: {unikalnye_polzovateli}') + otchet.append('') + otchet.append('СТАТИСТИКА ПО ДНЯМ (первые 7 дней):') + + for data in sorted(pervye_7_dnej.keys()): + stat = pervye_7_dnej[data] + otchet.append(f' {data}:') + otchet.append(f' Сумма: {stat["total_amount"]:,.2f} руб.') + otchet.append(f' Кол-во: {stat["transaction_count"]}') + otchet.append(f' Средний чек: {stat["avg_amount"]:,.2f} руб.') + + otchet.append('') + otchet.append('=' * 60) + + # сохран + with open(output_file, 'w', encoding='utf-8') as f: + f.write('\n'.join(otchet)) + + return True + + except Exception as e: + print(f'Ошибка при сохранении отчета: {e}', file=sys.stderr) + return False + + +def main(): + print('Запуск программы анализа транзакций...') + print('-' * 50) + + transaktsii = zagruzit_tranzaktsii('data.txt') + + if not transaktsii: + print('Не удалось загрузить транзакции. Программа завершена.') + print('\nФайл data.txt должен содержать строки в формате:') + print('ID_транзакции|ID_пользователя|Сумма|Категория|Время|is_fraud|Последние_4_цифры') + print('Пример:') + print('tx001|1|1500.50|Продукты|2024-01-15 10:30:00|False|1234') + return + + print(f'Загружено транзакций: {len(transaktsii)}') + + kategorii = ['Продукты', 'Кафе', 'Транспорт'] + otfiltrovannye_po_kat = filtr_po_kategorii(transaktsii, kategorii) + print(f'После фильтрации по категориям {kategorii}: {len(otfiltrovannye_po_kat)} транзакций') + + otfiltrovannye_po_summe = filtr_po_summe(otfiltrovannye_po_kat, 500, 5000) + print(f'После фильтрации по сумме (500-5000 руб.): {len(otfiltrovannye_po_summe)} транзакций') + + moshenniki = filtr_moshennicheskih(transaktsii) + summa_moshennikov = sum(t.get('amount', 0) for t in moshenniki) + + print(f'\nМошеннических транзакций: {len(moshenniki)}') + print(f'Общая сумма мошеннических транзакций: {summa_moshennikov:,.2f} руб.') + + if moshenniki: + print('\nТоп-3 мошеннических транзакции по сумме:') + for i, t in enumerate(moshenniki[:3], 1): + print(f' {i}. ID: {t["transaction_id"]}, Сумма: {t["amount"]} руб., Категория: {t["category"]}') + + if transaktsii: + primernyj_polzovatel = transaktsii[0].get('user_id') + + raskhody = rassch_traty_po_kategoriyam(transaktsii, primernyj_polzovatel) + print(f'\nРасходы пользователя {primernyj_polzovatel} по категориям:') + if raskhody: + for kat, summa in raskhody.items(): + print(f' {kat}: {summa:,.2f} руб.') + else: + print(' Нет расходов (или все транзакции мошеннические)') + + podozritelnye = obnaruzhit_podozritelnye(transaktsii, primernyj_polzovatel, 1.5) + print(f'\nПодозрительно крупные транзакции пользователя {primernyj_polzovatel} (среднее * 1.5):') + if podozritelnye: + for t in podozritelnye: + print(f' {t["timestamp"]}: {t["amount"]} руб. - {t["category"]}') + else: + print(' Не найдено') + + print('\n' + '=' * 50) + print('АГРЕГИРОВАННАЯ СТАТИСТИКА') + print('=' * 50) + + top_kat = top_kategorii(transaktsii, 5) + print('\nТоп-5 категорий по сумме трат:') + for i, (kat, summa) in enumerate(top_kat, 1): + print(f' {i}. {kat}: {summa:,.2f} руб.') + + po_dnyam = gruppirovat_po_dnyam(transaktsii) + print('\nСтатистика за первые 3 дня:') + for i, (data, stat) in enumerate(list(po_dnyam.items())[:3]): + print(f' {data}:') + print(f' Сумма: {stat["total_amount"]:,.2f} руб.') + print(f' Кол-во: {stat["transaction_count"]}') + print(f' Средний чек: {stat["avg_amount"]:,.2f} руб.') + + polzovateli_s_tranzaktsiyami = gruppirovat_po_polzovatelyam(transaktsii) + kolvo_po_polz = [(uid, len(txs)) for uid, txs in polzovateli_s_tranzaktsiyami.items()] + kolvo_po_polz.sort(key=lambda x: x[1], reverse=True) + + print('\nТоп-5 пользователей по количеству транзакций:') + for i, (uid, kol) in enumerate(kolvo_po_polz[:5], 1): + print(f' {i}. Пользователь {uid}: {kol} транзакций') + + print('\n' + '=' * 50) + uspekh = sozdat_otchet(transaktsii, 'financial_report.txt') + + if uspekh: + print('Отчет успешно сохранен в файл financial_report.txt') + else: + print('Ошибка при сохранении отчета') + + print('\n' + '=' * 50) + print('ДОПОЛНИТЕЛЬНЫЙ АНАЛИЗ') + print('=' * 50) + + moshenniki_po_polz = defaultdict(float) + for t in moshenniki: + moshenniki_po_polz[t.get('user_id')] += t.get('amount', 0) + + if moshenniki_po_polz: + top_moshennik = max(moshenniki_po_polz.items(), key=lambda x: x[1]) + print(f'\nПользователь с максимальной суммой мошеннических транзакций:') + print(f' ID: {top_moshennik[0]}, Сумма: {top_moshennik[1]:,.2f} руб.') + + if po_dnyam: + samyy_nagruzhennyy_den = max(po_dnyam.items(), key=lambda x: x[1]['transaction_count']) + print(f'\nДень с наибольшим количеством транзакций:') + print(f' {samyy_nagruzhennyy_den[0]}: {samyy_nagruzhennyy_den[1]["transaction_count"]} транзакций') + + statistika_po_dnyam_nedeli = defaultdict(lambda: {'vsego': 0, 'kolvo': 0}) + for t in transaktsii: + ts = t.get('timestamp') + if ts: + try: + dt = datetime.strptime(ts.split()[0], '%Y-%m-%d') + den_nedeli = dt.strftime('%A') + summa = t.get('amount', 0) + statistika_po_dnyam_nedeli[den_nedeli]['vsego'] += summa + statistika_po_dnyam_nedeli[den_nedeli]['kolvo'] += 1 + except: + pass + + if statistika_po_dnyam_nedeli: + print('\nСредний чек по дням недели:') + poryadok_dnej = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] + russkie_dni = { + 'Monday': 'Понедельник', + 'Tuesday': 'Вторник', + 'Wednesday': 'Среда', + 'Thursday': 'Четверг', + 'Friday': 'Пятница', + 'Saturday': 'Суббота', + 'Sunday': 'Воскресенье' + } + + for eng_den in poryadok_dnej: + if eng_den in statistika_po_dnyam_nedeli: + stat = statistika_po_dnyam_nedeli[eng_den] + sredniy = stat['vsego'] / stat['kolvo'] if stat['kolvo'] > 0 else 0 + print(f' {russkie_dni[eng_den]}: {sredniy:,.2f} руб. ({stat["kolvo"]} транзакций)') + + print('\n' + '=' * 50) + print('Программа завершена!') + + +if __name__ == '__main__': + main() \ No newline at end of file