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()